安卓集成第三方so库主要步骤如下:
1、将头文件和so文件导入到AS对应的文件目录
2、配置头文件和so文件,使得AS可以使用到他们
3、编译使用他们。
ffmpeg 主要有如下文件:
一、引入第三方库
1、AS默认是将so库放在 src/main/jni 文件夹中,也有人习惯放在libs目录下,这个无所谓,但是要保证项目的so文件统一在相同目录。(这里使用 src/main/jni 目录)
2、复制 so 文件到对应的平台目录 [arm64-v8a, armeabi-v7a, x86, x86_64]
3、将 include 文件夹复制到 cpp 目录,与 CMakeLists.txt 同级。
复制完成后的目录结构如下:
二、配置头文件和so文件,使得AS可以使用到它们,主要难点就在这
涉及到的配置文件有两个 ,一个是APP的 build.gradle ,一个是 CMakeLists.txt
1、build.gradle 文件
a、设置指定的 CMakeLists.txt 的位置,如果是新建native 工程,默认是设置好的了
b、设置指定jniLibs目录
c、在 defaultConfig 中设置输入和输出的so库类型
a、设置指定的 CMakeLists.txt 的位置
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
b、设置指定jniLibs目录
sourceSets.main{
jniLibs.srcDirs=['src/main/jni']
jni.srcDirs=[]
}
c、在 defaultConfig 中设置输入和输出的so库类型(abiFilters 最好上下保持一致,可以试着设置不一样,对比 apk文件libs下so数量的差异效果)
①输入的平台必须包含输出的平台
②如果不设置输入,默认会将本地的所有so库都加载到apk.
③如果不设置输出,输出平台默认和输入平台相同
④abiFilters 如果都不设置,默认就是全平台
⑤设置了CPU平台,如果没有对应平台的文件夹编译就会报错,如果不设置,就必须每个平台的要有。
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
//输出的so库的类型
abiFilters 'armeabi-v7a'//,'arm64-v8a','x86','x86_64'
}
}
ndk {
//加载的so库的类型
abiFilters 'armeabi-v7a'//,'arm64-v8a','x86'//,'x86_64'
}
d、完整的 build.gradle 文件内容
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
defaultConfig {
applicationId "org.itzheng.wangyiplayer"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
//输出的so库
abiFilters 'armeabi-v7a'//,'arm64-v8a','x86','x86_64'
}
}
ndk {
//加载的so库的类型
abiFilters 'armeabi-v7a'//,'arm64-v8a','x86'//,'x86_64'
}
}
//要加载的so库的目录
sourceSets.main{
jniLibs.srcDirs=['src/main/jni']
jni.srcDirs=[]
}
//CMakeLists位置
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
2、CMakeLists.txt
调试输出可以使用
#添加日志打印出来
message(CMAKE_SOURCE_DIR " ${CMAKE_SOURCE_DIR}")
a、导入 头文件(头文件就是我们刚才复制的include文件夹)
#导入include相关文件
include_directories(include)
b、导入so文件
①加载jni目录下的so库
set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/../jni/${ANDROID_ABI})
#加载预编译好的so库
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${JNI_LIBS_DIR} ")
上面的代码等同于下面的代码,区别在于,上面是加载整个文件夹下所有的so,下面必须单个添加
set(JNI_LIBS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../main/jni/${ANDROID_ABI})
#加载预编译好的so库
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavcodec.so LINKER_LANGUAGE CXX)
②连接到加载到的so库,这样才可以使用
target_link_libraries(native-lib
avfilter avformat avcodec avutil swresample swscale
${log-lib} )
c、设置要编译的cpp文件
add_library(native-lib
SHARED
native-lib.cpp )
上面那个是系统自动生成的,如果我们要将当前目录下所有的*.cpp文件都一起编译的话,可以使
file(GLOB SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_library(native-lib SHARED ${SOURCE} )
d、完整的 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.4.1)
#导入include相关文件
include_directories(include)
#加载so库
set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/../jni/${ANDROID_ABI})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${JNI_LIBS_DIR} ")
#设置要编译的cpp文件
file(GLOB SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_library(native-lib SHARED ${SOURCE} )
#日志 so
find_library(log-lib log )
#连接到库
target_link_libraries(native-lib
avfilter avformat avcodec avutil swresample swscale
${log-lib} )
三、编写测试代码
在 native-lib.cpp 文件中
#include <jni.h>
#include <string>
extern "C"{
#include "include/libavcodec/avcodec.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_org_itzheng_player_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
//std::string hello = "Hello from C++";
//return env->NewStringUTF(hello.c_str());
return env->NewStringUTF(av_version_info());
}
如果能输出 ffmpeg 的版本号说明配置成功了。
资源下载:
android-ffmpeg-4.0.6.new.zip