Android Studio下的JNI开发:
NDK (native develop kits )
0.环境配置
下载NDK,配置NDK的环境变量:
指定项目中的NDK的位置:
两种方法:
0-1.
File---->Project Structure—>SDK Location------>Android NDK Location
0-2.
可以在Project工程下的 local.properties中手动的添加NDK位置
ndk.dir=E\:\\SDK\\ndk-bundle (ndk的绝对路径)
sdk.dir=E\:\\SDK // 这个是SDK指定的目录
1、项目中具体的开发过程:
1.1所需要的资料:
Project下 创建jni文件(文件下包含的开发必用资料):
Android.mk(Android.mk官方文档)
---------- cut here ------------------
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
//
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
---------- cut here ------------------
APP_ABI := all
1.2 JNI开发的步骤:
java 调 C
手工操作JNI步骤:
0.创建java本地的native方法(声明本地方法,声明本地方法的关键字是native,它不用实现,实现是由底层的C实现的):
public class JniUtils {
public native int addFromC(int a,int b);
public native String testFromC();
}
1.在工程Project目录级创建 jni目录
1.1.创建.c文件并创建j与native对应的Java可以调用的方法。创建方法可以借助JDK的javah命令 生成 .h文件。
纯手工写的话注意:
#include<stdio.h>
#include<stdlib.h>
// 注意不要忘记引入jni.h文件
#include<jni.h>
//test.zh.com.auditiontest.utils
/**
注意方法名必须严格按照规范书写
方法必须接收两个参数一个是Jvm虚拟机引用 JNIEnv* ; obj代表是调用 c代码的java对象。
*/
jstring Java_test_zh_com_auditiontest_utils_JniUtils_testFromC(JNIEnv* env,jobject obj){
//jstring (*NewStringUTF)(JNIEnv*, const char*);
// JNINativeInterface (*(*env)).NewStringUTF(env,"Hello From C");
// (*env) JNIEnv
return (*env)->NewStringUTF(env,"Hello I from C");
}
借助javah指令进行生成头文件:
在Terminal下,将目录切换到项目的java目录层级下敲指令 javah 包名.类名就可以了;
javah test.com.zh.testicbclient.JniUtils.JniUtil
2.将 .c文件编译成可执行的二级制文件:
用到ndk-build.cmd命令: (要将E:\SDK\ndk-bundle ndk-build.cmd根目录配置到环境变量里面)
2.0:需要知道ndk-build.cmd是编译c二进制文件的命令,该命令的执行要在要编译的c文件的根目录中执行,在这里就在就要切换到jni目录下执行;
2.1:运行 ndk-build.cmd指令之前要先配置文档告诉ndk-build怎样去编译;这个文档就是前面提到的 Android.mk
Android.mk的配置:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
// LOCAL_MODULE : so文件的名字; LOCAL_SRC_FILES :指定要编译的c文件
LOCAL_MODULE := Hello
LOCAL_SRC_FILES := Test.c
include $(BUILD_SHARED_LIBRARY)
Terminal 下 切换到jni目录下 -------cd jni
敲如 ndk-build.cmd 之后的执行结果:
项目中多了一个文件夹:
这个地方由于.h生成的原因copy的时候要注意参数的问题,错误常常出现在这里。
3.最后一步就是加载二进制文件就可以了
关于JNI开发中碰到的错误 Android Studio下开发所遇到的及解决办法以供以后用
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/test.com.zh.myapplication-AvKdV9D0ZTIOTalhb-4KNg==/base.apk"],nativeLibraryDirectories=[/data/app/test.com.zh.myapplication-AvKdV9D0ZTIOTalhb-4KNg==/lib/arm64, /system/lib64, /system/vendor/lib64]]] couldn't find "libHello.so"
这个错是无法找到.so文件 尝试这种方法:
Android app Gradle下配置
defaultConfig {
applicationId "test.com.zh.myapplication"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
配置这个ndk没有作用:因为jni里面有对应的包 :这个要废弃了
/*
ndk {
abiFilters "armeabi", "armeabi-v7a"
}*/
// 注意这里已经手工调用ndk-bulid.cmd会生成了一个jni文件在Gradle里面没有加入配置需要配置下此目录在android{}下:
sourceSets {
main {
// gradle会到资源文件夹下libs里面找so文件
jniLibs.srcDirs = ['libs']
}
}
}
注意若已经配置该选项,仍然抛出上面的so文件找不到,我試了很多种办法,要配合app下libs下也要有该文件上图此libs为仍然抛出找不到的异常:
修改后:
ok此时一直困扰的手工操作下so文件找不到的bug完美解决:
demo地址:
https://github.com/zhao2017/testJni.git
Android JNI开发文档:
本地开发文档地址:
链接:https://pan.baidu.com/s/1Z85l2uQvOaHN5FJLoCyHWw
提取码:sht6
开发所需要的资料查看:
https://developer.android.google.cn/ndk/guides