官方文档
API介绍:https://developer.android.com/reference/android/app/NativeActivity
官方Demo:https://github.com/android/ndk-samples/tree/master/native-activity
NativeActivity是基于Activity的页面,有Activity的全部功能。除此之外,NativeActivity通过loadNativeCode方法实现了一套自有looper事件处理逻辑。
mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
classLoader, classLoader.getLdLibraryPath());
mNativeHandle为long指针,指向C++侧对应的ANativeActivity对象,包含了messageQueue和surface等信息。messagequeue是为了处理activityfinish等消息。C++和JAVA侧通过Surface和InputQueue联系
public void surfaceCreated(SurfaceHolder holder) {
if (!mDestroyed) {
mCurSurfaceHolder = holder;
onSurfaceCreatedNative(mNativeHandle, holder.getSurface());
}
}
public void onInputQueueCreated(InputQueue queue) {
if (!mDestroyed) {
mCurInputQueue = queue;
onInputQueueCreatedNative(mNativeHandle, queue.getNativePtr());
}
}
上面的loadNativeCode最终会在C++侧创建一个子线程并且loop()起来,而且会处理主线程消息。消息分为两类:
- 生命周期以及窗口创建,inputqueue创建等消息,也叫cmd消息
- 点击事件消息,也叫input消息
使用looper.addFd()监听消息
//先监听cmd消息,looper为子线程looper,android_app为主线程传递过来的对象,msgread为主线程创建,LOOPER_ID_MAIN为主线程事件(除了点击事件),cmdPollSource表示监听回调事件
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, &android_app->cmdPollSource);
//INPUTQUEUE创建后再监听input事件,looper为子线程looper,mDispatchReadFd为主线程传递过来的对象,LOOPER_ID_INPUT为主线程下发的点击事件,inputPollSource表示监听回调事件
AInputQueue_attachLooper(android_app->inputQueue,android_app->looper, LOOPER_ID_INPUT, NULL, &android_app->inputPollSource);
inputQueue->attachLooper(l, ident, callback, data);
looper->addFd(mDispatchReadFd, LOOPER_ID_INPUT, ALOOPER_EVENT_INPUT, callback, data);
c++可以通过onAppCmd()和onInputEvent()来实现逻辑
类图:
时序图