零蚀
生成Android.so包
-
step 1
下载开发包
-
step 2
打包生成支持Android平台的.so动态库(重点)
这里如果失败,后面一路飘红,走向无尽深渊。所以要认真对待每一个步骤。而且,也许你能打包成功,有了你想要的所有文件,但是当你跑上手机,那就是另一个美丽的故事了:可能缺少libnative.so,可能nijia报错,可能你的libxxx_arm_android_xxx.so库找不到,或者直接闪退,不给报错。
开始之前你要配置下载的configure文件内容(没错就是改执行文件的操作内容)
首先找到
CMDLINE_SET
可以找到以下代码,然后新增一个命令行选项:cross_prefix_clang
。CMDLINE_SET=" $PATHS_LIST ar arch as assert_level .... cross_prefix # 新增命令行参数 cross_prefix_clang ..... "
修改编译工具路径设置,搜索
ar_default="${cross_prefix}${ar_default}"
修改cc_default
&cxx_default
原有内容
ar_default="${cross_prefix}${ar_default}" # 原始内容 cc_default="${cross_prefix}${cc_default}" # 原始内容 cxx_default="${cross_prefix}${cxx_default}" # ---------------修改内容------------------------ cc_default="${cross_prefix_clang}${cc_default}" cxx_default="${cross_prefix_clang}${cxx_default}" # ---------------------------------------------- nm_default="${cross_prefix}${nm_default}" pkg_config_default="${cross_prefix}${pkg_config_default}"
需要看一下 ./configure 看看缺少什么,(如果没有yasm/nasm下载以下工具,着主要是为了提高效率使用了汇编指令)其次./configure会补充你缺少的文件
brew install yasm
或者选择不用
// 屏蔽掉yasm ./configure --disable-x86asm
然后不能用自己的ndk可能不匹配,会有一系列的问题,每个版本的ndk改动都不一样所以,这里我一开始使用的ndk21,这里打包虽然没问题,但是后面配置运行就会无限深渊,所以,这里使用ndk-r20b,然后放在一个方便的位置(我这里将自己as的ndk也改为了20)。
在下载的文件ffmpeg根文件下创建一个build_android.sh文件。
执行 ./build_android.sh
# 将sh文件设置为all可执行 ➜ ffmpeg-4.2.2 chmod a+x build_android.sh # 运行脚本 ➜ ffmpeg-4.2.2 ./build_android.sh
build_android.sh内容
#!/bin/bash #这个配置生成的是一整套完整功能的库,没有剪裁掉功能 #cd ffmpeg-4.2.2#在ffmpeg所在路径下编译 set -x # 目标Android版本 API=21 CPU=armv7-a # 记得换成自己的路径 NDK_PATH=/Users/{client_your_name}/Desktop/ffmpeg-4.2.2/android-ndk-r20b # 编译工具链路径 TOOLCHAIN=$NDK_PATH/toolchains/llvm/prebuilt/darwin-x86_64 # 编译环境 SYSROOT=$TOOLCHAIN/sysroot #这里是写你输出文件要存放的位置 PREFIX=/Users/{client_your_name}/Desktop/ffmpeg-4.2.2/android/armeabi-v7a function configure_deal { ./configure \ --prefix=$PREFIX \ --target-os=android \ --arch=arm \ --cpu=armv7-a \ --enable-asm \ --enable-neon \ --enable-cross-compile \ --enable-shared \ --disable-static \ --disable-doc \ --disable-ffplay \ --disable-ffprobe \ --disable-symver \ --disable-ffmpeg \ --sysroot=$SYSROOT \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --cross-prefix-clang=$TOOLCHAIN/bin/armv7a-linux-androideabi$API- \ --extra-cflags="-fPIC" } function build { configure_deal make clean # 设置运行的cpu核数 make -j4 make install } build
⚠️ 如果出现以下情况,说明你打包这个流程没问题,但是不一定会产生so库,如果没有生成so库,你要想想自己的build_android.sh这个脚本是不是哪里有问题里(就像如果你脚本里少写了个function关键字,程序是不报错的,甚至能像模像样走完,且不报错,但是就没有文件生成)
运行后会根据PREFIX路径生成文件,然后就是我们导入需要的文件,到此打包环节就结束了。
Android Studio 3.5 配置
-
添加jniLibs
其实是可以将so库到添加libs中的,但是我不想多添加代码,多一步,可能多错一步,所以采用jniLibs了,如果你用libs的话需要添加如下代码:
//导入app/libs下库 sourceSets.main { jniLibs.srcDirs = ['libs'] jni.srcDirs = [] }
lib动态库介绍:
- avcodes:编码库
- avformat:封装格式处理
- avfliter:滤镜特效处理
- avdevice:设备的各种输入输出
- avutil:工具库(格式算法,加解密算法etc)
- swresample:音频采样数据格式转换
- swscale: 视屏像素格式转换
jniLibs大家清楚,最好不要在其中创建子目录,因为程序会直接根据其中的各个兼容的平台来区分so库。所以这里命名一定要是armeabi-v7a(这里目前已经不再支持armeabi)
配置CMakeList.txt
cmake_minimum_required(VERSION 3.4.1) # 支持gnu++11 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") # 1. 定义so库和头文件所在目录,方面后面使用 set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}) set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg) # 2. 添加头文件目录 include_directories(${ffmpeg_head_dir}/include) # 3. 添加ffmpeg相关的so库 add_library( avutil SHARED IMPORTED ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libavutil.so ) add_library( swresample SHARED IMPORTED ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libswresample.so ) add_library( avcodec SHARED IMPORTED ) set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libavcodec.so ) add_library( avfilter SHARED IMPORTED) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libavfilter.so ) add_library( swscale SHARED IMPORTED) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libswscale.so ) add_library( avformat SHARED IMPORTED) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libavformat.so ) add_library( avdevice SHARED IMPORTED) set_target_properties( avdevice PROPERTIES IMPORTED_LOCATION ${ffmpeg_lib_dir}/libavdevice.so ) # 查找代码中使用到的系统库 find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # 配置目标so库编译信息 add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native-lib.cpp ) # 指定编译目标库时,cmake要链接的库 target_link_libraries( # 指定目标库,native-lib 是在上面 add_library 中配置的目标库 native-lib # 4. 连接 FFmpeg 相关的库 avutil swresample avcodec avfilter swscale avformat avdevice # Links the target library to the log library # included in the NDK. ${log-lib} )
gradle添加ffmpeg的配置平台
android { ...... defaultConfig { ...... externalNativeBuild { cmake { cppFlags "" abiFilters 'armeabi-v7a' } } } ..... externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" version "3.10.2" } } }
rebuild & make project
测试
-
NDK 编写
⚠️ 在这里首先看看你的include能否搜到头文件,这里要注意的是,所有关于ffmpeg的include都要在
extern "C"{}
的作用域内,这样就可以使用,如果在作用域外,自求多福。#include <jni.h> #include <string> extern "C"{ #include "libavcodec/avcodec.h" JNIEXPORT jstring JNICALL Java_com_example_ffmpeg_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { # 获取信息 auto string = avcodec_configuration(); return env->NewStringUTF(string); } }
打印
static { System.loadLibrary("native-lib"); } public native String stringFromJNI(); ..... tv.setText(stringFromJNI());
我将所需的文件内容都已经上传,需要的自领🔗 ffmpeg4.2.2百度网盘链接] 密码:w9rm
想了解build_android.sh怎么编写,看看configure的源码,里面有关于脚本编写的所有内容。(在这种配置上,浪费一天的时间,是件血亏的事情,心里憋了一天的mmp,可不舒服了,如果我再牛逼一点<指尖宇宙>,我肯定自己做一个比这更牛逼(傻瓜式)的东西)
🔗 前言
🔗 Android NDK列表
🔗 NO.1 Android NDK 前言
🔗 NO.2 Android CMake
🔗 NO.3 JNI调用java成员
🔗 NO.4 NDK常见函数&音视频初
🔗 NO.6 FFmpeg 4.2视频转码
🔗 NO.7 SDL2.0.12 播放本地YUV视频
🔗 NO.8 音频处理
🔗 NO.9 播放音频
🔗 NO.10 FFmpeg添加水印