Android實戰技巧之三十五:瞭解native activity,android實戰技巧

來源:互聯網
上載者:User

Android實戰技巧之三十五:瞭解native activity,android實戰技巧
1.native activity的意義

很多人覺得Android的Fwk提供的支援足夠好了,既然Google不推薦用Ndk開發為什麼又放寬Ndk的限制而推出可以無Java開發Android App呢?我的理解是不同的技術實現會有其適合的情境。
Ndk的適用情境官方給出三點:1.平台間的App移植 2.複用現有庫 3.對軟體效能要求較高的場合比如遊戲等。那麼native activity在十分適合遊戲領域,比如cocos-2dx對其的使用。

2.初步瞭解native activity

藉助SDK提供的NativeActivity類,我們可以建立完全的本地activity而無須編寫Java代碼。
需要注意的是,即使是無Java代碼編寫的應用仍然是跑(運行)在自己的虛擬機器中以此與其他應用隔離無不影響。你可以通過JNI的方式調用Fwk層的API,有些像sensor、輸入事件等操作可以直接調用本地介面(native interfaces)來完成(linc註:這樣才高效嘛)。

有兩種方式可以實現native activity。
1)native_activity.h
2)android_native_app_glue
由於第二種方法啟用另一個線程處理回調和輸入事件,Ndk的例子中就採用了這個實現方式。

3.Ndk內建的例子

這個程式主要示範根據sensor的檢測結果在整個螢幕上繪製不同的顏色。
AndroidManifest.xml
為了正常使用native activity,我們需要把API層級定在9及以上。

<uses-sdk android:minSdkVersion="9" />

由於我們只使用native code,將android:hasCode設為false。

<application android:label="@string/app_name" android:hasCode="false">

聲明NativeActivity類

        <activity android:name="android.app.NativeActivity"                android:label="@string/app_name"                android:configChanges="orientation|keyboardHidden">            <!-- Tell NativeActivity the name of or .so -->            <meta-data android:name="android.app.lib_name"                    android:value="native-activity" />            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>

注意meta-data中的lib_name(native-activity)要與Android.mk中LOCAL_MODULE相同。

Android.mk
強調模組名稱和源檔案如下:

LOCAL_MODULE    := native-activityLOCAL_SRC_FILES := main.c

外部庫的依賴
例子中用到了如下幾個外部庫,log、android(為NDK提供的標準Android支援API)、EGL(圖形API)以及OpenGL ES(android用的OpenGL,依賴EGL)
書寫約定為上述庫首碼為-l,如下:

LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM

注意:
實際的庫檔案名稱約定為首碼為lib,尾碼為.so。比如log庫檔案名稱實際為liblog.so。
這些庫的實際位置:

<ndk>/platforms/android-<sdk_version>/arch-<abi>/usr/lib /

比如liblog.so:

$ locate liblog.so/opt/android-ndk-r10b/platforms/android-12/arch-arm/usr/lib/liblog.so/opt/android-ndk-r10b/platforms/android-12/arch-mips/usr/lib/liblog.so/opt/android-ndk-r10b/platforms/android-12/arch-x86/usr/lib/liblog.so/opt/android-ndk-r10b/platforms/android-13/arch-arm/usr/lib/liblog.so...

靜態庫
本例用android_native_app_glue管理NativeActivity生命週期事件:

LOCAL_STATIC_LIBRARIES := android_native_app_glue

我們需要告知編譯系統去build這個static library,加上如下語句:

$(call import-module,android/native_app_glue)

原始碼
主要原始碼檔案只有一個,main.c。
引入的標頭檔對應在Android.mk中提到的,如下:

#include <EGL/egl.h>#include <GLES/gl.h>#include <android/sensor.h>#include <android/log.h>#include <android_native_app_glue>

程式的入口是android_main,通過android_native_app_glue調入並傳入一個預定義state結構來管理NativeActivity的回調。

void android_main(struct android_app* state)

結構android_app的定義參見/sources/android/native_app_glue/android_native_app_glue.h

接下來程式通過glue庫來處理事件隊列,參考如下代碼:

    struct engine engine;    // Make sure glue isn't stripped.    app_dummy();    memset(&engine, 0, sizeof(engine));    state->userData = &engine;    state->onAppCmd = engine_handle_cmd;    state->onInputEvent = engine_handle_input;    engine.app = state;

準備sensor

    // Prepare to monitor accelerometer    engine.sensorManager = ASensorManager_getInstance();    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,            ASENSOR_TYPE_ACCELEROMETER);    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,            state->looper, LOOPER_ID_USER, NULL, NULL);

處理訊息迴圈

while (1) {        // Read all pending events.        int ident;        int events;        struct android_poll_source* source;        // If not animating, we will block forever waiting for events.        // If animating, we loop until all events are read, then continue        // to draw the next frame of animation.        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL,&events,                (void**)&source)) >= 0) {            // Process this event.            if (source != NULL) {                source->process(state, source);            }            // If a sensor has data, process it now.            if (ident == LOOPER_ID_USER) {                if (engine.accelerometerSensor != NULL) {                    ASensorEvent event;                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,                            &event, 1) > 0) {                        LOGI("accelerometer: x=%f y=%f z=%f",                                event.acceleration.x, event.acceleration.y,                                event.acceleration.z);                    }                }            }        // Check if we are exiting.        if (state->destroyRequested != 0) {            engine_term_display(&engine);            return;        }    }

隊列為空白時,調用OpenGL繪製螢幕

        if (engine.animating) {            // Done with events; draw next animation frame.            engine.state.angle += .01f;            if (engine.state.angle > 1) {                engine.state.angle = 0;            }            // Drawing is throttled to the screen update rate, so there            // is no need to do timing here.            engine_draw_frame(&engine);        }

編譯
首先通過NDK編譯出so檔案,在根目錄下直接執行ndk-build即可:

$ ndk-build[armeabi-v7a] Compile thumb  : native-activity <= main.c[armeabi-v7a] Compile thumb  : android_native_app_glue <= android_native_app_glue.c[armeabi-v7a] StaticLibrary  : libandroid_native_app_glue.a[armeabi-v7a] SharedLibrary  : libnative-activity.so[armeabi-v7a] Install        : libnative-activity.so => libs/armeabi-v7a/libnative-activity.so

上述只摘錄出armeabi-v7a一個平台的編譯log,由於在Application.mk中沒有指明特定平台,編譯系統會編譯出其他armeabi、x86和mips平台的so。

然後再編譯apk
我嘗試將工程向AS中匯入,發現沒能配置好gradle編譯環境,無法編譯。
接著我就藉助ant來編譯,參考如下步驟:

$ android update project -p .Updated and renamed default.properties to project.propertiesUpdated local.propertiesNo project name specified, using Activity name 'NativeActivity'.If you wish to change it, edit the first line of build.xml.Added file ./build.xmlAdded file ./proguard-project.txt$ ant debug...[echo] Debug Package: /opt/android-ndk-r10b/samples/native-activity/bin/NativeActivity-debug.apk...BUILD SUCCESSFULTotal time: 3 seconds

最後
安裝運行吧!

adb install /opt/android-ndk-r10b/samples/native-activity/bin/NativeActivity-debug.apk

參考:
http://blog.csdn.net/lincyang/article/details/40950153

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.