NativeActivity使用流程

NativeActivity.java的使用中,屏幕绘制的操作是用native代码实现(如C++),显示UI的窗口跟普通的java层app是一样的,也是一个Activity.java,就是NativeActivity.java,所以从他的onCreate方法看起:

https://www.khronos.org/registry/OpenGL-Refpages/es3/

https://www.khronos.org/registry/EGL/sdk/docs/man/

https://github.com/android/ndk-samples/blob/master/native-activity/app/src/main/cpp/main.cpp

W:\Android\LA.UM.7.6\LINUX\android\frameworks\base\core\java\android\app\NativeActivity.java
这里会去加载一个本地库libname = "main",并查找本地库中的入口函数funcname = "ANativeActivity_onCreate";当然库的名字,入口函数名字都是可以修改,修改要在androidManifest.xml中用meta-data指定,

   @Override
    protected void onCreate(Bundle savedInstanceState) {

        mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
                getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
                getAbsolutePath(getExternalFilesDir(null)),
                Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
                classLoader, classLoader.getLdLibraryPath());

}

W:Android\LA.UM.7.6\LINUX\android\frameworks\base\core\jni\android_app_NativeActivity.cpp

这里的code是一个unique_ptr指针,调用release()返回了一个普通指针,传给了java层,后续java层把这个普通指针再传回native层,转成NativeCode* code = (NativeCode*)handle;来使用。

这里是借助android ndk提供的一个静态库android_native_app_glue.c,实现一个执行模型,在不同的线程实现app自己的主事件循环。

static jlong
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
        jobject messageQueue, jstring internalDataDir, jstring obbDir,
        jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
        jbyteArray savedState, jobject classLoader, jstring libraryPath) {
    code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);

...
return (jlong)code.release();

}

W:\Android\LA.UM.7.6\LINUX\android\prebuilts\ndk\r16\sources\android\native_app_glue\android_native_app_glue.c

这里提供NativeActivity.java中需要的入口函数:JNIEXPORT
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState,
                              size_t savedStateSize)

然后新建一个线程,运行应用自己实现的android_main方法。应用在android_main中处理activity生命周期的事件处理,及input事件的处理。

JNIEXPORT
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState,
                              size_t savedStateSize) {
    LOGV("Creating: %p\n", activity);
    activity->callbacks->onDestroy = onDestroy;
    activity->callbacks->onStart = onStart;
    activity->callbacks->onResume = onResume;
    activity->callbacks->onSaveInstanceState = onSaveInstanceState;
    activity->callbacks->onPause = onPause;
    activity->callbacks->onStop = onStop;
    activity->callbacks->onConfigurationChanged = onConfigurationChanged;
    activity->callbacks->onLowMemory = onLowMemory;
    activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
    activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
    activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
    activity->callbacks->onInputQueueCreated = onInputQueueCreated;
    activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;

    activity->instance = android_app_create(activity, savedState, savedStateSize);
}

W:\Android\LA.UM.7.6\LINUX\android\prebuilts\ndk\r16\sources\android\native_app_glue\android_native_app_glue.c

// --------------------------------------------------------------------
// Native activity interaction (called from main thread)
// --------------------------------------------------------------------

static struct android_app* android_app_create(ANativeActivity* activity,
        void* savedState, size_t savedStateSize) {
    pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
}

W:\Android\LA.UM.7.6\LINUX\android\prebuilts\ndk\r16\sources\android\native_app_glue\android_native_app_glue.c

static void* android_app_entry(void* param) {
    android_main(android_app);
}

/**
 * This is the main entry point of a native application that is using
 * android_native_app_glue.  It runs in its own thread, with its own
 * event loop for receiving input events and doing other things.
 */
void android_main(struct android_app* state) {}

 

 * 1/ The application must provide a function named "android_main()" that
 *    will be called when the activity is created, in a new thread that is
 *    distinct from the activity's main thread.

在activity的oncreate被调用时,在非主线程中,会调用android_main()函数,所以应用程序需要提供一个这样的函数。

为什么是非主线程中呢?因为在

static struct android_app* android_app_create(ANativeActivity* activity,
        void* savedState, size_t savedStateSize){}

创建了新的线程android_app_entry,来执行应用程序的入口函数。

android_main(struct android_app *state)函数参数,接收一个android_app的结构体,这个结构体的构建是在android_app_create()@android_native_app_glue.c中

这个结构体中包含了一些重要对象的引用,如:ANativeActivity,这个ANativeActivity就是运行这个应用程序的实例。

往上回溯这个ANativeActivity就是loadNativeCode_native()@android_app_NativeActivity.cpp中的,std::unique_ptr code;

struct NativeCode : public ANativeActivity {

}

ANativeActivity 的定义在native_activity.h中。

android_app持有一个ALooper instance实例来监听两个重要的事情:

一个activity生命周期事件:APP_CMD_START等

一个是跟activity关联的AInputQueue的输入事件。

 

在收到事件后,返回数据会指向一个android_poll_source的结构体,然后调用结构体中的process函数处理事件,同时会往process中填充android_app->OnAppCmd,android_app->onInputEvent数据。

看事件处理的具体流程:

android_main()函数的实现类:https://github.com/android/ndk-samples/blob/master/native-activity/app/src/main/cpp/main.cpp

void android_main(struct android_app* state) {
    struct engine engine{};

    memset(&engine, 0, sizeof(engine));
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    state->onInputEvent = engine_handle_input;
    engine.app = state;
}

在android_main()中指定了activity生命周期的处理实现,及input事件的处理实现。

这样在android_native_app_glue.c中分发事件时process_cmd,process_input时,会调用到上面指定的处理实现。

 

这个开源的main.app实现的效果,默认显示的黑色的屏幕,当手指在屏幕点击时,会根据手指的坐标,除上屏幕的宽高,计算出一个颜色值,来设置屏幕刷新的颜色。

 

你可能感兴趣的:(android开发)