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()方法了。

Logo

更多推荐