Android NDK : NDK开发概要
通过NDK可以做什么?
1 . 在java代码中调用C++的库
2. 创建可执行的程序 (不推荐使用NDK来做这个)
3 通过gdb来调试native 程序
由图可以看出,一个java应用是通过JNI来调用本地方法(即C / C++的函数) 。整个Application依然是运行在dalvik虚拟机上的,所以整个Application的生命周期
仍然是android的生命周期,这点并没有改变,但是推荐使用一个小型的 java wrapper 来管理整个Application的生命周期 。
什么时候需要本地方法?
在有些情况下,你可能需要使用一些本地方法(C / C++ )直接在CPU上跑 ,而不是在虚拟器上跑,此时就需要使用到本地方法。
于是NDK提供给了我们一个工具箱,可以在java应用中来编写和组织本地代码。
在android中使用本地代码的一些特性:
高复杂度的精确地计算 (比如一些复杂图形)
使用NDK提供的一些稳定的依赖库
Java与本地方法的交互应该尽可能少,比如一种理想的情况是使用java应用程序调用计算密集型的本地函数并接收结果,注意java与本地方法
不要作频繁的调用和回调 。
从Android2.3开始我们可以使用NativeActivity来开发无Java代码的android应用开发。
一些常用的API和library
使用NDK 构建 native application
从图中可以看出NDK的构建系统是为了创建C / C++ 的静态库和动态库
NDK的目录和结构
这里拿最新的NDK来说明 , NDK R10的目录结构 :
打开我们下载好的NDK R10的目录 如下 :
build目录下是一些进行构建的脚本 ,包含 makefiles awk脚本等 (稍微学过linux的应该都比较熟悉了);
docs目录下是一些文档(html) ,包括如何使用NDK,在eclipse中引入NDK等 ,绝对最好的学习文档 ;
platforms目录下是一些头文件和库
prebuilt目录下是一些对于不同平台下的预编译库
samples目录是一些示例程序,比如你常见的各种 “ hello world ”版本
sources 目录下是源码,链接到应用或库
tests目录下是一些自动化测试NDK的脚本
toolchains目录下是ARM Linux 和 x86的工具链 ( 编译,链接等 )
GNUmakefile 构建NDK的nakefile文件
ndk-build 构建脚本 ,用于构建一个本地应用或者本地库
ndk-gdb gdb调试开始的脚本
ndk-stack 栈追踪分析工具
NDK C++ support
NDK提供了一些基本的C++运行时环境通过默认的库—— /system/lib/libstdc++
使用默认的系统库,有些C++的特性是不支持的:
- C++ exceptions
- RTTI (Run-Time Time Information)
- Standard C++ library
JNI - 在java代码中调用C++ 函数
在Java代码中声明 :
public native String NDKTestFromJNI();// native声明,表示这个方法来自Native层。实现过程已经在native层实现了
C++ / C 代码 :
jstring Java_com_testdnk_testndk_MainActivity_NDKTestFromJNI(JNIEnv* env,
jobject thiz) {
return env->NewStringUTF("Hello NDK!");
}
注意格式 jstring 为返回值 ,com_testdnk_testndk为包名(即函数声明所在路径名),MainActivity为android活动类 (class名) NDKTestFromJNI为函数名。
SDK project with native code
此时我们来完成我们的第一个android NDK应用 。
首选从官方下载NDK : http://wear.techbrood.com/tools/sdk/ndk/ 选择适合自己的版本 。
打开你的eclipse ,配置 NDK的路径 ,window ——> preference
如果你的eclipse没有 NDK这一项 则请下载jar包 ,然后放在eclipse的 plugins 目录下 再重启eclipse :
jar 包下载 : http://download.csdn.net/detail/cassiepython/9572228
完成上面这些就可以正式开始我们的Hello NDK 开发了 。新建一个android项目 , 然后在工程项目上点击右键,如图:
输入名称 :
接下来在生成的TestNDK中写入下列代码 :
#include <jni.h>
#include <string.h>
extern "C" {
jstring Java_com_testdnk_testndk_MainActivity_NDKTestFromJNI(JNIEnv* env,
jobject thiz) {
return env->NewStringUTF("Hello NDK!");
}
}
然后在项目工程上右键点击 Build Project 来生成库 。
最后 Mainactivity中调用该方法,并将字符串显示在一个TextView中 :
package com.testdnk.testndk;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.testDNK);
textView.setText(NDKTestFromJNI());
}
public native String NDKTestFromJNI();// native声明,表示这个方法来自Native层。实现过程已经在native层实现了
static {
System.loadLibrary("TestNDK");// 加载库,前面的lib和后缀名不用写
}
}
运行结果 :