Android NDK官方介绍html
The Android NDK is a toolset that lets you implement parts of your app using native-code languages such as C and C++. For certain types of apps, this can help you reuse code libraries written in those languages.java
实如今你的Android应用中调用C程序实现一些功能。那为何要在Java开发中使用C语言呢?android
代码的保护。因为apk的java层代码很容易被反编译,而C/C++库反汇难度较大。git
能够方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。github
提升程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提升应用程序的执行效率。服务器
便于移植。用C/C++写得库能够方便在其余的嵌入式平台上再次使用。
PS:资料来源app
虽然关于NDK开发的学习资料很少,Google官方并不少关于NDK开发文档,但居然NDK开发包那必然有它的意义。因此咱们有必要对NDK开发有个初步认识。这节主要搭建NDK开发环境并在应用中调用native函数方法。函数
从ndk-7后,谷歌已经改良了ndk的操做,不需用使用cygwin来交叉编译,因此这里就再也不讲cygwin的配置。所搭建的开发环境是Android Studio性能
1.在官方下载Android NDK开发包 下载地址目前最新的版本为r12b学习
2.添加java系统环境变量(若是Android Studio的terminal中没法使用javah指令的时候须要作此步操做)
变量 | 值 |
---|---|
CLASSPATH | .;%JAVA_HOME%lib; |
JAVA_HOME | X:XXJavajdk1.8.0_05 |
PATH | %JAVA_HOME%bin; |
3.新建Android工程,添加项目构建NDK本地路径
4.local.propertices中添加ndk.dir=c:\Android-ndk
5.gradle.properties文件中添加android.useDeprecatedNdk=true
1.新建类JniFunction,实现两个native方法
public class JniFunction { static public native String getJniString();//获取字符串 static public native int addNumber(int a,int b);//获取两个整数相加值 }
2.rebuild Project,在工程目录下app/intermediates/classes/debug下查找到JniFunction.class
3.在main目录下建立一个jni文件夹
4.打开Android Studio的terminal,使用cd定位在Android工程的app目录下输入
javah -d jni -classpath ..\..\build\intermediates\classes\debug com.xxxxxxx.xxx.JniFunction //切记debug和com之间有空格
5.在jni文件夹中就生成了com_learnncode_learnndk_JniFunction.h的头文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_learnncode_learnndk_JniFunction */ #ifndef _Included_com_learnncode_learnndk_JniFunction #define _Included_com_learnncode_learnndk_JniFunction #ifdef __cplusplus extern "C" { #endif /* * Class: com_learnncode_learnndk_JniFunction * Method: getJniString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_learnncode_learnndk_JniFunction_getJniString (JNIEnv *, jclass); /* * Class: com_learnncode_learnndk_JniFunction * Method: addNumber * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_learnncode_learnndk_JniFunction_addNumber (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif
6.在jni文件夹下新建C/C++ Source File,复制h头文件中定义的函数实现函数内容。须要注意的是选择新建.c文件而不是.cpp,另外记得多添加一个无用的c文件,否则编译可能会出错。
#include "com_learnncode_learnndk_JniFunction.h" /* * Class: com_learnncode_learnndk_JniFunction * Method: getJniString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_learnncode_learnndk_JniFunction_getJniString (JNIEnv * env, jclass obj){ return (*env)->NewStringUTF(env,"Hello Android NDK"); } /* * Class: com_learnncode_learnndk_JniFunction * Method: addNumber * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_learnncode_learnndk_JniFunction_addNumber (JNIEnv * env, jclass obj, jint a, jint b){ return a + b; }
7.在app build.gradle添加ndk配置
defaultConfig { applicationId "com.learnncode.learnndk" minSdkVersion 14 targetSdkVersion 24 versionCode 1 versionName "1.0" ndk{ moduleName "JniFunction" //设置库(so)文件名称 } }
8.在jni调用的地方添加如下内容
static { System.loadLibrary("JniFunction"); } //JniFunction就是build.gradle中NDK的文件名
1.so文件的生成
在app build.gradle中设置ndk生成so文件库文件名
ndk{ moduleName "JniFunction" //设置库(so)文件名称 abiFilters "armeabi","armeabi-v7a","x86" }
编译项目后在项目目录下ndk文件中就能看到生成的so文件
ABI:指应用基于哪一种指令集来进行编译,ABI总共有四种,分别是armeabi、armeabi-v7a、mips、x86,它们都是表示cpu的类型。
安卓支持三类处理器(CPU):ARM、Intel和MIPS。ARM无疑被使用得最为普遍。Intel由于普及于台式机和服务器而被人们所熟知,然而对移动行业影响力相对较小。MIPS在32位和64位嵌入式领域中历史悠久,得到了很多的成功,可目前Android的采用率在三者中最低。
2.Android studio2.2环境下目录变化
更新了Android Studio以后发现加载目录发现了变化,原来的Jni文件放置在了单独的文件目录下
Project
Android
Android项目调用.so文件方法:在src/main/目录下新建jniLibs文件夹把ndk abiFilters生成的so文件拷贝在此目录下,再在build.gradle defultConfig中配置jniLibs路径,看过其余人写的默认写的是libs好像也是可运行的,这里我仍是填上正式新建时的路径
sourceSets.main{ jniLibs.srcDirs "src/main/jniLibs" }
NDK开发环境的搭建算不上特别难,就是麻烦了些。以前看别人的教程说NDK r10b版本是比较稳定的,我使用的是r12b也能编译成功,目前看来仍是可使用的。这节先为NDK开发开一个头,其中也没详细讲解关于NDK开发的语法等内容。学习NDK的道路仍是任重而道远啊。附上google官方的NDK开发Demo实例
本节Demo项目地址