配置过程其实也是jni的使用过程,以后用jni开发也可以根据这个模板来出来进行导入。
通过android studio的选项创建native ,c++项目,创建后的项目结构如下:
这里ffmpeg涉及的资源文件主要是指编译产生的so文件跟头文件。根据自己项目需要兼容的cpu架构进行编译再导入。
因为android studio4.0以后,是不建议将so文件导入到jniLibs目录的,如果在build.gradle文件中指定jniLibs,容易爆so文件重复的错误。
图中两红色框起来的就是需要手动粘贴到项目中的ffmpeg文件。
现在主流机型其实主要适配arm64-v8a跟armeabi-v7a,在ndk17后,谷歌对armeabi基本处于弃用状态,所以这里的适配兼容架构就先写这两个架构。
本人使用的是android studio4.0以上的版本,运行github一些ffmpeg demo
发现还是报错,大致意思是找到了两个相同的so文件,所以这里还是建议so文件保存在libs目录下,在cmakelist.txt指定资源即可。
cmakelist其实就是项目中c/c++资源的build.gradle管理文件,是对涉及native层面的代码,so文件,头文件进行管理的。
首先需要明确这里需要做的主要是以上三种资源的配置。
jnidemo是这个模块的别名,native-lib.cpp是源文件,根据文件跟cmakelist.txt的相对位置填写,这里是同一层所以可直接写native-lib.cpp,同时也可以使用多个cpp文件,统一打包成jnidemo这个动态库。
这里相对简单,需要使用include_directories
完整语句就是
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library - > 设置需要编译的源文件跟头文件
avutil表示这个动态库的别名,shared表示输出的是动态库,另外添加关键字imported
set_target_properties -> 给别名设置so文件所在的位置
关联目标资源
target_link_libraries
如果是使用find_library形式找到的资源,需要用${} 包裹
主要是两个externalNativeBuild,分别是说明需要适配的cpu架构跟cmakelist文件所在的位置
在cppFlags中补充
abiFilters "arm64-v8a","armeabi-v7a"
来指定适配的cpu架构。
本文是基于kt开发的。
在主页面加入
external fun stringFromJNI():String
external,类似java中的native关键字,表示这个方法不是由这语言本身实现。
option + enter(mac系统)会在cpp文件中创建这个方法。
代码如下:
#include
#include
// 因为ffmpeg包含cpp文件,所以这里需要用extern "C" 包裹起来
extern "C" {
#include
#include
#include
#include
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnidemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
// return env->NewStringUTF(hello.c_str());
return env->NewStringUTF(avcodec_configuration());
}
}
因为ffmpeg本身是包含cpp文件的,所以需要在外层包裹extern “C”,导入的ffmpeg头文件也在这一步中实现。
// 测试是否成功,如果失败,先导入github上的demo文件慢慢对比,试到成功
项目代码上传到码云,对比下自己配置吧
https://gitee.com/timeshan/jni-demo
需要再次提醒,ndk高于17后的特点,以及as4.0的特点,这个jni导入资源跟编译器版本也有很大关系