##前言 上篇经过一个简单的例子大概阐述了jni开发的基本流程,最后也编译出了本身的so文件,本篇主要介绍怎么引入第三方的so文件并进行调用java
零基础带你吃掉JNI全家桶(一)bash
经过上篇咱们知道,从Java层要调用native层的方法,要么是静态注册,要么是动态注册,可是无论是哪种,两个方法之间必须须要创建必定的通道关系,静态注册须要对应好方法名,动态注册须要对两个方法进行绑定,都是须要知道包名的,可是问题来了,那么如何在个人项目中调用第三方so中的方法呢?本身的项目包名都是不同的,实际上有两种方式:app
上面第一种方法就不说了,通常直接调用sdk便可,咱们直接看第二种,大概分为如下几个步骤:ide
咱们就使用上篇例子生成出来的so,咱们来调用下,从build中把so拷出来,位置以下,这里咱们用arm架构就好了,一个是64位的,一个是32位的 post
而后放到咱们新建的一个项目中,这里把so名字重命名下,防止混淆 gradle
而后咱们须要在build.gradle中指定so文件目录ui
sourceSets {
main {
jni.srcDirs = []
jniLibs.srcDirs = ['src\\main\\jniLibs']
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
复制代码
而后,由于自己本身是不须要生成so库的,因此CMakeLists.txt中的native-lib能够删掉,咱们加入要引入的so库,并与之关联this
#定义cmake支持的最小版本号
cmake_minimum_required(VERSION 3.4.1)
#加入lib2库 ,定义为导入形式
add_library(lib2 SHARED IMPORTED)
#关联lib2库为咱们要导入进来的libdata.so文件,ANDROID_ABI会根据自身cpu架构选择so文件
set_target_properties( lib2
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libdata.so)
# 从系统里查找依赖库,可添加多个
find_library( # 例如查找系统中的log库liblog.so
log-lib
# liblog.so库指定的名称即为log,如同上面指定生成的libnative-lib.so库名称为native-lib同样
log )
复制代码
这样CMakeLists文件在执行的时候就会把libdata.so文件加载进来。spa
最后一步,编写本地方法,新建一个类
package com.example.taolin.jni_project;
public class NativeHelper {
static {
System.loadLibrary("data");
}
public static native String stringFromJNI();
public static native int add(int a,int b);
}
复制代码
主要包名,要和so中的一直的,也是上篇文章中的动态注册代码,这里粘贴部分
//动态注册
jint registerMethod(JNIEnv *env) {
jclass clz = env->FindClass("com/example/taolin/jni_project/NativeHelper");
if (clz == NULL) {
LOGD("con't find class: com/example/taolin/jni_project/NativeHelper");
}
JNINativeMethod jniNativeMethod[] = {{"stringFromJNI", "()Ljava/lang/String;", (void *) backStringToJava},
{"add", "(II)I", (void *) addNum},};
return env->RegisterNatives(clz, jniNativeMethod,
sizeof(jniNativeMethod) / sizeof(jniNativeMethod[0]));
}
复制代码
这样的话,就在调用的时候,就能够找到对应的类,将Java层方法和Native层方法进行关联起来,进行通讯
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(NativeHelper.stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
}
复制代码
具体图我就不截了,也是能成功显示出字符串的,这样就调用了外部so的方法,大功告成!
这里只是最简单的,从native层返回一个字符串,比较浅显局限,下篇将接着介绍下,Jni的语法,以及java层和native间更为复杂的交互过程,对象怎么传输?,native层怎么操做java层的类?等等。
有新的想法和疑问的老哥能够留言一块儿讨论哦,溜了溜了~