Android studio准备
Android studio需要下载Android6.0版本(Android SDK Platform 23),最小支持Android6.0
NDK 下载
cmake下载安装
Android studio 代理配置
dl.google.com可能会被屏蔽,首先查下其IP地址。查到IP地址后修改etc/hosts文件。
Android 市场份额
Android 个版本市场份额
Android 支持6.0就可以了。
CMake
C/C++ 编译成so库,需要使用到CMake。
新建一个Empty的Android工程,我们看下如何从0配置NDK开发环境。
然后打开Terminal
进入JNILoader所在的目录,输入如下命令
javac JNILoader.java
注意不要忘了后缀.java
输入javac -h ./ JNILoader.java,会生成相应的文件,注意./前后都要有空格。
然后将生成的com_example_testndkempty_JNILoader.h文件移动到cpp文件夹中。
然后创建JNILoader.cpp文件,并输入相关内容,如下图
注意,该文件代码错误,第九行代码应该是 return env->NewStringUTF(labelString.c_str());我截图中忘了增加()
接下来我们使用CMake编译cpp文件夹下的文件。
在app文件夹下创建CMakeLists.txt文件,注意,名字一定不要写错
CMakeLists.txt文件内容
#这里在SDK里面查看cmake支持的版本
cmake_minimum_required(VERSION 3.10)
#Test221123 编译成动态库,编译的时候使用JNILoader.cpp文件
add_library(Test221123 SHARED src/main/cpp/JNILoader.cpp)
#需要使用到的系统库
find_library(log-lib log)
#连接到哪些库
target_link_libraries(Test221123 ${log-lib})
Test221123是在JNILoader类中起的名字,详见上文。
Gradle文件中的配置,有两个地方需要新增,这两个地方已经加了汉语注释
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.testndkempty"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//编译可增加些flags,但我们这里不增加任何东西
externalNativeBuild{
cmake{
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild{
//cmake 文件的路径
cmake{
path "CMakeLists.txt"
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
运行项目,build会出现下面的文件夹。
我们也可以指定编译的ndk 种类。
gradle里增加如下代码
ndk{
abiFilters 'x86_64','armeabi-v7a'
}
这里的代码会有红线,原因就是我们在c代码中使用了c++,可以做如下修改
//
// Created by 王学岗 on 2022/11/23.
//
#include <string>
#include "com_example_testndkempty_JNILoader.h"
extern "C" jstring Java_com_example_testndkempty_JNILoader_getNativeString
(JNIEnv *env, jobject obj) {
std::string labelString = "Hello 音视频开发";
return env->NewStringUTF(labelString.c_str());
}
或者这样写,也可以消除红线
//
// Created by 王学岗 on 2022/11/23.
//
#include <string>
#include "com_example_testndkempty_JNILoader.h"
#ifdef __cplusplus
extern "C" {
#endif
jstring Java_com_example_testndkempty_JNILoader_getNativeString
(JNIEnv *env, jobject obj) {
std::string labelString = "Hello 音视频开发";
return env->NewStringUTF(labelString.c_str());
}
#ifdef __cplusplus
}
#endif
第一个FFmpeg程序
把FFmpeg库引入
修改CMakeLists
cmake_minimum_required(VERSION 3.10)
#设置FFMPENG_DIR CMAKE_CURRENT_SOURCE_DIR 在cmake同一级目录下找
SET(FFMPENG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/libFFmpeg/armeabi-v7a)
#引用FFMPENG_DIR
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/include)
#链接lib
LINK_DIRECTORIES(${FFMPENG_DIR}/lib)
#打印日志
MESSAGE(STATUS "${FFMPENG_DIR}/include")
MESSAGE(STATUS "${FFMPENG_DIR}/lib")
#Test221123 编译成动态库,编译的时候使用JNILoader.cpp文件
add_library(Test221123 SHARED src/main/cpp/JNILoader.cpp)
#需要使用到的系统库
find_library(log-lib log)
#连接到那哪些库 z c m dl ${log-lib}是系统自带的
target_link_libraries(Test221123 avformat avcodec avdevice avfilter avutil fdk-aac x264 z c m dl ${log-lib})
修改com_example_testndkempty_JNILoader.h和JNILoader.cpp文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_testndkempty_JNILoader */
#ifndef _Included_com_example_testndkempty_JNILoader
#define _Included_com_example_testndkempty_JNILoader
#ifdef __cplusplus
extern "C" {
#endif
//引入FFmpeg库
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavutil/avutil.h>
/*
* Class: com_example_testndkempty_JNILoader
* Method: getNativeString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_testndkempty_JNILoader_getNativeString
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
//
// Created by 王学岗 on 2022/11/23.
//
#include <string>
#include "com_example_testndkempty_JNILoader.h"
#ifdef __cplusplus
extern "C" {
#endif
jstring Java_com_example_testndkempty_JNILoader_getNativeString
(JNIEnv *env, jobject obj) {
char buff[10240] = {0};
//avcodec_configuration得到FFmpeg编译时配置的字符串
sprintf(buff,"%s",avcodec_configuration());
return env->NewStringUTF(buff);
}
#ifdef __cplusplus
}
#endif
看下运行效果
cmakeList实战
cpp文件如上
cmakeList文件代码如下
#这里在SDK里面查看cmake支持的版本
cmake_minimum_required(VERSION 3.0.0)
#设置FFMPENG_DIR CMAKE_CURRENT_SOURCE_DIR 在cmake同一级目录下找
SET(FFMPENG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp)
#引用FFMPENG_DIR
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/camera_preview)
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/libcommon/egl_core)
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/libcommon/message_queue)
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/libcommon/opengl_media)
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/libcommon/opensl_media)
INCLUDE_DIRECTORIES(${FFMPENG_DIR}/libcommon)
#Test221123 编译成动态库,编译的时候使用JNILoader.cpp文件
add_library(innerScreenLauncher SHARED src/main/cpp/ChangbaRecordingPreviewScheduler.cpp
src/main/cpp/camera_preview/mv_recording_preview_controller.cpp
src/main/cpp/camera_preview/recording_preview_renderer.cpp
src/main/cpp/libcommon/egl_core/egl_core.cpp
src/main/cpp/libcommon/egl_core/egl_share_context.cpp
src/main/cpp/libcommon/message_queue/handler.cpp
src/main/cpp/libcommon/message_queue/message_queue.cpp
src/main/cpp/libcommon/opengl_media/render/video_gl_surface_render.cpp
src/main/cpp/libcommon/opengl_media/texture/gpu_texture_frame.cpp
src/main/cpp/libcommon/opengl_media/texture/texture_frame.cpp
src/main/cpp/libcommon/opengl_media/texture/yuv_texture_frame.cpp
src/main/cpp/libcommon/opengl_media/texture_copier/gpu_texture_frame_copier.cpp
src/main/cpp/libcommon/opengl_media/texture_copier/texture_frame_copier.cpp
src/main/cpp/libcommon/opengl_media/texture_copier/yuv_texture_frame_copier.cpp
src/main/cpp/libcommon/opengl_media/movie_frame.cpp
src/main/cpp/libcommon/opensl_media/opensl_es_context.cpp
src/main/cpp/libcommon/matrix.cpp
src/main/cpp/libcommon/thread.cpp)
#需要使用到的系统库
find_library(log-lib log)
#连接到哪些库
#${log-lib} OpenSLES -lGLESv2 -lEGL android为系统库
target_link_libraries(innerScreenLauncher ${log-lib} OpenSLES -lGLESv2 -lEGL android)