编译系统环境
win10 自带Ubuntu 子系统(linux)
执行如下命令安装 一些工具
apt-get install yasm
apt-get install nasm
apt-get install pkg-config
ndk版本 r20b
下载 android-ndk-r20b-linux-x86_64.zip
# 1 执行scp命令 将下载下来的ndk 文件复制到 linux 子系统中 比如我安装再子系统的/usr/bin位置
scp -r [/mnt/ndk路径] [要放在linux子系统中的位置]
# 2 执行unzip 来解压 ndkzip
unzip android-ndk-r20b-windows-x86_64.zip
# 3 配置 ndk路径 执行如下命令
vim /etc/profile # 打开配置文件 按i 进入编辑模式
# 4 在文件最后配置path处 添加ndk配置 按ESC 输入:WQ 保存并退出
export NDK=/usr/bin/android-ndk-r20b
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$NDK:$PATH
# 5 执行如下命令 立即 更新配置
source /etc/profile
可选最新ndk版本 在配置文件中注意对应路径即可(比如r17b 之后不支持mips 等区别)
ffmpeg 版本 4.0.2
# 如上述ndk
# 1 scp 命令 复制 ffmpeg 到 linux 子系统
scp -r [/mnt/ffmpeg存在windows目录] [要放在linux子系统中的位置]
# 2 执行tar 解压缩命令 解压ffmpeg 压缩包
tar -jxvf ffmpeg-4.2.2.tar.bz2
# 3 cd 命令进入到ffmpeg 目录下
cd [ffmpeg 路径]
# 执行 如下命令 生成一些编译时需要的文件
./configure --disable-x86asm
当然可官网选最新版本或者稳定版
编写 编译脚本 build_ffmpeg.sh
内容如下
#!/bin/bash
export NDK=/usr/bin/android-ndk-r20b #这里配置先你的 NDK 路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
function build_android
{
./configure \
--prefix=$PREFIX \
--enable-neon \
--enable-hwaccels \
--enable-gpl \
--disable-postproc \
--disable-debug \
--enable-small \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-static \
--enable-shared \
--disable-doc \
--enable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS"
make clean
make -j16
make install
echo "============================ build android arm64-v8a success =========================="
}
#arm64-v8a -> arm64-v8a
ARCH=arm64
CPU=armv8-a
API=21
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
#armv7-a -> armeabi-v7a
# ARCH=arm
# CPU=armv7-a
# API=21
# CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
# CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
# SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
# PREFIX=$(pwd)/android/$CPU
# OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
# build_android
#i686 -> x86
# ARCH=x86
# CPU=i686
# API=21
# CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
# CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
# SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
# PREFIX=$(pwd)/android/$CPU
# OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -mno-stackrealign"
# build_android
# #x86-64 -> x86-64
# ARCH=x86_64
# CPU=x86_64
# API=21
# CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
# CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
# SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
# PREFIX=$(pwd)/android/$CPU
# OPTIMIZE_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
# build_android
#armv5-a ->armeabi r20b ndk 里没有armv5
# ARCH=arm
# CPU=armv5te
# API=21
# CC=$TOOLCHAIN/bin/armv-linux-androideabi$API-clang
# CXX=$TOOLCHAIN/bin/armv-linux-androideabi$API-clang++
# SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
# CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
# PREFIX=$(pwd)/android/$CPU
# OPTIMIZE_CFLAGS="-march=$CPU"
# build_android
--enable-static \ # 编译静态库
--enable-shared \ # 编译动态库 我们这里都编译
PREFIX=$(pwd)/android/$CPU # 输出路径 当前目录下android 以cpu为子文件夹的位置
执行scp 命令将 build_ffmpeg.sh
复制到linux子系统中ffmpeg安装目录下
执行 如下命令开始编译 等待编译结束即可
./buildFfmpeg
编译结束后会在当前目录的android目录下根据cpu架构生成的目录
include
下 为头文件lib
下为编译好的库由于ffmpeg 是c,c++ 编译的要使用 我们需要使用ndk 所以新建项目需要支持 native 这里我们打印下版本号 ----- 步骤如下
新建支android项目 player Phone and table 中选择 Native c++
将main->cpp 目录下的CMakeLists.txt 文件复制到 main 目录下
将第二步编译好的include文件夹复制到cpp目录下
main 目录下新建jniLibs 将 对应架构的ffmpeg 的 静态文件 复制到该文件夹下
配置cmake
指定头文件路径
指定静态库路径
连接静态库
具体配置文件如下
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
set(CMAKE_VERBOSE_MAKEFILE on)
project("player")
add_library( # Sets the name of the library.
player
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
cpp/native-lib.cpp)
# 引入当前头文件
include_directories(${CMAKE_SOURCE_DIR}/cpp/include)
#打印当前 cmakeLists 的路径
message("当前cmakel路径: ${CMAKE_SOURCE_DIR} \n cpu架构:${CMAKE_ANDROID_ARCH_ABI}")
#设置C++ 编译 -L 设置库路径 -L设置的路径与下面的link_directories 应该类似
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
#指定静态库或动态库的搜索路径 该指令的作用主要是指定要链接的库文件的路径
# 自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
link_directories(
${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}
)
find_library(
log-lib
log)
#将指定的静态库连接到可执行文件上
target_link_libraries(
player
avformat avcodec avfilter avutil swresample swscale
${log-lib})
在MainActivity中声明native函数
public native String stringFromJNI();
在native-lib.cpp中实现
#include <jni.h>
#include <string>
//由于 FFmpeg 库是 C 语言实现的,我们这里是c++文件,所以要告诉编译器按照 C 的规则进行编译
//导入 version头文件
extern "C" {
#include "libavformat/version.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_player_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
// 读取version
return env->NewStringUTF(AV_STRINGIFY(LIBAVFORMAT_VERSION));
}
在MainActivity 中调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 调用native 方法获取版本信息
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
}
图就不加了 代码库在下面的连接里