文章转自:[Android ]JNI 入门踩坑
很久以前玩了一下NDK的编译,那时候还是Eclipse时代。
现在都换成Android studio时代,当然就要换新工具啦。
普通的配置的方法,太多文章做基础配置的介绍了,我这里就不重复介绍。
史上最详细Android Studio + NDK范例说一下踩坑当中遇到的问题吧。
(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的打印方法。其参数和等级很容易在方法中辨认。
(6)库引用相关
倘若xxx.c文件和对应的引用的xxx.h文件放到同一个文件夹里面
(7)Android生命周期产生的问题。
Java调用c的,需要jni提供接口就可以调用了。
c调用java的情况,一般是需要c使用反射的方法,创建相关对象和方法,然后填入方法参数调用的。
但是有个问题,因为Android的Activity和Fragment,Service等,其拥有生命周期的特殊性,我们无法直接反射生成一些需要持有上下文context的方法。那我们需要如何处理呢?
这里需要表明一下,我们每个JNI的方法都有两个变量
JNIEnv是上下文,jobject是调用这个方法的对象
暂时踩坑情况就到这里。
***2017.3.15*****
群内有同学反映有其他问题,如果使用高版本的Android SDK编译后,如果切换到低版本的SDK例如(25->23)会出现崩溃的问题。
这是个开端,之后会继续深入给大家介绍JNI的内容。
敬请期待下期内容吧!!!