这两天研究了下ndk开发,由于公司android播放器,后续开发须要调用底层so库,网上查了不少资料全都是eclipse,可是我用的是netbeans只好自行研究,ndk很简单,baidu一下资料不少,若是你是一个有经验的程序员,分分钟就能够搞定,编译出一个so来。 html
主要问题就在于如何将so与apk打包到一块儿。 java
Eclipse是经过ADT插件自动完成的,也能够本身编写ant脚本,经过ant打包,这就不在本文范围内了。 linux
让习惯netbeans的程序员,排斥eclipse的程序员可以顺利的完成他们的android开发,也让像学习ndk开发的人可以快速入门 android
有VC基础,想搞android开发的开发的技术人员 c++
使用netbeans的android开发人员(通常也都是VC转过来的,由于VS IDE和NetbeansIDE风格比较类似) 程序员
Netbeans: 算法
本教程使用的是6.8,但不限于6.8版本(自行下载安装) windows
用于开发android app api
Ndk开发环境: 安全
用于开发供app调用的so本地库
Windows开发环境包含如下2个软件包
n Ndk开发包android-ndk-r8d-windows.zip
下载连接http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip
若是打不开,能够进入下载页面
http://developer.android.com/tools/sdk/ndk/index.html#download下载
n Linux模拟环境cygwin
第2步. 下载Ndk开发包
第3步. 解压到任意位置(本例:F:\ndk)目录结构如图
第4步. Ndk安装就完成了,该安装cygwin了
第5步. 下载cygwin.zip,这个是网络安装器,下载好有900多M就不打包在本教程中了
第6步. 安装cygwin,选择第一个,从网上下载安装,如图
第7步. 设置安装目录,如图
第8步. 设置下载到安装文件保存位置,如图
安装完成后,本地就有下载好的包,之后在别的机器从新安装时就能够选择第3项,从本地安装,选者这里设置的目录
第9步. 而后一直默认悬想,一直下一步,到如图步骤,选择一个下载站点,通常选择163速度还能够
第10步. 选择要安装的模块,只要安装Devel就够了,如图
第11步. 等待安装完成吧,大小是900多M
第12步. 验证cygwin安装
n 运行安装目录下的“Cygwin.bat”,第一次运行时,它会自动建立用户信息,用户信息存放在“.\Cygwin\home”中。
n 在运行“Cygwin.bat”打开的命令行窗口输入:“cygcheck -c cygwin”命令,会打印出当前Cygwin的版本和运行状态,若是status是ok的话,则cygwin运行正常。
n 分别输入:“make –v”和,“gcc –v”命令若是检测成功,会有make和gcc相关版本信息打印出来。
如图
第13步. Ndk开发环境搭建完成
第14步. 在系统环境变量中配置ndk目录(可选的操做,主要是为了方便),如图
cygwin是linux模拟环境,访问windows磁盘的方式是/cygdrive/盘符
直接使用附带jni例子
进入目录F:\ndk\\jni目录
编译hello-jni
编译后就会生成so文件了,这个文件就能够供android应用程序调用
第1步. 建立android项目calljni
第2步. 添加HelloJni类,代码以下
package com.example.hellojni;
public class HelloJni
{
/* A native method that is implemented by the
* 'hello-jni' native library, which is packaged
* with this application.
*/
public native String stringFromJNI();
/* this is used to load the 'hello-jni' library on application
* startup. The library has already been unpacked into
* /data/data/com.example.hellojni/lib/libhello-jni.so at
* installation time by the package manager.
*/
static {
System.loadLibrary("hello-jni");
}
}
第3步. 在MainActivity类中添加调用代码
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// ToDo add your GUI initialization code here
lib.stringFromJNI();
TextView tv = new TextView(this);
tv.setText( lib.stringFromJNI() );
setContentView(tv);
}
第4步. 将so文件添加到工程目录\lib\armeabi下,添加后so位置如图
第5步. Netbeans区别于eclipes的关键步骤
1) 编辑F:\ndk\calljni\nbproject\build-impl.xml文件
2) 找到name="-sign"的target, 也就是执行apkbuild的target
3) 在全部指令以前,加入如下指令,执行aapt将so打包进apk_
<exec executable="${aapt}" failonerror="true">
<arg value="a"/>
<arg value="${dist.apk}_"/>
<arg value="lib/armeabi/libhello-jni.so"/>
</exec>
若是有多个so须要打包进去,就多添加几条以上指令
这一步就是帮助netbeans的用户解决,如何把so文件打包进apk中这个难题。
你们都知道Apk就是一个zip格式的包,可是你不能直接将so文件打包进编译出来的apk中,由于apk是要签名才有效的,里面有签名文件如图中,打开查看,是经过hash算法计算出来的,因此必须在签名以前,把so文件打包进去一块儿签名,因此必须本身修改项目的编译脚本文件(其实就是ant编译脚本)。
第6步. 编译项目生成calljni.apk,在模拟器运行结果如图
1. 什么是NDK?
NDK 提供了一系列的工具,帮助开发者快速开发C/C++的动态库(so文件),经过mk 文件隔离CPU、平台、ABI 等差别,开发人员只须要简单修改mk 文件(指出“哪些文件须要编译”、“编译特性要求”等),就能够建立出so,使你能够在你的Android程序当中用Java语言(JNI)调用这些c/c++代码.
Google明确声明该API是稳定的,在后续全部版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能很是有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)
2. so文件必须使用ndk编译?
不是,能够直接在linux下编译so,可是你得确保你所使用的api是操做系统所支持,就是上面google声明中说的ndk支持的库,若是是特定平台支持的api,那可能就只有部分手机能够正常运行
3. mk文件如何编写
附件提供mk模板一分,可参考编写
4. 网上说的使用javah生成c/c++ .h文件,是否必须
不是,彻底不须要,给出java生成.h文件的指令,和先决条件
javah -classpath ./build/classes -d jni org.me.calljni.MainActivity
首先必须编译java类,无论你用任何方式,编译出来就行,生成类.class文件,
而后使用以上指令生成头文件-classpath后面的目录就是生成的class的目录
5. java代码、c代码、so方法之间的联系
n 你的应用的java源代码中要声明一个或多个方法,这些方法前面需有'native'关键字,这代表它们被本地代码实现。如:
public native String stringFromJNI();
n 你必须提供本地的共享库(.so),库中包含这些方法的实现。将这个库打包你的.apk中。这个库的命名必须符合标准的Unix命名规则,也就是:lib<something>.so这种形式,例如:
libhello-jni.so。
n 而且还要包含一个标准的JNI入口,例如:
static {
System.loadLibrary("hello-jni");
}
n c函数生命应该按照以下规则命名,以说明函数是属于哪一个java类的
java_目录_目录_方法名()例如:
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz )
以上函数,是一个java类的成员函数,这个类必须是在com\example\hellojni包下,类名必须是HelloJni
方法名必须是stringFromJNI(),没有参数
这是由于java是面向对象的语言,因此so中实现的全部全局函数应该是java的某个成员方法
n JNIEnv* env, jobject thiz
这2个参数是全部jni函数必须的,只有这2个参数的函数,表示无参数的成员函数,带有 3个参数就表示成员函数有1个参数,依次类推
n JNIEXPORT与JNICALL在提供android应用调用的so代码中不是必须的
加上兼容性更好
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,jobject thiz );
6. ndk能不能直接开发java类
不知道,未研究,有兴趣的能够深刻研究,可以实现类成员函数,已经足够
7. so中能不能调用其它 .so或.a
理论上能够,但未验证,能够自行验证,若是是so,须要将so文件一块儿打包进apk,若是是.a文件,应该不须要打包进apk
8. ndk适合开发哪些模块
如下为我的理解
n 首先ndk未提供ui以及事件处理的api,因此作android开发不可能使用纯c/c++,应用主体应该仍是android sdk使用java开发
n 其次so的反编译难度比android应用的java代码要难上不少,,因此ndk能够用于开发一些须要保密代码,防止反编译泄露机密算法逻辑等
n 观察ndk支持的库,能够看到,ndk适合作一些算法模块,提升效率,支持libc也能够实现通讯模块,增强通讯的安全性