9.6 配置 native 方法
9.6.1 CMakeLists.txt 文件中内容,配置生成一个 so 库add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp ) 9.6.2 build.gradle externalNativeBuild {
make { cppFlags “” //使用ctrl+鼠标点击,可以跳转到对应源码,然后setxxx这里的xxx就是我们这里写的,每个上面都有官方的demo cFlags “” arguments “” abiFilters “armeabi-v7a” } }还有externalNativeBuild { cmake { path “CMakeLists.txt” //buildStagingDirectory 指定编译输出目录} }这里配置 cmake 的参数,使用 ctrl+鼠标 点击,会跳到具体的一个代码中。这个是gradle-3.2.1-sources 里面的。我们不知道该配什么参数的时候,就可以用这个方法,跳到对应的代码里面,这个类或者父类中的属性值,有 setXXXX 的,这里 XXXXX 就是我们可以在这里配置的参数,该配置什么,gradle-3.2.1-sources 源码中,在每个 setXXXX 上面,都有一段参考,并且有简单介绍。流程分析10.1 C++的代码,使用 CMake,编译成了 libnative-lib.so 库10.2 MainActivity.java 加载 so 库
static { System.loadLibrary(“native-lib”); }这个代码会在 MainActivity 初始化时候进行加载。10.3 MainActivity.java 关联 so 库中方法public native String stringFromJNI();这里的 native 指明是个本地方法,系统在调用的时候,会从加载的 so 库中去找。默认查找一个以Java+包名+方法名的方法,这里 stringFromJNI 就会查找 so 库中的Java_hellojni_codegg_com_hellojni_MainActivity_stringFromJNI 方法。除了这种默认的方法,有时候我们使用的是三方库,内部方法没法修改,这个时候就不能使用这个默认方法了。如果是这个情况,就需要我们进行配置,指定 Java 的某个方法和 C 的哪个关联。具体新增一个 so 库中实现一个叫做 JNI_onLoad 的方法,在里面进行注册 Java中的某个方法,和 C 中的方法匹配。int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return-1; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { //注册return-1;
}
return 0; } JNI_onLoad 方法是 Java 加载一个 so 库后,系统默认让执行的一个方法。如果找不到,就不执行了。一般我们在JNI_onLoad 来注册 Java 的某个方法和 C 的哪个关联,并且可以设定使用 Java 的具体版本。
10.4 相关文档https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html 关于 JNI ,这里就是官方的文档,关于相关的配置,这里都可以找到。后续有一章节,会实战到这个,继续加油。
- JNI 执行调用流程
make { cppFlags “” //使用ctrl+鼠标点击,可以跳转到对应源码,然后setxxx这里的xxx就是我们这里写的,每个上面都有官方的demo cFlags “” arguments “” abiFilters “armeabi-v7a” } }还有externalNativeBuild { cmake { path “CMakeLists.txt” //buildStagingDirectory 指定编译输出目录} }这里配置 cmake 的参数,使用 ctrl+鼠标 点击,会跳到具体的一个代码中。这个是gradle-3.2.1-sources 里面的。我们不知道该配什么参数的时候,就可以用这个方法,跳到对应的代码里面,这个类或者父类中的属性值,有 setXXXX 的,这里 XXXXX 就是我们可以在这里配置的参数,该配置什么,gradle-3.2.1-sources 源码中,在每个 setXXXX 上面,都有一段参考,并且有简单介绍。流程分析10.1 C++的代码,使用 CMake,编译成了 libnative-lib.so 库10.2 MainActivity.java 加载 so 库
static { System.loadLibrary(“native-lib”); }这个代码会在 MainActivity 初始化时候进行加载。10.3 MainActivity.java 关联 so 库中方法public native String stringFromJNI();这里的 native 指明是个本地方法,系统在调用的时候,会从加载的 so 库中去找。默认查找一个以Java+包名+方法名的方法,这里 stringFromJNI 就会查找 so 库中的Java_hellojni_codegg_com_hellojni_MainActivity_stringFromJNI 方法。除了这种默认的方法,有时候我们使用的是三方库,内部方法没法修改,这个时候就不能使用这个默认方法了。如果是这个情况,就需要我们进行配置,指定 Java 的某个方法和 C 的哪个关联。具体新增一个 so 库中实现一个叫做 JNI_onLoad 的方法,在里面进行注册 Java中的某个方法,和 C 中的方法匹配。int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return-1; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { //注册return-1;
}
return 0; }
绘制流程(图)
市面上讲解绘制,直接上来一堆内容,我这里先忽略掉细节,我们来说下简单的绘制代表什
么。
我们自己画东西的时候,需要画笔,画板(画布),然后有各种涂料。
在安卓里面,这里画板就是 Canvas ,而画笔就是对应的各种 API。
那么接下来我们说下,这 Canvas 的简单逻辑,让你一目了然。
我们画的东西,叫做一个内存,叫做 FrameBuffer,这个有时候是双缓存。
然后我们每个 Activity 创建的时候,都会申请一个 Surface ,这个被叫做 平面,然后这个对
应到一个 Buffer,这一组由 Activity 或者是系统对话框,系统中使用 WMS.addView 添加进来
的 Buffer 组合。
依据层叠关系放置,而 SurfaceFlinger 这边会完成所谓的合并,绘制,推送到真正的屏幕
FrameBuffer,完成显示。
我来给大家发画一张图,大家大致看一下,形成印象。