Android实战技巧之三十五:了解native activity
2015-06-12 17:53
351 查看
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-activity LOCAL_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.properties Updated local.properties No project name specified, using Activity name 'NativeActivity'. If you wish to change it, edit the first line of build.xml. Added file ./build.xml Added file ./proguard-project.txt $ ant debug ... [echo] Debug Package: /opt/android-ndk-r10b/samples/native-activity/bin/NativeActivity-debug.apk ... BUILD SUCCESSFUL Total time: 3 seconds
最后
安装运行吧!
adb install /opt/android-ndk-r10b/samples/native-activity/bin/NativeActivity-debug.apk
参考:
/article/1516405.html
相关文章推荐
- android 系统菜单
- 【MIG专项测试组】如何准确评测Android应用的流畅度?
- android XMl 解析神奇xstream 四: 将复杂的xml文件解析为对象
- ios、android 数据可视化图表赏析
- Android Framework基础一
- android 获取屏幕宽高最新方法
- Android View绘制流程
- Android中的布局优化方法
- Android 实践 - 2015/06/12
- android audio system好文收藏
- Android控件使用—CountDownTimer倒计时器
- 自定义ListView实现下拉刷新和分页加载(效果类似知乎)
- menu item home区域的的id
- Android控件使用—SwipeRefreshLayout实现下拉刷新
- android压力测试命令monkey详解
- Android 获得手机屏幕真实的宽高
- android XMl 解析神奇xstream 三: 把复杂对象转换成 xml
- android自定义View之(二) Custom Drawing
- Android控件使用—Viewpager做引导界面
- android,侧滑栏SlidingLayout、ViewPager实现画廊、简单用viewpager实现画廊、圆形图片、简单的跑马灯动画效果、可拖拽的弹簧式水泡动画集合