Android平台从诞生起,就已经支持C、C++开发。众所周知,Android的SDK基于Java实现,这意味着基于AndroidSDK进行开发的第三方应用都必须使用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?
1.代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
2.可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
3.提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
4.便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
温馨提示:从Android Studio 1.3 Beta1开始,就支持了NDK。在进行配置前请先将Android Studio更新至最新版本,不低于1.3。
然后使用Android Studio内置的SDK管理器下载NDK。
或者在项目上右键打开Project Structure,切到的SDK Location页进行安装
咱们先建一个NdkJniDemo的工程,再新建JniUtils类实现native方法
public class JniUtils {
public static native String getStringFormC();
static {
//System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}
}
Build-Clean Project-Rebuild Project生成class文件,
这时候打开如下图的文件夹看是否生成了classes文件夹,没有生成请重新来过。
![](https://i-blog.csdnimg.cn/blog_migrate/81d18d3c15a0b3daabf7617229abd614.webp?x-image-process=image/format,png)
再打开Terminal输入指令
cd app/build/intermediates/classes/debug
然后再输入指令
javah -jni 包名.JniUtils
注意 这里javah -jni后面跟的是JniUtils类的全路径,如果javah报不存在之类的,是你的java环境没有配置好。
这时候打开classes/debug下面的文件发现多了一个文件
包名_JniUtils.h
然后在src/main下新建文件夹jni,把生成的.h文件复制或者剪切到jni文件夹下面去,新建一个c类随便取一个名字如jniutils,添加代码如下:
#include "com_ndkjnidemo_quan_ndkjnidemo_JniUtils.h"
/*
* Class: Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils
* Method: getStringFormC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_getStringFormC
(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env, "权兴权意-这里是来自C的string");
}
这里发现头文件#include <jni.h>
报红色,是因为咱们还没有配置ndk环境,按照开头配置即可。
![](https://i-blog.csdnimg.cn/blog_migrate/9121168792ca23cfe0feadc7340539d4.webp?x-image-process=image/format,png)
设置好了之后,发现头文件还是红色的,然后再build一下工程,就会有提示,按着提示做就行了 在gradle.properties文件末尾添加android.useDeprecatedNdk=true
就ok啦。
然后在app文件下得build.gradle ->defaultConfig括号内添加如下代码
ndk{
moduleName "NdkJniDemo" //生成的so名字
ldLibs "log", "z", "m" //添加依赖库文件,因为有log打印等
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
到了这一步重新build项目,发现已经没有变红了。接下来就是运用了,在JniUtils类里面添加如下代码(同前):
static {
System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}
然后简单调用就行了,MainActivity代码如下:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView ndk_text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ndk_text = (TextView) findViewById(R.id.ndk_text);
ndk_text.setText(JniUtils.getStringFormC());
}
}
运行结果如图:
小贴士:
1.如果build工程时遇到Error:Executionfailed for task':app:clean'. > Unable to delete file: xxx.file问题,不要慌。
说明这个文件被其他文件占用,可以把AS关掉,直接去对应的文件夹下面手动删除对应的文件,再重新打开AS就ok了。
2.遇到error: 'JNIEXPORT'does not name a type的问题,不要慌。
有#include <jni.h>即可。
小伙伴推荐了一篇文章,可以试试。
用Android Studio 运行ndk 程序
http://blog.csdn.net/cuiran/article/details/50755767
参考:
文/兔子吃过窝边草(简书作者)
Android Studio ndk-Jni开发详细入门,Aes加密demo
http://www.jianshu.com/p/d8cde65cb4f7