一,概述
由于公司项目用到jni(java native interface),所以小小的研究一下,我们平时引用一些第三方sdk时,有时会用到so库,即底层调用C/C++代码,此时第三方已经封装好,展现在我们面前的是java层代码,我们只需要调用即可,下面就来一遍我们自己生成so文件.
我认为有这么几个步骤:
1,下载ndk,配置ndk环境变量
2,编写java方法代码
3,利用命令生成.h文件
4,编写.c文件
5,生成so,java层实现调用C方法
二,实现
1, 下载ndk,配置ndk环境变量
关于ndk的下载,由于我现在用的是Android Studio2.3.1,直接使用AS下载,点击,进入Android SDK,
,,这里可直接下载NDK,接下来配置ndk环境变量,类似jdk配置,可自行百度,这里不再赘述
2,编写java方法代码
直接上代码,这里建议有个专门的类管理native方法,
public class MyJniUtils {
public native String getString();
}
一般我们声明调用C的方法,都用native关键字,这里返回的是string类型
3,利用命令生成.h文件
重点来了,生成.h头文件,上述第二步代码编写完成后,Rebuild Project,这样MyJniUtils的.class文件就生成在了如下目录:
Terminal定位到debug目录,输入:javah -jni MyJniUtils所在包的包名.MyJniUtils
如下:
,至此,.h文件生成,在debug目录下,如图:
4,编写.c文件
mian目录下建立jni文件夹,将第4步生成的.h文件拷过来,新建jniTest.c文件,这里可自由取名
我们看到.h文件中已经帮我们生成好了jniTest.c文件的方法名,直接拷贝,头文件引入
#include “cn_junjun_com_jnidemo_MyJniUtils.h”
jniTest.c具体代码:
#include “cn_junjun_com_jnidemo_MyJniUtils.h”
JNIEXPORT jstring JNICALL Java_cn_junjun_com_jnidemo_MyJniUtils_getString
(JNIEnv* env, jobject obj) {
return (*env)->NewStringUTF(env,”Hello from C”);
}
至此,简单的.c文件编写完成
5,生成so,java层实现调用C方法
我们最期待的来了,生成so库
build.gradle里面的defaultConfig中,添加
ndk{
moduleName “MyJni” //生成的so名字
abiFilters “armeabi”, “armeabi-v7a”, “x86” //输出指定三种abi体系结构下的so库。
}
,比以前的使用cmake方便很多,直接Rebuild Project,就会在build->intermediates->ndk->debug->lib下生成我们想要的so库啦,上图:
将生成的lib下的文件拷入项目libs文件夹或者jnilibs文件夹就可以使用了.
其中MyJniUtils加入加载so库的方法如图:
java层现在就可以调用C层的方法了,
TextView tv = (TextView) findViewById(R.id.sample_text);
MyJniUtils jni = new MyJniUtils();
tv.setText(jni.getString());
6,坑坑坑
这里说两个坑:
第一:如果无法生成so库,请在jni文件里添加一个空的util.c,至于为什么,我也不知道,应该是一个bug
第二:我在生成so过程中出现如下错误:
Error:(115) * Android NDK: Aborting . Stop.
Error:Execution failed for task ‘:app:compileDebugNdk’.
> com.android.ide.common.process.ProcessException: Error while executing process D:\huangwenjun\soft\sdk\ndk-bundle\ndk-build.cmd with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=D:\huangwenjun\workspace\MydemoWorkspace\JniDemo\app\build\intermediates\ndk\debug\Android.mk APP_PLATFORM=android-25 NDK_OUT=D:\huangwenjun\workspace\MydemoWorkspace\JniDemo\app\build\intermediates\ndk\debug\obj NDK_LIBS_OUT=D:\huangwenjun\workspace\MydemoWorkspace\JniDemo\app\build\intermediates\ndk\debug\lib APP_ABI=armeabi-v7a,armeabi,x86}
我把build.gradle中的compileSdkVersion和targetSdkVersion都改成24就可以了,之前是25,可能是版本的问题吧,但是用24生成so之后,再改回25,方法依然是可以调用的
至此完结
说了这么多,有不完善的地方,欢迎大家指正