一、前期基础知识储备
Android NDK 是一套允许您使用 C 和 C++ 等语言,以原生代码实现部分应用功能的工具集。在开发某些类型的应用时,这有助于您重复使用以这些语言编写的代码库(C++等语言在执行速度、稳定性、安全性上有很大的优势)。
public class MyActivity extends Activity {
/**
* Native method implemented in C/C++
*/
public native void computeFoo();
}
可以在 Android Studio 2.2 或更高版本 中使用 NDK 将 C 和 C++ 代码编译到原生库中,然后使用 Android Studio 的集成编译系统 Gradle 将原生库打包到 APK 中。Java 代码随后可以通过 Java 原生接口 (JNI) 框架调用原生库中的函数。
Android Studio 编译原生库的默认编译工具是 CMake。由于很多现有项目都使用 ndk-build 编译工具包,因此 Android Studio 也支持 ndk-build。不过,如果您要创建新的原生库,则应使用 CMake。
本文主要分析NDK的方式,暂不涉及CMake的方式处理。
二、上代码,具体实现
在实际开发中,我们使用原生代码的场景常见的有两种,一是有C++原生代码编译好的so库但是没有原生代码,二是两者都有。第一种情况就不好做延伸了,因为没有原生代码所以无法做功能扩展;第二种情况是本文主要讨论的,以博主开发的应用为例,谷歌2019年8月1日起,所有发布到谷歌应用市场的应用,既要求有32位,也要求要64位,32位64位主要针对的就是原生代码提供的so库。
如上图,armeabi-v7a下存放的so库为32位,arm64-v8a下存放的是64位so库,在以前的开源项目来说,往往只有32位的,没有64位的,所以就需要自己手动创建新的64位so库。
如上图,我们现在有C++原生代码的情况下,只需要生成一份新的64位so库即可。步骤如下:
1)gradle.properties文件下加入android.useDeprecatedNdk=true;
2)app的build.gradle文件下加入三处声明;
android {
compileSdkVersion 28
defaultConfig {
... ...
... ...
ndk {
moduleName "nativefaceswap"
abiFilters 'armeabi-v7a','arm64-v8a'
}
}
sourceSets {
main {
jni.srcDirs = []
}
}
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
}
}
①第一处ndk的moduleName声明,与Android.mk文件中声明的so库名一致;同时指定过滤器,编译出指定架构的so库,本例中需要32位和64位so库,所以过滤器指明架构为armeabi-v7a和arm64-v8a。
②第二处sourecSets的声明,指明了so库放置的位置,Android Studio默认放置so库的文件夹为jniLibs,若想改为其他目录则需要在这里进行声明以更改。
③第三处externalNativeBuild的声明,指明了Android.mk文件的位置,用以编译时进行定位。
3)如果你的C++文件来自于开源项目,那么需要手动进行修改;