Netbeans玩转ndk

1.       引言

这两天研究了下ndk开发,因为公司android播放器,后续开发需要调用底层so库,网上查了很多资料全都是eclipse,但是我用的是netbeans只好自行研究,ndk很简单,baidu一下资料很多,如果你是一个有经验的程序员,分分钟就可以搞定,编译出一个so来。

主要问题就在于如何将soapk打包到一起。

Eclipse是通过ADT插件自动完成的,也可以自己编写ant脚本,通过ant打包,这就不在本文范围内了。

1.1. 目的

让习惯netbeans的程序员,排斥eclipse的程序员能够顺利的完成他们的android开发,也让像学习ndk开发的人能够快速入门

 

1.2. 可能阅读者

VC基础,想搞android开发的开发的技术人员

使用netbeansandroid开发人员(一般也都是VC转过来的,因为VS IDENetbeansIDE风格比较相似)

2.       开发工具体系

Netbeans

本教程使用的是6.8,但不限于6.8版本(自行下载安装)

用于开发android app

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

http://www.cygwin.com/

Netbeans玩转ndk

2.1. 搭建安装环境

第2步.         下载Ndk开发包

第3步.         解压到任意位置(本例:F:\ndk)目录结构如图

Netbeans玩转ndk

第4步.         Ndk安装就完成了,该安装cygwin

第5步.         下载cygwin.zip,这个是网络安装器,下载好有900M就不打包在本教程中了

第6步.         安装cygwin,选择第一个,从网上下载安装,如图

                     Netbeans玩转ndk

第7步.         设置安装目录,如图

Netbeans玩转ndk

第8步.         设置下载到安装文件保存位置,如图

Netbeans玩转ndk

安装完成后,本地就有下载好的包,以后在别的机器重新安装时就可以选择第3项,从本地安装,选者这里设置的目录

第9步.         然后一直默认悬想,一直下一步,到如图步骤,选择一个下载站点,一般选择163速度还可以

Netbeans玩转ndk

第10步.     选择要安装的模块,只要安装Devel就够了,如图

Netbeans玩转ndk

第11步.     等待安装完成吧,大小是900M

第12步.     验证cygwin安装

n  运行安装目录下的“Cygwin.bat”,第一次运行时,它会自动创建用户信息,用户信息存放在“.\Cygwin\home”中。

n  在运行“Cygwin.bat”打开的命令行窗口输入:“cygcheck -c cygwin”命令,会打印出当前Cygwin的版本和运行状态,如果statusok的话,则cygwin运行正常。

n  分别输入:“make –v”和,“gcc –v”命令如果检测成功,会有makegcc相关版本信息打印出来。

如图

Netbeans玩转ndk

第13步.     Ndk开发环境搭建完成

第14步.     在系统环境变量中配置ndk目录(可选的操作,主要是为了方便),如图

cygwinlinux模拟环境,访问windows磁盘的方式是/cygdrive/盘符

Netbeans玩转ndk

2.2. 尝试编译一个so

直接使用附带jni例子

进入目录F:\ndk\\jni目录

Netbeans玩转ndk

编译hello-jni

Netbeans玩转ndk

编译后就会生成so文件了,这个文件就可以供android应用程序调用

Netbeans玩转ndk

 

2.3. netbeans创建的android项目中使用刚才编译出来的so本地库

第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位置如图

Netbeans玩转ndk

第5步.         Netbeans区别于eclipes的关键步骤

1)        编辑F:\ndk\calljni\nbproject\build-impl.xml文件

2)        找到name="-sign"target 也就是执行apkbuildtarget

3)        在所有指令之前,加入以下指令,执行aaptso打包进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编译脚本)。

 

Netbeans玩转ndk

 

 

第6步.         编译项目生成calljni.apk,在模拟器运行结果如图

Netbeans玩转ndk

2.4. ndk开发体系相关

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  JNIEXPORTJNICALL在提供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也可以实现通信模块,加强通信的安全性


转载于:https://my.oschina.net/u/732357/blog/106697