Android NDK开发目前比较流行的方式就是使用CMake,本文一个简单的hello CMake,打开NDK的门槛,我们从搭建,配置NDK环境,到输出一个aar 以及多架构的so,给任意工程调用
1. 开发环境搭建
打开Android studio 菜单键 Tools 下拉
进入菜单安装红色部分的插件
安装完毕后,重启Android studio
2. 创建主工程
注意点就是App build.gradle的配置,支持本地aar的配置,以及支持哪种so架构的目录
android {
compileSdkVersion 29
buildToolsVersion "30.0.0"
defaultConfig {
applicationId "com.immomo.ncctest"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
// 配置你的项目支持的so架构
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
}
}
// 跟Android的代码块同级别,配置libs文件夹
repositories {
flatDir {
dirs 'libs'
}
}
3. 创建CMake NDK Module,用来编写JNI代码逻辑以及生成so和打包aar
只说重点
创建Android library项目
重点是library中的gradle配置
android {
compileSdkVersion 29
buildToolsVersion "30.0.0"
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
// 这里配置cmake的信息,以及cmake编译生出的so的架构
externalNativeBuild {
cmake {
// c++ 版本信息
cppFlags '-std=c++17'
// 生成的so支持的架构模式
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86'
}
}
}
}
// 跟Android代码块同级目录
externalNativeBuild {
cmake {
// cmake文件目录,
path file('src/main/cpp/CMakeLists.txt')
// version号
version '3.10.2'
}
}
我们在Android library中建立cpp文件夹
创建名字为CMakeLists.txt的文件
在我们创建的CMakeLists文件中配置如下信息
// 对应build.gradle中的cmake版本
cmake_minimum_required(VERSION 3.10.2)
// 你当前创建的Android lib的名称
project("mylibrary")
// 设置library信息
add_library(
// 编译生成的so的名字,默认前面会自动添加lib前缀(libtest-lib)
test-lib
// 可以分享
SHARED
// ndk c++实现代码,我们需要在cmakelist同目录创建这个名字的.cpp文件
test-lib.cpp )
find_library(
log-lib
log )
target_link_libraries(
// 编译生成的so的名字
test-lib
${log-lib} )
在cpp目录创建test-lib.cpp文件
紧接着我们创建我们要写在so中的代码逻辑,这里我简单的打印一个字符串展示
我们直接new c++file 会帮我们生成.h 和.cpp
.h文件就一个简单的声明
#ifndef NCCTEST_MYTEST_H
#define NCCTEST_MYTEST_H
extern char *libAdd(char *data);
#endif //NCCTEST_MYTEST_H
.cpp文件如下
#include "MyTest.h"
char *libAdd(char *data) {
return data;
}
然后就是我们JNI 提供给java调用的部分
#include <jni.h>
#include <string>
#include "MyTest.h"
extern "C" {
JNIEXPORT jstring JNICALL
// 这里分三部分阅读
//1.固定写法Java_ (Java层调用的)
//2.com_test_mylibrary_MyTest_(java层调用类的包名+类名)
//3.libAdd(java层的方法名字,需要和c++名字一致)
Java_com_test_mylibrary_MyTest_libAdd(
JNIEnv *env,
jobject jobject1, jchar data) {
std::string hello = "Hello CMake!";
return env->NewStringUTF(hello.c_str());
}
}
然后我们在刚才声明的目录中创建我们的JNI接口方法类,用于调用
object MyTest {
// c++层的方法名
external fun libAdd(data: Char): String?
// 加载我们的cmake生成的so文件,记得try-catch
init {
try {
System.loadLibrary("test-lib")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
3. 一个简单的哈喽CMkake就写完了,就差最后一哆嗦了.
我们执行build,(就是菜单栏那个绿色的小锤子按钮,如果还不知道我给你截个图哈哈哈)
或者你也可以在gradle菜单执行build
会在编译目录生成我们提供的AAR以及对应的so文件
copy出来给主工程使用吧
下面是我们生成的so文件,他来了
注意他的目录在cmake目录,
然后我们返回主工程,在lib是中把so文件copy进去
然后在build.gradle中
添加我们本地aar的依赖
我们在主工程中的activity中显示这个字符串,
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 这里我们在一个text上面设置so中获取的字符串
findViewById<TextView>(R.id.sample_text).text = MyTest.libAdd('c')
}
}
最终结果如下
卧槽,为啥so代码写的是hello cmake,这里显示的是什么玩意…
以为博客是后写的,编译生成的so我没有替换,只改了c.pp的字符串显示,不想替换打包了,将就着看吧.