大家好,我系苍王。
以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。
很久以前玩了一下NDK的编译,那时候还是Eclipse时代。
现在都换成Android studio时代,当然就要换新工具啦。
普通的配置的方法,太多文章做基础配置的介绍了,我这里就不重复介绍。
说一下踩坑当中遇到的问题吧。
(1)ndk的配置
ndk命令的环境配置,一开始想想觉得很简单。
但是当手写多次都有问题之后,最后还是使用复制粘贴其他环境变量的(特别是符号大小写的问题)
(2)低版本的NDK编译问题
NDK编译版本过低的时候会提示这个
网上很多资料都是在gradle.properties中添加一个Android.useDeprecatedNdk=true,
然而这样还是无法解决问题的。。。
其实这里一定要用android.useDeprecatedNdk=true(android一定要小写。)
(3)指定资源文件
网上都是指定这样的资源文件,你又理解这两个参数所表达的意思吗?
jni.srcDirs指的是需要编译的xx.c文件的地址
jniLibs.srcDir指的引用的xx.so文件的地址
如果你按上图这样填,你绝对会被坑死。。。编译出来连NDK的文件夹都不会出现。
jni.srcDirs=[]是不可行的,一定要指定好c文件的路径
对应的目录地址一定要有xx.c的文件
这样才能生成ndk的文件夹,ndk文件里面才是生成so文件,用于apk中jni的运行。
到达这里你编译app的时候,就会将so的文件放到你apk的lib文件夹里面
(4)开发中需要注意的是
类型转换,是真的要了解清楚,现在类型转换都已经比较智能了,只需要在前面加个jxxx(xxx为java数据类型)就是转换的类型了。
(5)Android studio无法调试JNI里面的代码,其断点是无效的,所以必要的时候,一定要将必要参数打log
这里提供打log封装的方法,需要引用android/log.h的库,然后用define定义__android_log_print的打印方法。其参数和等级很容易在方法中辨认。
调用起来也非常简单,只需要使用上面的方法
调试台打log
(6)库引用相关
倘若xxx.c文件和对应的引用的xxx.h文件放到同一个文件夹里面
无需在c文件里面编写include h的头文件就可以使用h中定义的方法。
(7)Android生命周期产生的问题。
Java调用c的,需要jni提供接口就可以调用了。
c调用java的情况,一般是需要c使用反射的方法,创建相关对象和方法,然后填入方法参数调用的。
但是有个问题,因为Android的Activity和Fragment,Service等,其拥有生命周期的特殊性,我们无法直接反射生成一些需要持有上下文context的方法。那我们需要如何处理呢?
这里需要表明一下,我们每个JNI的方法都有两个变量
JNIEnv是上下文,jobject是调用这个方法的对象
那么调用Activity的方法,就利用jobj这个对象来调用方法即可。这里方法调用的方法自己还是查一下(jni.h和jni接口说明文档吧)
暂时踩坑情况就到这里。
***2017.3.15*****
群内有同学反映有其他问题,如果使用高版本的Android SDK编译后,如果切换到低版本的SDK例如(25->23)会出现崩溃的问题。
这是个开端,之后会继续深入给大家介绍JNI的内容。
敬请期待下期内容吧!!!
我建立了一个关于Android架构学习的群,里面可以进一步进行组件化学习和架构思想的的交流。
群号是316556016,也可以扫码进群。我在这里期待你们的加入!!!