NDK的全称是 Native Development Kit,NDK提供了一系列工具来帮助开发者快速开发 C/C++ 的动态库,并能自动将so和Java应用一起打包成apk。
为了搭建起ndk开发环境,花了我两天的功夫。网络上有很多文档,但是大部分都是比较旧的了,还需要在命令行下进行操作。我经过一通测试,发现使用新版本的sdk、ndk,完全不需要进行命令行操作了。
闲话少说,下面讲讲我总结的搭建过程,及我的第一个基于ndk的HelloWorld程序。
1. 确认Android开发环境
使用标准Eclipse, 安装Android的环境。例如我的android开发环境如下:
Eclipse Version: Mars.2 Release (4.5.2)
Android SDK: Android 6.0 (API level 23)
ADT Version: 23.0.4.1468518
2. 下载ndk,在eclipse中设置路径
下载ndk,解压。我的ndk版本:android-ndk-r10b。
然后打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径为刚才ndk解压路径。
3. 创建接口类
先按通常的步骤,建立一个android的helloWorld工程,验证其可运行。
在这个包下面,新建一个JniClient 类。在里面声明一个接口(后期开发,可以继续添加新的接口):
static public native String sayHello();
4. 配置Android项目的NativeSupport
右键点击项目,在Android Tools里面点击Add NativeSupport, 指定库名。注意命名库名是有限制的,不能有下划线“_”,因为下划线“_”是jni中函数名分割的标识。而我曾经用hello_world做为库名,恰好中招,掉入坑中好久爬不出来。现在我使用默认的库名“HelloWorld”,点击确认。
这样就会自动生成:HelloWorld.cpp和Android.mk。
Android.mk不需要修改。
5. 修改HelloWorld.cpp,实现接口功能
代码如下:
#include <jni.h>
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_helloworld_JniClient_sayHello(JNIEnv *env, jclass)
{
return env->NewStringUTF("Hello JNI!");
}
}
注意两点:
(1) C/C++定义的方法必须为:Java+包名+activity名+你的函数名,每个部分之间要用下划线_来连接, 而且参数也是固定的。所以定义C/C++函数的固定格式为:
Java_PackageName_ActivityName_function(JNIEnv* env, jobject obj) {…}
(2)此处的 extern “C” ,是必需的。不添加会遇到运行时崩溃。
6. 修改主程序,调用接口
原来的程序在运行时,默认的输出为“HelloWorld”。现在来修改输出,使用cpp中的返回内容。
在res->layout->activity_main.xml中, 为TextView添加id, 然后在java代码中调用, 其他不做修改。
xml中添加id:
android:id="@+id/tv_say_hello"
MainActivity.java中,动态赋值:
TextView tv_say_hello = (TextView) findViewById(R.id.tv_say_hello);
tv_say_hello.setText(JniClient.sayHello());
其次, 添加库的引用, 引用名字就是Add NativeSupport时填写的类名, 默认与项目名称相同。也可以查看Android.mk下LOCAL_MODULE对应的值。例如我的就是:
LOCAL_MODULE := HelloWorld
添加如下代码:
static {
System.loadLibrary("HelloWorld");
}
7. 进行工程编译,运行程序
若前面设置都正常,此时就能编译出libHelloWorld.so了。
在eclipse的Console里面输出信息:
[armeabi] Compile++ thumb: HelloWorld <= HelloWorld.cpp
[armeabi] StaticLibrary : libstdc++.a
[armeabi] SharedLibrary : libHelloWorld.so
[armeabi] Install : libHelloWorld.so => libs/armeabi/libHelloWorld.so
若在模拟器上运行,需要有在x86上运行的库,则需要添加Application.mk,否则不能编译其他几个平台下的.so库
Application.mk里面只有一句话:
APP_ABI := all
正常编译后,运行效果就是TextView的输出内容变为“Hello JNI!”。
8. Demo下载
代码例程可以从以下地址下载:
http://download.csdn.net/detail/lintax/9555897