网上已经有太多的有关如何配置eclipse+NDK了,本人就不再重复这些了,只是想记录下自己开始写第一个NDK程序的整个流程(保证可执行),共自己和大家分享。
首先安装一个能够支持Native代码的eclipse插件Sequoyah,然后在eclipse中的“窗口-首选项-Android”中多出来了一个“本机开发”选项,在“NDK Location”选择你的android-ndk的路径。有了Sequoyah插件进行Android Native开发就简单多了。下面根据自己的第一个Android Native程序开发过程,做一个记录。
1. 创建Android应用程序MyFirstNativeStore,过程省去。
2. 创建用来保存int和String类型的
public enum StoreType {
Integer, String
}和Store类,该类使用到Native函数,利用本地语言进行保存和读取操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
com.yemeishu.myfirstnativestore.store;
public
class
Store {
static
{
System.loadLibrary(
"MyFirstNativeStore"
);
}
public
native
int
getInteger(String pKey);
public
native
void
setInteger(String pKey,
int
pInt);
public
native
String getString(String pKey);
public
native
void
setString(String pKey, String pString);
}
|
其中在eclipse中会提示“此项目没有本机库支持”
这时候可以点开左边的提示,选择“加上本机支持”:
之后会在出现添加本机支持有关的参数名称(如NDK所在路径、生成的lib**.so文件名称等等)
添加完成之后,在项目中多了一个“jni”文件夹,该文件夹这时候多出了两个文件,如本程序中多了“MyFirstNativeStore.cpp”和“Android.mk”,有了这两个文件,我们不用自己手动编写麻烦的“Android.mk”文件了。这两个文件的含义也不用多说了。
2. 利用javah编译生成头文件,首先在eclipse中“运行-外部工具-外部工具配置”选项中配置javah工具:
3. 执行外部工具javah,执行完之后,刷新本工程,会在jni文件夹下自动生成头文件“com_yemeishu_myfirstnativestore_store_Store.h”(包名+java类名)。
4. 完成一些基本类配置之后,我们来设计android显示层,显示需要导入的store数据和读取store数据,设计界面
xml代码如下:
在StoreActivity类中 直接获取控件资源,设置两个按钮的按键事件函数onSetValue()和onGetValue。
两个函数代码如下:
5. 完成了界面设计了,java层基本完成,现在把注意力放在jni文件夹下,读取和保存Store类型的数据的Native层实现了。
5.1 在文件夹下jni由于没配置好c++编译器和NDK命令等,所以自动生成的.cpp和.h等文件出现错误,所以先进行配置,首先在工程属性中,在“C/C++ Build”下的“Tool Chain Editor”选择GCC等工具。
"C/C++ Build的Builder Settings"中配置"Build command:"直接输入ndk-build。
在“Behaviour”中设置
5.2 首先在jni文件夹下创建Store.h文件,主要创建一些保存Store类型、Store数组等枚举、结构体等信息,直接上代码(你肯定能看得懂):
这里还定义了一些操作Store类型信息的操作函数,如findEntry()查找保存在pStore链表中的Store数据,并返回StoreEntry结构数据,即数据的key、数据类型(int和string类型)和数据值。具体实现函数在jni文件夹下创建Store.c类中实现,代码如下:
5.3 完成了基本Store操作之后,现在开始完成连接java和Native桥梁的“MyFirstNativeStore.cpp”(还记得吧?),在该类中直接实现由javah外部工具生成的“com_yemeishu_myfirstnativestore_store_Store.h”的头文件定义的四个函数,“com_yemeishu_myfirstnativestore_store_Store.h”中的四个函数定义如下显示
具体实现函数代码如下
5.4 最后修改下自动生成的Android.mk文件,将Store.c也包含进去
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyFirstNativeStore
### Add all source file names to be included in lib separated by a whitespace
LOCAL_SRC_FILES := MyFirstNativeStore.c Store.c
include $(BUILD_SHARED_LIBRARY)
|
6. 编译、执行。结果省去。
利用NDK进行Android编程,主要流程为:
一、编写Android程序,创建需要利用Native编写的实现函数类(包含native关键字的函数,和static{System.loadLibrary("xxx")})。
二、利用javah外部工具生成包含Native函数的头文件(头文件名为:包名+函数名称)。
三、通过“本机开发”(eclipse插件Sequoyah)自动生成Android.mk文件和实现Native函数的.c或者.cpp文件,实现函数功能。
四、利用Android提供的“Android GCC”或者“Cygwin GCC”或者“MinGW GCC”等工具和NDK-build编译Native函数,生成lib***.so(windows下)库文件。
五、完成实现java与Native的函数调用和回调、结果返回等。
7. 最后提供源码程序:MyFirstNativeStore 和插件sequoyah(org.eclipse.sequoyah.feature.2.0.0.I20110609-0753)
1.配置好NDk编译环境(这个Google一下,:))
2.将已有C/C++代码,编译成SO文件
3.Eclipse中新建Android工程,创建一个jni目录。如下所示
4.在jni目录创建C/C++文件,里面调用步骤2函数,或者第三方SO的函数
5.创建Android.mk文件,内容为:
LOCAL_PATH := $(call my-dir)
# Link libXXX.so
include $(CLEAR_VARS)
LOCAL_MODULE :=XXX
LOCAL_SRC_FILES := libXXX.so
#LOCAL_SRC_FILES := /jni/libXXX.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := XXXAgent
LOCAL_SRC_FILES := XXXAgent.cpp
LOCAL_SHARED_LIBRARIES := XXX
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
将XXX替换为编译出的SO或者第三方SO的名字
6.将jni目录下的C/C++编译成Android通过JNI调用的SO文件,这里名字为 libXXXAgent.so
7.Android工程中使用时,首先加载一下用到的SO库,即可正常使用了。
System.loadLibrary("XXX");
System.loadLibrary("XXXAgent");
说明:这里的重点是如何调用第三方SO库,所有部分细节没有表述。比如Javah生成相关头文件,jni调用等。
补充:上面步骤可能比较多,这里举一个例子加以说明。某天,你得到一个第三SO库,名字就叫XXX。你发现里面的功能正好是你Android项目里需要的,可以拿来就用。这个消息令你高兴万分啊那是。但是,如何在Android里使用呢,XXX库里的调用约定不符合JNI规定,是不能直接来用的。哈哈,想到了,创建一个XXXAgent.so。它的调用采用JNI,然后在实现里调用第三方SO就可以了。以上就是大概的思路。
SO文件是如何自动安装到虚拟机或者手机上呢,NDK生成的SO文件会自动放到libs/armeabi目录下。而此目录下的SO文件都会自动打包到APK,安装后释放到/data/data/项目名字/lib/下。这里XXXAgent.SO文件生成libs/armeab,XXXAgent.SO依赖XXX文件,XXX文件自动拷贝到libs/armeab下。(XXX文件放在jni下,和Android.mk同级,这个是和Android.mk里的设置配合使用的)