测试环境 ---- android studio 3.0
NDK环境 ---- 17.1.4828580
目的:开源博客,希望各位纠错指正,指正的位置也会标注出指正的作者,本人QQ231734881 有错误的地方请加QQ并告知谢谢。
首先假设没有NDK环境,首先第一步安装下载NDK到电脑
CMake
为编译 需要自己手动配置 ndk-build C环境变量到android studio此行为方便日后开发,如果喜欢手动编译的话可以不勾选CMake选项
LLDB
为Debug工具建议勾选方便日后维护和管理,此截图为未勾选状态。
我们注意看 SDK Tools 这个高亮标签,他的上方名为:
Android SDK Location
这个选项了吗?他就是你通过android studio下载NDK的标准下载位置,我们日后的引用是需要此目录作为支持的。(可以记下来或者到时候来看下就好,有些说什么一定要记下来的文章我觉得没有必要)
下面我们就开始介绍支持NDK的配置文件了
如果我们在MODULE配置NDK的支持的话,我们就需要在自己新建的MODULE中的
build.gradle
文件中配置NDK的启用
目录结构为
Module文件夹
|_build
|libs
|src
| .gitignore
|_bluetoothpluglibrary.iml
|_build.gradle
|_proguard-rules.pro
这目录结构中的 build.gradle就是配置NDK的主角了,这样描述有些啰嗦但相对清晰。
配置build.gradle内容如下
android {
.... //为其它配置选项---忽略并非配置中添加...
ndk {
moduleName "BluetoothJniLibrary"
ldLibs "log"
abiFilters 'armeabi','arm64-v8a','armeabi-v7a','x86','x86_64'
}
sourceSets.main{
jni.srcDirs = []
jniLibs.srcDir "src/main/libs"
}
....//为其它配置选项---忽略并非配置中添加...
}
解析:ndk
moduleName :BluetoothJniLibrary
既然是在NDK标签内关键字:moduleName那么就是NDK编译后生产出来的SO文件的名称,千万不要写成你创建Module文件夹的名称。
ldLibs “log”
故名思是会生产一个log文件
abiFilters ‘armeabi’,‘arm64-v8a’,‘armeabi-v7a’,‘x86’,‘x86_64’
这就有意思了,这个是创建支持不同CPU平台的so,也并非像传说中不创建armeabi就会报错,只要配置符合项目最低android系统的或机型CPU平台版本的就可以了。一般8.0手机都会是armCPU系统架构且为64位系统那么我们简单配置为arm64-v8a就可以了。
解析sourceSets.main
这里要说一下,sourceSet.main 在配置文件中sourceSet是可以被不全出来的,main这个子属性补全未必会有需要我们手动加上
jni.srcDirs = []
这里是系统默认的jni生产出来库的存放位置,我们可以将其清空然后根据我们自定义的地址来存放生产出来的库
jniLibs.srcDir “src/main/libs”
这个就是我们想要存放生产出来库的地址,这个地址中src为build.gradle的上级目录,后面main为同级目录
libs为main的下级目录。这个设置的目的是为了代码运行中可以寻找到依赖库的路径。
到这里我们配置文件就完成了,下面我们要配置java代码来调用生产库了
在我门src下建立一个.java文件,名字自定义
package jni;
public class JniPlug {
static{
System.loadLibrary("BluetoothJniLibrary");//加载生成so文件名称
}
public String get_Jni_Test(){
return JniTest();
}
native private String JniTest();//底层映射
}
这是我的自己建的与底层互动的中间类
分解:static{}
static{ System.loadLibrary("BluetoothJniLibrary");//加载生成so文件名称 }
其中System.loadLibrary顾名思义为系统加载支持,最为关键的就是BluetoothJniLibrary这个就是上面在
build.gradle文件中的NDK标签内关键字ModuleName的值是一致的,这个一定要注意
分解:native private String JniTest();
native private String JniTest();//底层映射
native为本地的意思,顾名思义就是被表示为JniTest函数是从本地映射上来的函数
然后我们build项目,来获取这个泪的class文件通过class文件来生成对应的.h文件
android studio 自带CMD命令窗,快捷方式为alt+F12后默认进入项目根目录
然后我们进入到生产class文件的目录
根目录(如果是在module中创建上面的类那么这里就是Module的目录,如果在项目本身创建的话就不需要该目录)\build\intermediates\classes\debug
javah -jni -d /自己想放入的目录(但是要方便自己寻找) -classpath . jni.JniPlug(切记JniPlug这个class文件在命令中是不要加.class后缀否则出错 )
这样我们就有了需要的头文件了,不过我们要将这个头文件拷贝到我们项目中的一个制定文件夹,我的文件夹在src\main\jni文件夹内为什么要建立这么一个文件夹呢?我们还需要配置Android.mk 与 Application.mk否则我们会在NDK-BUILD过程中报错。
LOCAL_PATH := $(call my-dir) //为调用当前目录
include $(CLEAR_VARS) //情况无用变量
LOCAL_MODULE := JniLibrary #JNITest //生产的库文件的名称
LOCAL_SRC_FILES := JniLibrary.cpp #这个是我们自定义的c++文件
include $(BUILD_SHARED_LIBRARY)//构建后成为共享库
APP_ABI := all //ABI 全部构建
通过alt+F12进入我们存放.h 与 Android.mk Application.mk文件的目录后,执行下面的命令
ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk
解析
ndk-build 为ndk命令方法默认不用管
NDK_PROJECT_PATH=. 这是当前目录了,因为我们切换进来了在这里生产共享库文件
NDK_APPLICATION_MK=Application.mk 我们之前建立的文件
APP_BUILD_SCRIPT=Android.mk 我们之前建立的文件
然后我们需要将生产的好库的上级目录一起拷贝到build.gradle文件中关键字 sourceSets.main设置的目录中就大功告成了
哦对了最后我们需要在android studio项目根目录中的gradle.properties文件最下方写入
android.useDeprecatedNdk=true 这个使用被弃用的NDK,为的是因为版本原因造成安装过程中出现的NDK异常
编后语:
刚刚把剩下内容补全,也是第一次书写真的是不太好组织语言,大家请多帮忙好吗?有问题请提出指正,目的是变成一个开源的博客。鸣谢各位。