jni涉及概念
* 交叉编译:一个平台为另一个平台编译代码。不同的操作系统windows Mac OS X linux/unix.不同的处理器架构都算不同平台,x86,arm,mips
* 工具链:一套编译的工具,编译过程中顺序调用的一套工具。
* 函数库:实现某一类功能函数的集合,其中的代码已经编译成二进制机器指令。提供库至少需要提供两个文件,.h头文件声明库中的函数,.so/.a库文件包含函数的具体实现。
* 静态链接库 .a 静态库只用在静态链接过程中,将库的二进制机器代码拷贝一份
* 动态链接库(共享库) .so 动态库先用在动态链接过程中,记录用到哪个库的哪个函数。在程序运行之前,需要先加载动态库。
* jni开发相关工具 *
NDK: Native Development kit 本地开发工具集
第一步 : 新建模块,native声明本地方法,调用本地方法
public native String helloFromC();
public void click(View v){
helloFromC();
}
第二步 : 在module的build.gradle中defaultConfig 内添加ndk
//同步报错,点击setXXX 自动添加android.useDeprecatedNdk=true
defaultConfig {
applicationId "simcpux.sourceforge.net.jnidemo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
ndk{
moduleName "ancely"//指定最终生成的库名 比好libc.so c则为生成的库名 最终生成库文件名:libhello.so
}
}
第三步 : 在调用本地方法的类中加载动态库,指定库名来加载
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("ancely");//指定库名加载动态库
}
第四步 : 模块中new一个jni Folder文件夹,默认在main目录下
右击app–>Folder–>JNIFolder–>完成用来放C文件的位置
第五步 : 在jni文件夹下新建hello.c源文件,hello.h头文件(可选)
再右击刚刚建好的 jni文件–>New–>C/C++Source Files–>
第六步 : 在hello.c源文件中按要求实现本地方法相应函数
E:\SDK\ndk-bundle\platforms\android-24\arch-arm\usr\include里面的转换数据的类型
#include "ancely.h"
#include <jni.h> //提供java和c的基本类型及引用类型对应,声明数据转换方法
/**
* 本地方法相应的函数名:Java_包名_类名_本地方法名
* 参数1 JNIEnv *env jni环境,调用转换数据方法
* 参数2 jobject obj 调用本地方法类的对象
*/
jstring Java_simcpux_sourceforge_net_jnidemo_MainActivity_helloFromC(JNIEnv *env jni,jobject obj){
char buf[] ="hello from C";
return (*env)->NewStringUTF(env,buf);
}
第七步 : gradle同步,make module
第八步 : 运行应用程序
javah生成本地方法相应函数声明
在main/java文件夹和com的同层目录中执行
D:\jni02\code\JniDemo\calc\src\main\java>javah -classpath . -d ../jni com.itheima.calc.MainActivity
jni开发过程中常见错误
找不到库: Couldn’t load ca1c: findLibrary returned null
原因:1.加载的库名不正确;2.没有生成相应平台的库找不到方法: Native method not found: com.itheima.calc.MainActivity.result_from_c
原因:1.实现的本地方法相应函数名写错;2.没有加载库