(十四)JNI和NDK的编程
2019-08-26 本文已影响0人
YongtaoHuang
JNI是Java Native Interface(JAVA本地接口)的缩写,为了方便Java调用C、C++等本地代码所封装的一层接口。Java的跨平台特性导致了其本地交互能力的不足,一些和操作系统相关的特性java无法完成。
NDK是Android所提供的一个工具集合,通过NDK可以在Android中更加方便的通过JNI来访问本地代码。
总之,JNI是一个协议,NDK是服务JNI的工具。
NDK的优点有:
1、增大反编译难度,提高代码安全性。
2、方便使用已有的C/C++开源库。
3、便于平台间的移植。
4、提高某些特殊情形的执行效率(不是提高Android程序的性能)
关于环境配置:
1、安装NDK
NDK环境配置.jpg
2、勾选支持C++

这样新建项目会默认生成native-lib,供我们参考改成我们想要的。
14.1-2 JNI和NDK的开发流程
书中所写的方法(Android.mk)目前已经不实用了。目前多采用CMake方式。
第一步:在Java中声明native方法
public class JNI {
static {
System.loadLibrary("native-lib");
}
/**
* 定义native方法 调用C代码对应的方法
* @return
*/
public native String sayHello();
}
第二步:实现JNI方法
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
/**
* jstring : 返回值
* Java_全类名_方法名
* JNIEnv* env : 里面有很多方法
* jobj : 谁调用了这个方法就是谁的实例
*/
jstring Java_com_ylsk_testjni_JNI_sayHello(JNIEnv* env,jobject jobj){
char* text = "I am from c";
return (*env)->NewStringUTF(env,text);
}
第三步:配置CMake和buildGradle
// CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp
src/main/cpp/Hello.c )
find_library( log-lib
log )
target_link_libraries( native-lib
${log-lib} )
build.gradle中本地编译指向上面的CMakeLists.txt
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
编译将生成.so文件:

MainActivity源代码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@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(stringFromJNI());
// pay attention 此处调用我们定义的jni
String result = new JNI().sayHello();
Log.d(TAG, "onCreate: "+"result: "+result);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
结果:
2019-10-11 15:33:21.146 30967-30967/? D/MainActivity: onCreate: result: I am from c
14.3 JNI的数据类型和类型签名
JNI基本数据类型的对应关系
JNI类型=对应=Java类型
jboolean=对应=boolean
jint=对应=int
jfloat=对应=float
JNI引用数据类型的对应关系
JNI类型=对应=Java类型
jobject=对应=Object
jstring=对应=String
jintArray=对应=int[]
类型签名
采用“L+包名+类名+;”
14.4 JNI调用Java方法的流程
JNI调用Java方法的流程是先通过类名找到类,然后再根据方法名找到方法的id,最后可以调用这个方法了。