Android NDK开发入门实例

写这个,目的就是记录一下我自己的NDK是怎么入门的。便于以后查看,而不会忘了又用搜索引擎一顿乱搜。然后希望能够帮助刚学的人入门。先转一段别人说的话:

“NDK全称:Native Development Kit。

1、NDK是一系列工具的集合。

* NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。

* NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

* NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

2、NDK提供了一份稳定、功能有限的API头文件声明。

Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。”

在深入理解之前,暂且就把NDK当成是一种工具,这种工具使得JAVA能够使用C/C++编译出的so包。并将此包一起打入apk包中。

下面开始正式入门:

一、开发环境搭建(以Windows平台下为例,Linux平台下类似)

1. 下载NDK压缩包,至于从哪里下载借助搜索引擎吧。

2. 解压NDK压缩包,配置环境变量。将解压的地址写入环境变量PATH中

3. 在命令提示符下输入ndk-build如果弹出如下的错误,而不是说ndk-build not found,就说明ndk环境已经安装成功了。特别提示一下,搜索引擎中会告诉一些早期的NDK版本的使用,是在命令提示符下输入build/host-setup.sh;但是NDK经过更新,这个文件已经没有了。只需要输入ndk-build就可以了。

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/home/braincol/workspace/android/android-ndk-r5/build/core/build-local.mk:85: *** Android NDK: Aborting . Stop.

4. cygwin的安装,至于如何安装,从哪里安装也去借助搜索引擎吧。在Cygwin安装过程中,可能比较慢,必须安装的项目有make和gcc;建议安装下面几个包:autoconf2.1 ,automake1.10 ,binutils ,gcc-core ,gcc4-core ,gdb ,pcre ,pcre-devel,都安装最新版本。安装完毕后,运行Cygwin,输入"make -v"和"gcc -v"来检测是否安装成功;make版本要在3.81以上。

5. 以上任务结束后,就表示基本的开发环境搭建完成了。

二、编写JAVA代码

1. 建立一个android的工程TestNDK,创建TestNDK.java文件。

TestNDK.java:


2. 必要的一些说明

表明程序开始运行的时候会加载testNDK, static区声明的代码会先于onCreate方法执行。如果程序中有多个类,而且如果TestNDK这个类不是你应用程序的入口,那么testNDK(完整的名字是lib testNDK.so)这个库会在第一次使用TestNDK这个类的时候加载。

可以看到这两个方法的声明中有 native 关键字, 这个关键字表示这两个方法是本地方法,也就是说这两个方法是通过本地代码(C/C++)实现的,在java代码中仅仅是声明。

用eclipse编译该工程,生成相应的.class文件,这步必须在下一步之前完成,因为生成.h文件需要用到相应的.class文件。暂时不考虑报错信息。

3. 生成.h文件

在C/C++文件编写之前,需要利用javah这个工具生成相应的.h文件,然后根据这个.h文件编写相应的C/C++代码。

进入到刚才建立的testNDK工程目录中,查看工程文件:AndroidManifest.xml assets bin default.properties gen res src并新建一个ndk的文件夹后就可以进行.h文件的生成了。

在工程目录下执行:javah -classpath bin -d ndk com.blueeagle.example.TestNDK

这里-classpath表示类的路径;-d ndk 表示生成的.h文件存放的目录;com.blueeagle.example.TestNDK则是完整的类名。

现在可以再ndk目录下看到多了一个.h文件:com_blueeagle_example_testNDK.h;打开后,可以看到.h的内容:

com_blueeagle_example_testNDK.h:


上面代码中的JNIEXPORT 和 JNICALL 是jni的宏,在android的jni中不需要,当然写上去也不会有错。

函数名比较长但是完全按照:java_pacakege_class_mathod 形式来命名。

也就是说:

TestNDK.java中stringTestNdk() 方法对应于 C/C++中的 Java_com_blueeagle_example_testNDK_ stringTestNdk() 方法

TestNDK.java中stringTestNdk2() 方法对应于 C/C++中的 Java_com_blueeagle_example_testNDK_ stringTestNdk2() 方法

注意下其中的注释:

Signature: ()Ljava/lang/String;

()Ljava/lang/String;

()表示函数的参数为空(这里为空是指除了JNIEnv *, jobject 这两个参数之外没有其他参数,JNIEnv*, jobject是所有jni函数必有的两个参数,分别表示jni环境和对应的java类(或对象)本身),

Ljava/lang/String; 表示函数的返回值是java的String对象。

三、编写C/C++文件

testNDK.c:


这里只是实现了Java_com_blueeagle_example_testNDK_stringTestNdk方法,而Java_com_blueeagle_example_testNDK_stringTestNdk2 方法并没有实现,因为在testNDK.java中只调用了stringTestNdk ()方法,所以stringTestNdk 2()方法没有实现也没关系,不过建议最好还是把所有java中定义的本地方法都实现了。

Java_com_blueeagle_example_testNDK_stringTestNdk 函数只是简单的返回了一个内容为 "Hello Test NDK !" 的jstring对象(对应于java中的String对象)。

testNDK.c文件就已经编写好了,这时的.h文件已经没有用了。

四、编译生成相应的库

1 首先需要编写Android.mk文件

在testNDK.c的同级目录下新建一个Android.mk的文件


这个Androd.mk文件很短,下面我们来逐行解释下:

LOCAL_PATH := $(call my-dir)

一个Android.mk 文件首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。

include $( CLEAR_VARS)

CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),
除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。

LOCAL_MODULE := testNDK

编译的目标对象,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。

注意:编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'hello-jni'的共享库模块,将会生成'libhello-jni.so'文件。

重要注意事项:

如果你把库命名为‘libtestNDK’,编译系统将不会添加任何的lib前缀,也会生成libfoo.so,这是为了支持来源于Android平台的源代码的Android.mk文件,如果你确实需要这么做的话。

LOCAL_SRC_FILES := testNDK.c

LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。

注意,默认的C++源码文件的扩展名是’.cpp’. 指定一个不同的扩展名也是可能的,只要定义LOCAL_DEFAULT_CPP_EXTENSION变量,不要忘记开始的小圆点(也就是’.cxx’,而不是’cxx’)

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY表示编译生成共享库,是编译系统提供的变量,指向一个GNU Makefile脚本,负责收集自从上次调用'include $(CLEAR_VARS)'以来,定义在LOCAL_XXX变量中的所有信息,并且决定编译什么,如何正确地去做。还有 BUILD_STATIC_LIBRARY变量表示生成静态库:lib$(LOCAL_MODULE).a, BUILD_EXECUTABLE 表示生成可执行文件。

2 其次进行编译

进入到工程根目录,输入ndk-build即可生成相应的库libs/armeabi/testNDK.so

五、在eclipse重新编译HelloJni工程,生成apk

重新编译testNDK工程,将so包打入工程apk包,即可看到结果。在模拟器上显示Hello Test NDK!

希望能够给后来的人提供帮助!

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. [置顶] 那些你应该知道却不一定知道的——View坐标分析汇总
  6. 第二篇:实现uni-app和原生(Android)以及H5项目混编
  7. Android(安卓)小项目之--Mini音乐播放器
  8. Mac Android(安卓)studio NDK 开发
  9. android轻量级开源缓存框架——ASimpleCache(ACache)源码分析(封装

随机推荐

  1. Android开发视频教程
  2. android系统编译的网站
  3. Android SQLite数据库实例
  4. Android Library项目注意事项
  5. android SD 卡写操作
  6. Android 银行卡手机号带空格格式
  7. Android gallery与BaseaDapter的使用
  8. Android(安卓)输入法遮挡问题
  9. Android 启动时间优化
  10. kotlin开发Android入门篇一