Android实战技巧之三十五:了解native activity

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。

=”false”>

声明NativeActivity类

==>=>

注意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

注意: 实际的库文件名约定为前缀为lib,,后缀为.so。比如log库文件名实际为liblog.so。 这些库的实际位置:

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

比如liblog.so:

$ locate liblog.so/opt/android/arch-arm/usr/lib/liblog.so/opt/android/arch-mips/usr/lib/liblog.so/opt/android/arch-x86/usr/lib/liblog.so/opt/android/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中提到的,如下:

程序的入口是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 accelerometerengine.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;((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;}}得意时应善待他人,因为你失意时会需要他们

Android实战技巧之三十五:了解native activity

相关文章:

你感兴趣的文章:

标签云: