说明:本文是传统so生成方案,最新的有cmake方式,具体请参见://www.greatytc.com/p/9fe0f55fe962。
JNI(Java Native Interface | Java 本地接口)
1、下载ndk
如图所示1、2、3、4
2、配置SDK location
打开如下页面,第三步的时候点击
select default ndk
会自动识别默认路径
3、创建类
- 创建类
public class JNITest {
//创建一个 native 方法
public native static String get();
}
-
点击make project
这样就可以生成对应的class 文件
4、创建头文件
- 终端使用命令进入main目录
cd src/main
- 使用下方命令创建 .h 的头文件
javah -d jni -classpath /Users/zhangdake/AndroidStudioProjects/DemoAll/sample/build/intermediates/classes/debug com.canzhang.sample.manager.jni.JNITest
命令的简单介绍
javah:生成头文件
-d jni:当前目录下创建一个 jni 文件夹
-classpath .../debug 指定要生成头文件的字节码文件目录,即我们刚刚的 JNITest.class 的目录
com.canzhang.sample.manager.jni.JNITest 是 JNITest 文件的包名加上字节码文件的名称
注意:这个 debug 文件目录可能太长,输入麻烦,我们可以找到 debug 文件夹,右键 copy path,复制文件目录即可
- 现在我们可以看到 app/src/main 目录下有一个 jni 文件夹,里面有一个 com_canzhang_sample_manager_jni_JNITest.h 的头文件,就是我们生成的头文件,头文件命名也是按照包名加字节码名的规范,以下划线连接。
5、创建c文件
在上方生成的jni目录内创建
注意:目录不要放错,方法内的包名也不要写错
#include<jni.h>
#include<stdio.h>
//导入我们创建的头文件,注意包名要正确
#include "com_canzhang_sample_manager_jni_JNITest.h"
//注意包名不要弄错
JNIEXPORT jstring Java_com_canzhang_sample_manager_jni_JNITest_get
(JNIEnv *env, jclass jclass){
//返回一个字符串
return (*env)->NewStringUTF(env,"我来自c");
}
5、创建mk文件
同样也是在jni目录内创建
-
Android.mk
(不能随意添加注释字符,容易报错)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=JNITest
LOCAL_SRC_FILES:=test.c
include $(BUILD_SHARED_LIBRARY)
-
Application.mk
(不能随意添加注释字符,容易报错)
APP_ABI := all//全平台
示例图
6、生成so库
cd 到 app/src/main/jni 目录下,使用 ndk-build
(注意中间有个横杠,另外这里要使用这个命令,需要配置下ndk的环境变量)命令生成 so 库:
然后就可以看到这些库了
如果有乱码提示,则查看mk文件中是否配置有中文字符
如果出现警告
Android NDK: WARNING: APP_PLATFORM android-14 is higher than android:minSdkVersion 1 in F:/workspace/DemoAll/DemoAll/sample/src/main/AndroidManifest.xml. NDK binaries will *not* be comptible with devices older than android-14.
则可以在清单文件中添加
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="26"></uses-sdk>
7、使用so库
- 为了让项目能够找到我们的 so 库,在主module下的 build.gradle 文件夹的 android 下添加:
sourceSets {
main() {
jniLibs.srcDirs = ['src/main/libs']
jni.srcDirs = [] //disable automatic ndk-build call, which ignore our Android.mk
}
}
- 然后我们在 JNITest.java 中动态导入 so 库,不需要写 libJNITest,只用写 JNITest:
public class JNITest {
// 动态导入 so 库
static {
System.loadLibrary("JNITest");
}
//创建一个 native 方法
public native static String get();
}
- 使用
String s = JNITest.get()
这样获取的返回值就是 我们在c中的返回值了