[置顶] Android(安卓)NDK使用分析
AndroidNDK使用分析:
在Android应用程序开发中,对于一些对性能安全要求较高的模块开发中,我们一般会使用C/C++代码来实现,或者引用一些已经实现好的C/C++库时,都需要使用JNI机制。正如上面的介绍是比较常用的,同样可以实现编写基于JNI机制访问C/C++库文件。
AndroidNDK是谷歌公司提供的开发工具集,我们可以使用它快捷得开发基于JNI机制的程序。它的几个重要的功能如下:
A、提供将C/C++源代码编译成本地库文件(编译器、连接器等)
B、提供将编译好的本地库文件插入到Android的包文件(.apk)
C、提供NDK开发相关的文档、实例及规范等
注意:
谷歌是不建议开发者使用NDK开发Android本地应用程序的,当然,这样做是可以实现的,因为Android系统的主要应用是运行在dalvik虚拟机上的Java程序,推荐多开发运行在dalvik上的程序。
NDK的功能:
如上图所示,Androidndk先编译了C/C++本地代码,并生成本地库文件,然后将其插入到Android应用程序的包当中,但调用JNI的编译本地代码的工作还需要我们来做的。
NDK安装:
在谷歌官网上下载最新的NDK包,并解压到指定的目录下,那么这个目录就作为环境变量的名字,即NDK_HOME,然后在环境变量的path中添加该NDK_HOME环境变量即可。
Cygwin安装:
在上面,我们已经安装并安装了Cygwin了,在这里简单介绍下他的作用。Cygwin主要是用来处理不同平台间的转化工作,例如Android是基于Linux的框架集,而我们常使用的系统却是windows系统,所以使用它来将库文件从windows转为基于Linux系统的。当然,如果使用的系统是Linux的话则无需这个步骤了。
既然在这里介绍了它,无可置疑会用到它的。回到上面NDK环境的配置,怎么样验证环境变量是否配置成功那?答案就是使用这个Cygwin工具。我们打开它,在里面输入ndk-build,如果没有报错而是出现这个结果的话,则说明环境变量配置成功:
哦,这里的错误是因为没设定项目的路径,这里不用理会即可。
NDK的使用步骤:
实际上,NDK的使用流程与之前介绍的《Android本地接口JNI使用分析》使用流程及内容很多都很相似,在这里,我只介绍与之前不同的一些东西,下面即为NDK的开发流程:
1、创建Java本地方法类
2、编译Java本地方法生成C/C++头文件
3、编写实现上面的C/C++实现文件
4、编译生成动态运行库(.so)
5、运行应用程序
下面,根据上面的流程来介绍下NDK的使用及注意事项。我的项目目录:
运行的效果如:
每点击按钮打印LOG日志。
创建Java本地方法:
创建Java本地方法与之前文章是相同的,只不过这里的LOG内容为”HelloNdk!”而已,代码如下:
publicclassVerifyNdkJniMethod{
static{
System.loadLibrary("hello_ndk");
}
publicstaticnativeStringhelloNdk();
}
编译Java本地方法:
和之前的文章内容相同,都是使用Javah命令来编译生成的class文件,从而生成对应的C/C++头文件,我的头文件:
/*DONOTEDITTHISFILE-itismachinegenerated*/
#include<jni.h>
/*Headerforclasscom_demo_verifyndk_jni_ndk_VerifyNdkJniMethod*/
#ifndef_Included_com_demo_verifyndk_jni_ndk_VerifyNdkJniMethod
#define_Included_com_demo_verifyndk_jni_ndk_VerifyNdkJniMethod
#ifdef__cplusplus
extern"C"{
#endif
/*
*Class:com_demo_verifyndk_jni_ndk_VerifyNdkJniMethod
*Method:helloNdk
*Signature:()Ljava/lang/String;
*/
JNIEXPORTjstringJNICALLJava_com_demo_verifyndk_1jni_ndk_VerifyNdkJniMethod_helloNdk
(JNIEnv*,jclass);
#ifdef__cplusplus
}
#endif
#endif
同样的,与之前的头文件编写方式相同,我的实现文件如下:
#include<stdio.h>
#include"VerifyNdkJniMethod.h"
JNIEXPORTjstringJNICALLJava_com_demo_verifyndk_1jni_ndk_VerifyNdkJniMethod_helloNdk
(JNIEnv*env,jclassobj)
{
return(*env)->NewStringUTF(env,"HelloNdk!");
}
编译生成动态库文件(.so):
在这里,与我们之前介绍的略有不同,我们任然需要编写Android.mk文件,我的mk文件如下(在文章的最下面会介绍下mk文件):
#指定源文件的位置
LOCAL_PATH:=$(callmy-dir)
#初始化与Make相关的环境变量
include$(CLEAR_VARS)
#库编译相关信息包括库名称、源码等
LOCAL_MODULE:=hello_ndk
LOCAL_SRC_FILES:=VerifyNdkJniMethod.c
#生成共享库
include$(BUILD_SHARED_LIBRARY)
同样需要将头文件和实现文件及mk文件放在一起,只不过这里我们必须在项目的根目录下新建一个jni目录,cd到这个目录下,使用ndk-build或是$NDK/ndk-build来编译生成动态库文件。这与之前有些不同,之前我们使用的是$NDK/ndk-build来编译,是因为之前我们没有通过NDK的方式来实现,而是借助工具Cygwin来实现生成共享库文件的(这个是成立的);而现在,我们配置了NDK的环境变量可以使用$NDK/ndk-build或是ndk-build都可以进行编译生成,不同的是使用NDK及进行编译的话,我们必须cd到项目根目录下的jni下,上面的编译命令才会生效。原因是这样的,使用NDK编译的时候,NDK自身带有编译器系统,在编译的时候,编译系统会在当前的目录下查找AndroidManifest.xml文件,若文件存在,则将当前的目录看做为Android工程目录。然后再转到jni目录下,根据Android.mk进行NDK编译。
运行应用程序:
这个过程与之前的文章《Android本地接口JNI使用分析》基本相同,我的代码如下:
publicclassVerifyNdkJniActivityextendsActivity{
privatestaticStringTAG="VerifyNdkJniActivity";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify_ndk_jni);
}
publicvoidhelloNdk(Viewv){
Stringresult=VerifyNdkJniMethod.helloNdk();
log(result);
}
privatevoidlog(Stringlog){
Log.d(TAG,log);
}
}
Android.mk文件说明:
实际上,Android.mk文件的帮助文件在<NDK_HOME>/docs/ANDROID_MK.html中(不过是英文的),下面就介绍下吧!
LOCAL_PATH:=$(param...):
这个变量是用来在开发树中查找源文件,必须在mk文件的最开始处定义,一般情况下,使用下面的这种的编写格式:
LOCAL_PATH:=$(callmy-dir)
其中的my-dir为一个宏函数,$(callmy-dir)就是用来返回一个宏函数的值,一般Android.mk文件与源文件在同一个目录下。
Include$(CLEAR_VARS):
用来初始化mk文件中LOCAL_XXX的变量,但是上面的LOCAL_PATH除外,因为Android系统会将LOCAL_XXX的变量当作全局变量,所以会先对其进行初始化。
LOCAL_MODULE:=XXX:
用来标记在mk文件中描述的每一个模块,也就是要生成的库的名称。这个名称必须唯一并且不能含有空格,编译系统会自动产生适当的前缀和后缀,比如:libhello_jni.so文件。
LOCAL_SRC_FILES:=XXX.c/.cpp:
用来将包含将要被编译进打包模块的各个资源文件。同时,这些源文件所在的位置为LOCAL_PATH所指定的目录。
Include$(BUILD_SHARED_LIBRARY):
用来使用LOCAL_PATH、LOCAL_SRC_FILES等的变量值,创建名称为lib$(LOCAL_MODULE).so的库文件。
到这里,关于NDK的一些基本的东西介绍完了,如果想要更灵活的使用NDK,那么可以参看NDK中自带的simples,仔细研究学习,其位置在:<NDK_HOME>\samples\
/**
*欢迎加入技术群:179914858
*如果有任何问题请在评论中进行讨论学习
*/
更多相关文章
- . Android內核Porting相關背景知識 转载
- Android(安卓)NDK安装及使用简介
- Android使用ttf字体库替代替图片
- Android资源管理器程序
- Android(安卓)Okhttp断点续传面试深入解析
- Android内核开发:系统启动速度优化
- 交叉编译-5:使用NDK和CMake在Linux上编译Android动态库
- Android录音并进行本地转码为MP3
- Android模拟器正确应用与安装方法