貌似許多人都是從lame庫開始入門Android NDK開發(fā)的,在網(wǎng)上一搜一大堆詳細(xì)教程。本篇的亮點(diǎn)是采用Google推薦的CMake工具(不是ndk-builder)來移植lame項(xiàng)目。重點(diǎn)寫一下與ndk-builder的差異,而非教程。
1.CMake是什么?
這個(gè)是AndroidStudio 2.2以上的版本才可使用的,跟ndk-builder一樣是一款原生構(gòu)建工具。
與ndk-builder不同的是,ndk-builder需要用到mk文件,而CMake則使用CMakeLists文件。
具體可閱讀官方介紹 向您的項(xiàng)目中添加C代碼 以及 CMake(不讀的話,可能看不懂怎么移植哦)
在這里要說的就是,如果你使用的是AndroidStudio 2.2以上的版本,那么只要在創(chuàng)建項(xiàng)目時(shí)選擇“Include C++ Support”選項(xiàng),然后不停點(diǎn)擊下一步就可以創(chuàng)建一個(gè)使用CMake工具構(gòu)建C\C++代碼的項(xiàng)目。
當(dāng)然前提是,你在SDK Manager中安裝了CMake。
由于本文重點(diǎn)在移植lame項(xiàng)目,對CMake的介紹就不多說了。
2.將lame的代碼放入項(xiàng)目
現(xiàn)在假設(shè)你已經(jīng)創(chuàng)建了一個(gè)采用CMake的NDK項(xiàng)目,那么你可以找到兩個(gè)很重要的東西:cpp文件夾和CMakeLists.txt文件。前者是用來放C\C++源碼的,后者則是CMake的構(gòu)建腳本文件。
如果你看完了向您的項(xiàng)目中添加C代碼 文章,那你肯定知道CMakeLists.txt腳本中的大體內(nèi)容了。
好了,先下載lame吧。
http://lame.sourceforge.net/download.php
http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz
下載完之后解壓,然后找到libmp3lame文件夾,將里面的.c和.h文件全部復(fù)制到項(xiàng)目的cpp目錄中。
注意:libmp3lame文件夾內(nèi)還包含其他文件夾,不用管它。
然后,再找到include文件夾,將lame.h文件拷貝到cpp目錄中。(總共43個(gè)文件)
接下來需要將源文件加入到項(xiàng)目中,通過CMakeLists.txt腳本來控制
在CMakeLists中修改add_library 方法的最后一個(gè)參數(shù),通過AndroidStudio創(chuàng)建的ndk項(xiàng)目中會有一個(gè)native-lib.cpp文件,在此文件后將lame相關(guān)的所有.c文件添加進(jìn)來。這一步是指定源代碼的位置。
像下面這樣:
add_library(native-lib
SHARED
native-lib.cpp bitstream.c encoder.c gain_analysis.c lame.c id3tag.c
mpglib_interface.c newmdct.c presets.c psymodel.c quantize.c fft.c
quantize_pvt.c reservoir.c set_get.c tables.c takehiro.c util.c
vbrquantize.c VbrTag.c version.c)
不過,這里要注意,AndroidStudio默認(rèn)的CMakeLists文件的位置在項(xiàng)目目錄中,我將它放到cpp目錄中去了。所以才能直接添加.c文件名,否則需要添加相對路徑“src/main/cpp/xxx.c”
到此,lame項(xiàng)目就已經(jīng)被放入我們的ndk項(xiàng)目中了。
3.移植修改
首先,需要對lame中的三個(gè)文件進(jìn)行一些小改動(dòng)。
1)刪除fft.c文件的47行的"include "vector/lame_intrin.h""
2)修改set_get.h文件的24行的#include“l(fā)ame.h"
3)將util.h文件的574行的"extern ieee754_float32_t fast_log2(ieee754_float32_t x);"
替換為 "extern float fast_log2(float x);"
這些跟ndk-builder是一樣的,網(wǎng)上有很多教程。
然后,需要修改app -> build.gradle文件
android {
...
defaultConfig {
...
externalNativeBuild{
cmake{
cFlags "-DSTDC_HEADERS"
}
}
}
}
沒錯(cuò),就是添加這個(gè)-DSTDC_HEADERS編譯標(biāo)識。
大家可以試一下,如果不加這個(gè)標(biāo)志,我們的項(xiàng)目編譯會報(bào)錯(cuò),比如undefined symbol bcopy...之類的。
這里說明一下我的調(diào)查結(jié)果:
首先,添加-D標(biāo)志的意思就是給編譯器添加宏定義。那么-DSTDC_HEADERS就相當(dāng)于給項(xiàng)目增加一句”#define STDC_HEADERS“。
我們打開machine.h文件看一下第34行:
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else
# ifndef HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr(), *strrchr();
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
意思很明白,如果沒有定義STDC_HEADERS這個(gè)宏則會用到bcopy方法,而這個(gè)方法我們根本沒有,于是就報(bào)錯(cuò)了。
4.測試
到現(xiàn)在我們的移植工作就已經(jīng)做完了,接下來可以簡單測試一下。
打開項(xiàng)目中的native-lib.cpp文件,做如下修改:
#include <jni.h>
#include <string>
#include "lame.h"
extern "C"
jstring
Java_com_javine_mylameproject_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
return env->NewStringUTF(get_lame_version());
}
運(yùn)行項(xiàng)目,如無意外我們的app會顯示lame的版本號 3.99.5