这里先做一个道歉,因为我还大三,身上还有不少课程。最近五门的必修课压身所以更新的进度上会有严重的脱节,但是我还是会尽量保证一周一篇文章的,希望能够理解。
文章内容参考书目《音视频开发进阶指南 -- 基于 Android 与 iOS 平台的实践》
| GitHub传送门 |
|---|
其实很多网站都已经有过这样的介绍了,不过既然是自己的文章,还是需要讲讲的,嘿嘿。创建一个新的 AS 项目,并且选择到我们的 Native C++ 的选项来创建我们的项目。当然我们里面会看到一个 C++ standard ,我直接默认选的 Toolchain Defalut 。
到了这里其实我们的程序就可以运行了,不信你可以直接跑,不过看看代码,你会发现存在一定的不同
Native C++ ? 这个问题是读者必须清楚的, Java 终究并不是一门万能的语言,每门语言都是如此,有着自己的长处和局限性。不然为什么还需要 Binder 机制去调用一些底层的服务,因为很多东西,上层做不了。
情况可以分为以下几种:
(1)应用程序需要一些平台的相关特性支持,而 Java 层并没有提供相应的API,(比如OpenSL ES的使用)。
(2)调用已然存在的用 C/C++ 编写的函数库。
(3)应用程序对一些关键操作存在一定的处理速度要求。
Native 代码 native 方法的函数。 public class NativeTest {
public native void encode();
}
复制代码
就如上面一般创建一个文件,用 native 修饰即可,但是你可能会看到这个函数爆红,其实没什么关系,我们先用小锤子 Build 一下,正常情况下是不会报错的,因为只是这个 native 函数没有找到对应的 C/C++ 函数而已,并不影响我们本身的 Java 类。
C/C++ 文件了。 1. 切换到src/main/java目录下 2. 在Terminal中输入javah -jni 包名.带native的Java类 // 在我的项目中的语句 javah -jni com.clericyi.player.NativeTest 3. 得到一个格式为:(包名_类名).h的头文件,并将他移动到cpp的目录下 复制代码
#include <jni.h>
#include <string.h>
#include "com_clericyi_player_NativeTest.h"
JNIEXPORT jstring JNICALL Java_com_clericyi_player_NativeTest_encode
(JNIEnv *env, jobject) {
return env->NewStringUTF("Encoder encoding");
}
复制代码
其实这个时候还是用不起来的,需要进行一定的配置才行,走完下面的流程应该就能看到我们的运行效果了。
(1) 修改CMakeList.txt中的对应数据,添加创建的cpp文件
add_library(
# 。。。
audioencoder.cpp)
(2) app -> build.gradle
android {
defaultConfig {
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
cFlags "-DSTDC_HEADERS"
}
}
ndk {
// 可以加入x86等等,跟应用的手机架构相对应
// 写了几个,到时候build中就会生成几个
abiFilters "armeabi-v7a"
}
}
}
复制代码
因为我们在开发过程中必须要使用到 NDK ,而 NDK 的版本兼容是一个很重要的事情。为了能向下兼容一些版本,我们选用低一级的版本即可。(下载路径:Prefereces -> Android SDK -> SDK Tools)
相信很多人会在查资料时发现别人安装的都是 NDK ,而我安装的是 NDK(Side by Side) ,但是你在自己的AS上也同样的找不到我们需要的 NDK 。所以给出一个网址来给读者们作为安装的教程: 安装及配置 NDK 和 CMake
三部分构成:
Android 或者 iOS PC 编译生成了一份给别人用的东西。 以 LAME 作为示范例子,来做一个详细的示范。
这里已经不再建议用书上的方法了,我试了一天了,太难调通了。这里还是使用 Android Studio 现在自动生成带有的解决方案 -- CMake 。
LAME ,把 libmp3lame 下的文件和 include 下的 lame.h 文件全都移动到 AS 中 cpp/lame 的文件夹下。
CMakeLists.txt 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).
# 我们要放入的cpp文件
native-lib.cpp
# lame
lame/bitstream.c lame/encoder.c lame/gain_analysis.c
lame/lame.c lame/id3tag.c lame/mpglib_interface.c
lame/newmdct.c lame/presets.c lame/psymodel.c
lame/quantize.c lame/fft.c lame/quantize_pvt.c
lame/reservoir.c lame/set_get.c lame/tables.c
lame/takehiro.c lame/util.c lame/vbrquantize.c
lame/VbrTag.c lame/version.c)
复制代码
build 一下我们的项目,会报错,我出现的错误即解决方案下方给出。 错误1:#include <lame.h> 解决方案:#include "lame.h" --- 错误2:ieee754_float32_t fast_log2(ieee754_float32_t x); 解决方案:float fast_log2(float x); 复制代码
#include <jni.h>
#include <string.h>
#include "com_clericyi_player_NativeTest.h"
JNIEXPORT jstring JNICALL Java_com_clericyi_player_NativeTest_encode
(JNIEnv *env, jobject) {
return env->NewStringUTF(get_lame_version());
}
复制代码
可以把上文中使用过的那个 C++ 文件的返回值修改成这个,就能够得到效果了。
基本这就完事儿了,如果想要做更深层次的了解,你可以看这样项目结构用于自学,对应的项目中的内容是书上的一个用于将 PCM 格式文件转化为 MP3 格式的范例。
PCM 的文件可以自己去随便捞一个,因为求方便我是用 adb 直接推到虚拟机中的。
以上就是我的学习成果,如果有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。