JNI初探
NDK产生背景
Android平台从诞生起,就已经支持C、C++开发。众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”。在Android SDK首次发布时,Google就宣称其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。
不过,Google也表示,使用原生SDK编程相比Dalvik虚拟机也有一些劣势,Android SDK文档里,找不到任何JNI方面的帮助。即使第三方应用开发者使用JNI完成了自己的C动态链接库(so)开发,但是so如何和应用程序一起打包成apk并发布?这里面也存在技术障碍。比如程序更加复杂,兼容性难以保障,无法访问Framework API,Debug难度更大等。开发者需要自行斟酌使用。
于是NDK就应运而生了。NDK全称是Native Development Kit。
NDK的发布,使“Java+C”的开发方式终于转正,成为官方支持的开发方式。NDK将是Android平台支持C开发的开端。
为什么使用NDK
- 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
- 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
- 提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
- 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
配置环境
-
下载NDK,NDK下载路径。
Windows下的是一个自解压文件,下载完成后双击运行,文件会自解压到当前目录,记住该目录地址,配置AndroidStudio时需要使用到这个地址 -
打开AndroidStudio,File -> Project Structure打开对话框,在对话框中输入NDK路径(上面的解压路径)
开启NDK之旅
1.新建JNIDemo工程,打开MainActivity.java
文件,在类内输入下面代码后,Build -> Make Project
public native String getStringFromNative();
2.在Terminal输入命令
cd app\src\main
javah -d jni -classpath C:\AndroidSdk\platforms\android-23\android.jar;..\..\build\intermediates\classes\debug com.sentu.jnidemo.MainActivity
就会发现在main目录下多了一个jni文件夹,里面有生成好的头文件
3.在jni目录下创建一个.c文件,实现头文件里声明的方法
#include "com_sentu_jnidemo_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_sentu_jnidemo_MainActivity_getStringFromNative(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "I'm comes from to Native Function!");
}
4.在 local.properties 文件中设置ndk的路径
ndk.dir=C\:\\AndroidSdk\\android-ndk-r10e
5.在MainActivity.java文件中添加如下代码
public class MainActivity extends Activity {
public native String getStringFromNative();
static {
System.loadLibrary("MyJni");
}
TextView info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
info.setText(getStringFromNative());
}
}
6.运行,查看效果
这个时候可能会出现一个问题
Error:(13, 0) Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
解决方案: 在gradle.properties
中添加android.useDeprecatedNdk=true