最近在我的Java同事在搞Java掉C++代码的事,而我是个写安卓的,在这一块比他稍微熟悉这块一些,就打算折腾一下。然后自己写了个测试,当然代码都很简单,主要是把其中的逻辑搞清楚。
一、配置AndroidStudio
要编译和调用原生代码,需要用的组件:
1.Android原生开发套间(NDK):这套工具能在Android应用中使用C/C++代码
2.CMake:一套外部编译工具
3.LLDB:AndroidStudio用于调试原生代码的调试程序
说明:在AndroidStudio的设置界面的Android SDK->SDK Tools中添加对LLDB和CMake、NDK的支持
1.在SDK Tools中选中性需要安装的NDK包、LLDB、CMake然后点击Apply即可安装
2.在模块中配置特定版本的NDK包
在build.gradl中dedaultConfig{}内添加子属性,如下
android{
ndkVersion “major.minor.build” //如 ndkVersion “21.0.6113669”
}
3.配置CMakeLists.txt
CMakeLists说明:
cmake_minimum_required(VERSION 3.4.1) //构建本地库所需要的最小CMake版本
add_library(test-lib SHARED test-lib.cpp) //说明,这是添加新建的.cpp文件
find_library() //说明该命令是用于找到NDK库并将其路径存储为一个变量,也可以使用此变量在构 建脚本的其他部分引用 NDK 库
target_link_libraries() //说明为了让您的原生库能够调用 log 库中的函数,您需要使用 CMake 构建脚本中的target_link_libraries()命令来关联这些库
4.使用Gradle关联原生库
要添加您的原生库项目作为 Gradle 构建依赖项,您需要向 Gradle 提供 CMake 或 ndk-build 脚本文件的路径
手动配置Gradle:
在android{}内添加子属性,如下
externalNativeBuil{
cmake{
path "...." //CMakeList.txt的相对路径
version "...." //CMakeList的版本
}
}
5.对于添加预构建的原生库
如果是将库添加在libs目录则需要在build.gradle中并在android{}内添加如下路径配置
sourceSets{
main{
jniLibs.srcDirs “…” //添加的路径
}
}
如果在自己新建jniLibs目录(与java目录同级)则不需要在gradle中配置原生库的路径
6.指定ABI
在defaultConfig配置ndk.abiFilters指定需要构建并打包到原生库中的部分
在
defaultConfig{
ndk{
abiFilters "...." //如:x86,x86_64,armeabi,....等等
}
}
指定输出打的什么平台的.so 文件
二、编写C++文件,打.so包
在编写C++文件的时候,你需要先熟悉一些JNI的接口语法
这里写了一段测试代码
#include <jni.h>
#include <string>
#include <iostream>
extern "C" JNIEXPORT jstring JNICALL Java_zx_example_ndktest_MainActivity_jniTest(JNIEnv * env,jobject ){
return env->NewStringUTF("Test Hello from C++");
}
extern "C"
JNIEXPORT jstring JNICALL
Java_zx_example_ndktest_JNI_stringFromJNI(JNIEnv *env, jobject thiz) {
return env->NewStringUTF("JNI Test from C++");
}
extern "C"
JNIEXPORT jstring JNICALL
Java_zx_example_ndktest_MainActivity_jniTest2(JNIEnv *env, jobject thiz) {
// TODO: implement jniTest2()
}
然后Build一下,就可以生成.so库文件了
这就是我自己生成的.so 文件了。copy一下到另外的测试工程中,调用.so文件里面的方法
public class JNI {
static {
System.loadLibrary("native-lib");
System.loadLibrary("test-lib");
}
public native String stringFromJNI();
}
然后写native方法供java调用就可以了
注意:
这里的stringFromJNI()方法只在路径xxxx.xxx.xxx.JNI类下面。然后你的C++代码的里面的JNI方法名的路径也要和你xxxx.xxx.xxx.JNI的路径一致,不然就调不到对应的C++方法,
即在C++文件中Java_zx_example_ndktest_JNI_stringFromJNI方法路径 Java_zx_example_ndktest_JNI_指定的是Java的native方法的调用路径。这个很重要