编写so库,并在其他工程里使用。
so库是linux下的动态链接库,相当于windows下的dll。后缀一般是".so"记录下整个流程。linux下编译代码都需要一个make文件来向编译器解释说明一些内容。所以需要些两个文件,一个是Android.mk(make文件),一个是c/c++源码文件。源码文件的方法定义名称是受ndk约束的,名称是固定格式的。很长很难记,所以用到一个头文件(就是方法名)生成工具java
so库是linux下的动态链接库,相当于windows下的dll。
后缀一般是".so"
记录下整个流程。
linux下编译代码都需要一个make文件来向编译器解释说明一些内容。
所以需要些两个文件,一个是Android.mk(make文件),一个是c/c++源码文件。
源码文件的方法定义名称是受ndk约束的,名称是固定格式的。很长很难记,所以用到一个头文件(就是方法名)生成工具javah命令。这个命令参考上一篇文章。
1、新建android项目
2、在项目中新建jni文件
3、在android项目中,新建一个包,里面写一个类,这个类是你要封装调用so文件里的方法。最好单独拿出来当一个包。因为javah生成的头文件是和这个包名、类名有关系的。
4、在这个类里可以声明几个native方法。名字随便起,这只是一个和底层交互的接口名。
public class MainActivity extends Activity {
static{
System.loadLibrary("getVersion");
}
public native String getVersion();
}
5、使用javah生成头文件(见上一篇文章)
#include <jni.h>
#ifndef _Included_com_example_testso_MainActivity
#define _Included_com_example_testso_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_com_example_testso_MainActivity_getVersion
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
6、下面这个就是接口名
JNIEXPORT jstring JNICALL Java_com_example_testso_MainActivity_getVersion
(JNIEnv *, jobject)
7、以上是为了生成so做的准备工作,实际如果你知道命名规范,熟悉整个流程,完全不用这样一步一步生成。直接编写C/C++文件,和Android.mk文件就可以。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := getVersion.c
include $(BUILD_SHARED_LIBRARY)
8、然后就可以根据Android.mk里你自己定义的一个源码文件名getVersion.c,新建一个getVersion.c文件,在里面写C/C++代码。
我这里就是返回一个字符串。语法啥的自己去看吧。这里主要是流程。
#include "C:\workspace\TestSo\jni\com_example_testso_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_example_testso_MainActivity_getVersion(
JNIEnv *env, jobject jobject) {
return (*env)->NewStringUTF(env, "hello world");
}
9、最后一步就是编译,也参考上一篇文章,使用ndk-build工具编译,然后就会在当前目录下出现一个obj文件夹,一层一层点进去就可以找到一个libhello.so,这个是在Android.mk文件里定义好的名字。。注意这个so文件所在的文件夹名字,我的是armeabi,有的是armeabi-v7a,有的是x86,这都是不同平台的cpu架构。
10、很关键的一步,如何在其他项目里使用这个so文件。
再新建一个项目,在这个项目的libs文件夹下,新建armeabi,如果不熟悉,可以多建几个不同的平台,比如armeabi-v7a,x86啊等等,系统会根据自己的平台去特定的文件夹里找so库。把libhello.so放到这个armeabi目录下。
11、你需要仔细看一下那个头文件的命名,后半部分是Java_com_example_testso_MainActivity_getVersion,包含了包名和类名,这个时候如果你想用这个so库,你引入这个库的方法,和方法所在包的名字必须和这个一样。以此为例,就是你写
static{
System.loadLibrary("getVersion");
}
public native String getVersion();
这段话的所在类名字必须是MainActivity,MainActivity所在的包名必须是com.example.testso,必须一样,否则会报错:native method not found异常。尽管你可能其他步骤都正确。
然后就可以使用这个getVersion()方法了。
更多推荐
所有评论(0)