NDK全称是native develop tools,用来交叉编译C/C++代码生成so动态链接库文件。交叉编译指的是在一个平台编译出另一个平台可以执行的代码。比如在操作系统为window、CPU架构为X86的平台编译出可以在操作系统为linux、cpu架构为arm的平台上执行的代码。
这里我们写第一个例子,这个例子很简单,就是用C写一句话,java层调用。写这个例子时,eclipse并没有配置ndk路径。只是把ndk下载解压配置了环境变量。因为我们要手写。
private native String helloFromC();
#include
// 注意方法命名为:Java_包名_类名_方法名, 必须要有如下两个参数
jsting Java_com_example_ndkdemo_MainActivity_helloFromC(JNIEnv* env,jobject thiz ){
// 把C中的字符串转换为JAVA中的字符串
return (*env)->NewStringUTF(env, "hello fromc..");
}
这里值得注意的是,包名指的是android工程的包名,类名指的是刚才我们写的那个本地方法所在类的类名,方法名要跟我们那个本地方法名一样。参数一:jni环境,二级指针。参数二:本地方法所在类对象。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello # 编译出来的库的名称
LOCAL_SRC_FILES := Hello.c # 要编译的源文件
include $(BUILD_SHARED_LIBRARY)
APP_ABI := armeabi armeabi-v7a x86
static{
System.loadLibrary("hello");
}
经过一系列繁琐的步骤,终于完成了艰难的NDK第一个例子,但是以我们上面那个步骤,明显有点复杂,因为很多文件都是我们手动创建出来的,而且C中的方法也是我们自己写,但是它的定义有点麻烦,什么Java_包名_类名…..如果能工具生成的话,是不是很爽….当然,这肯定是可以实现的….
private native String helloFromC();
private native int add(int x,int y);
Android项目右键 --> Android tools --> add native support...
#include
JNIEXPORT jstring JNICALL Java_com_example_ndkdemo2_MainActivity_helloFromC
(JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env, "hello from c..");
}
JNIEXPORT jint JNICALL Java_com_example_ndkdemo2_MainActivity_add
(JNIEnv * env, jobject obj, jint i, jint j){
return i+j;
}
Android ndk项目右键 --> properties --> c/c++ general(需要安装了cdt才能看到此项) -->
paths and symbols --> includes 页中点击 add --> file system 再选择路径(这个路径是你解压的android-ndk-r9的下面\platforms\android-18\arch-x86\usr\include的路径,参考如下):
F:\Android_Tools\android_ndk_r9\android-ndk-r9\platforms\android-18\arch-x86\usr\include
static{
System.loadLibrary("gxh");//so名字按具体情况修改
}
setContentView(R.layout.activity_main);
TextView tv01=(TextView) findViewById(R.id.tv_01);
tv01.setText(helloFromC()+"-------"+add(3,7));
上面写了那么多,都是在eclipse里,下面介绍下在Android Studio中的用法,废话不多说,上步骤!!!慢着!!!还是有话要说的…今天在Android Studio中新建项目写例子时,报了两个错误,以我蹩脚的英文水平没看明白,百度了半天也没什么资料参考….最后偶然看到某网站一段视频说如果编译版本过高的话,相应的NDK版本也要升高。猛然醒悟,我的编译版本是23,而NDK版本是r9,于是一气之下去网上下载了最新的r14b….不过好像r10应该就可以了。。。大家注意更新一下NDK版本吧。。ps:浪费这么多时间,已哭晕在厕所…
Build-->Make Projet
static {
System.loadLibrary("hello");//so库
}
public native String helloFromC();
用 javah命令生成jni目录以及.h文件(其实想得到C函数)
打开Terminal,默认已经进入该项目的目录了,但是我们要进入java目录,命令如下,其中第二行命令-d ../jni表示在本目录的上一级(也就是main目录)新建jni目录。执行完命令后,main/jni下会生成.h文件
在jni下写.c源文件
在jni目录下新建hello.c文件,把.h文件中的方法复制过来修改,删除.h文件。网传说是不能只有一个.c文件,,于是我又添加了一个空的.c文件。至于一个.c文件行不行,没有测试。
#include
JNIEXPORT jstring JNICALL Java_cn_gxh_ndkdemo_MainActivity_helloFromC(JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env, "hello from c..,this is android studio");
}
配置build.gradle(module下的)
moduleName 后面的值是要生成的so库名,要跟那个 System.loadLibrary(“hello”);这里对应起来啊。abiFilters表示要生成哪些cpu架构平台的so包。
gradle.properties中添加代码,表示允许使用过时的ndk版本
android.useDeprecatedNdk=true
到这里,这篇NDK入门篇终于写完了。。如有错误,欢迎指正。