http://blog.csdn.net/rozenix/article/category/787011
I.NDK配置和基本使用
下載解壓後即可使用。關鍵是不同版本的NDK開放的API不同,常用的是 r4和r5,後者面向Android 2.2+, 支持UI/圖形/聲音的部分C接口,還有STL的支持(遺憾的是r5中的STL沒整出來)。由於我面向的平臺是2.1的,所以,我用的是 r4c。
那個NDK是真正配置好的完全支持C++(包括STL)的?網上比較有名的是Crystax NDK r4, 我用的是Mozilla 爲開發Android Firefox開發而使用的NDK r4c(與Crystax類似),下載地址是:
http://ftp.mozilla.org/pub/mozilla.org/mobile/source/android-ndk-r4c-0moz3.tar.bz2
具體如何修改自己的NDK我後面再說。
1.NDK的基本使用
這裏說的基本使用,就是利用現有的NDK工具生成供SDK JAVA通過JNI調用的共享C庫(lib**.so)
以工程Helloworld爲例,在工程文件夾下:
#mkdir jni
#cd jni
至少要創建Android.mk和helloworld.c,例如:
Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := helloworld #庫名稱
LOCAL_SRC_FILES := helloworld.c #源文件
include $(BUILD_SHARED_LIBRARY) #生成共享庫
這是個NDK要使用的小型Makefile,更多的選項可以看 $NDK/docs/* 內的相關文檔。
helloworld.c 遵從一般JNI代碼的規定:
jstring Java_my_helloworld_Helloworld_hello( JNIEnv* env, jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello World from JNI !");
}
注意C++代碼裏面要加上 extern "C",防止C++的名稱修飾使得JNI無法找到函數名。
命名規則就是:Java_project_name_Activity_class_name_func_name.
編譯生成,採用的是NDK封裝好的腳本ndk-build, 在$NDK主文件夾下,使用很簡單,在工程主文件夾
下執行:(假設$NDK已經加入到$PATH)
#ndk-build
...
即可,若成功,則主文件夾的 libs/armeabi 或者libs/arm-v7te 下生成 libhelloworld.so
2.SDK中使用NDK生成的文件
修改src/my/helloworld/Helloworld.java,使之通過JNI調用C函數:
其中先加載libhelloworld.so,再調用其內的hellow()函數。
#ant debug
重建工程
前面提到的都是使用現有的ndk-build建立共享庫。如何建立可執行的C/C++文件?將jni/Android.mk內的
include $(BUILD_SHARED_LIBRARY) 改成include $(BUILD_EXECUTABLE) 即可。
那麼,想“自由使用”工具鏈,比如像使用gcc/g++那樣,尤其是想往Android上面移植 C/C++程序或者庫時,如何才能跳出ndk-build的限制?
I.提取Android的gcc工具鏈
如果你想偷懶的話,你很幸運,有現成的 ,附件的perl腳本agcc(csdn搞不出附件,只好鏈接新帖子) ,即可以完成工具鏈的抽取和封裝,可以像使用 gcc 那樣使用它,它最先來自
不過這個是面對整個Android開發包的(包括Android/SDK/NDK的所有文件),而且沒有C++/STL支持,我對它進行了修改,使它與上篇給出的ndk-r4配合,完全支持c/c++。
如果你想自己動手,請這樣做:
1.分別對
1)生成可執行文件
2)靜態庫
3) 動態庫
4)多個源文件 的不同類型的工程使用
#ndk-build -B V=1
命令,會讓ndk-build “揭露出”整個工具鏈的不同使用過程 ,比如上篇中的helloworld工程:
顯示:
Compile thumb : helloworld <= /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector
-fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/opt/android/android-ndk-r4c/samples/helloworld/jni
-DANDROID -Wa,--noexecstack -O2 -DNDEBUG -g -c -MMD -MP -MF /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o.d /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o
SharedLibrary : libhelloworld.so
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o
-Wl,--whole-archive -Wl,--no-whole-archive /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so
-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/libhelloworld.so
......
從這些命令記錄分別提取出
1)工具的名稱和位置
例如gcc/g++工具是 arm-eabi-gcc/g++,位置是 /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/。。
2)工具相關選項和參數
交叉編譯時,最重要的就是編譯工具的相關參數設置,以及從環境中提取的文件(頭文件夾,鏈接文件,庫文件..)。下面的從上面提取的相關參數就不用我解釋了吧?(如果不熟悉這些的話,真的不應該直接從Android上手學交叉編譯,道理你們懂的。。)
CC = arm-eabi-gcc
CFLAGS/CXXFLAGS ="-fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64"
CPPFLAGS ="-I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -I/opt/android/android-ndk-r4c/samples/helloworld/jni -DANDROID "
CXX =arm-eabi-g++
LDFLAGS = "-nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a"
3)工具的使用過程
主要是面對不同的源文件(.c/.cpp/.o/.h...),以及不同的目標(生成什麼?.o/.exe/.s...),工具的使用過程和參數都是不同的,比如上例:
.c-->.o
$CC $CPPFLAGS $CFLAGS helloworld.c -c -g -o helloworld.o
僅僅 預處理-->編譯,未鏈接
然後
.o-->.so
$CC $LDFLAGS helloworld.o -o libhelloworld.so
完成鏈接
4)大家可以查看其他幾類情況,使用的工具和參數各不相同。
II.直接使用工具鏈
提取出了工具鏈,弄清其不同參數和工作流程後,就可以自己指明使用了。首先將工具加入$PATH,然後,例如編譯如下的兩個全面測試C++功能的.cpp文件,要求ahoo.cpp -->libahoo.so(動態庫);a.cpp+libahoo.so --->a(程序):
ahoo.h
ahoo.cpp
a.cpp
命令就是:(都是先編譯,再鏈接,注意參數的區別)
1)ahoo.cpp--->ahoo.o a.cpp-->a.o
arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te
-mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o
arm-eabi-g++ a.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o a.o
2) ahoo.o -->libahoo.so
arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libahoo.so
3) a.o -->a
arm-eabi-gcc a.o -nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtend_android.o /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o -o a -lahoo -L./
你是什麼感覺呢,不覺得太長太麻煩了嗎?何苦呢?何必呢?所以我纔將所有的內容都封裝在agcc 內的啊,你難道不想也這樣做嗎?(尤其是對程序或者庫進行 ./configure 的時候!),上面的例子,直接用我的agcc 的話(先將包含arm-eabi-*的路徑加入$PATH )
#agcc ahoo.cpp -shared -o libahoo.so
Compile Thumb++ :ahoo.cpp ===> ahoo.o
...
Link ARM shared lib : ahoo.o ====> libahoo.so
...
#agcc a.cpp -o a -lahoo -L./
Compile Thumb++ :a.cpp ===> a.o
....
Link ARM executable : a.o ====> a
...
# file a
a: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
#file libahoo.so
libahoo.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped
#arm-eabi-readelf -d a
Dynamic section at offset 0x132cc contains 23 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libahoo.so]
0x00000020 (PREINIT_ARRAY) 0x1c2a4
0x00000021 (PREINIT_ARRAYSZ) 0x8
.................
搞定!現在你也可以從自己的NDK出發提取組合自己的工具鏈了吧
Android中提取的工具鏈搭建好之後:
I.使用工具鏈移植c/c++程序或庫
這類的程序的標準生成流程都是 :./configure -->make;make install 。想往Android上移植該怎麼辦?
1.(若需)修改代碼
前面說到Android的C庫不是POSIX兼容的,很殘。若程序/庫需要Android沒有的內容或者不開放C接口的內容,那就悲劇了,你只有想法子改代碼了。比如想移植 alsa-lib,它使用了SYS V SHM(內存共享功能),這個Android沒有,有人質疑爲何沒有,Google官方回答:“Sorry!But NO!”這樣的話,只有設法在代碼內移除這個需求...
2.(若需)修改工程
如果原工程沒有跨平臺支持的話,估計要修改configure,Makefile等文件才行。有兩種情況:
1)如zlib,在當前機器上直接./configure --prefix=/data/local,再修改生成的Makefile,將其中的CC=gcc RANLIB=ranlib LD=ld 改成
CC=agcc RANLIB=arm-eabi-ranlib LD=arm-eabi-ld ... 改完工具就可以直接make了。
2)如libffmpeg,還有另一條路(有時這是最後一條路 ):如果你夠強,直接利用Makefile.am(Makefile的來源文件)寫出工程的Android.mk文件,建立標準的NDK工程,利用ndk-build完成一切。(我討厭這招,因爲很費事,難成功)
3.直接上
若你夠幸運,前面兩個都不需要的話(所以我非常喜歡freedesktop.org 提供的工程,非常規範全面),以下的一條命令就行了:
#CC=agcc CXX=agcc LD=arm-eabi-ld RANLIB=arm-eabi-ranlib /
PKG_CONFIG_LIBDIR=/data/local/lib/pkgconfig:/data/local/share/pkgconfig/ /
./configure /
--prefix=/data/local /
--host=arm-eabi-linux /
--enable-malloc0returnsnull /
--enable-shared
這裏有關鍵幾項,
1)CC=agcc 則常見的CFLAGS,CPPFLAGS,LDFLAGS等變量都不用提供了,都在agcc裏面。
2)PKG_CONFIG_LIBDIR ,當前的工程所需(若需)的庫文件的.pc(庫的描述文件)在哪個文件夾下面一定要指明,且不要用PKG_CONFIG_PATH, 後者會先找主機裏面的庫(比如主機的/usr/lib/之類的),再找目標環境裏的。
3)prefix, 目標環境的路徑。一般默認的是/usr/local或者/usr, 所以一定要改成目標環境的文件夾前綴,此處是 /data/local
4)host ,指的是目標平臺,也可以寫成 arm-unknown-linux等,不過一定要確認configure腳本能認識這個“型號”,不然會產生問題(拒絕生成動態庫等等)
5)--enable-shard, 不是所有的configure默認生成動態庫(我就碰到過,比如jpeg62),其他的選項類似。
6)還有,有的工程的configure方式 很特別(比如openssl和原版X11),但是大體都可以仿照以上解決。(關鍵是讓configure找到所需的工具鏈,找到所需的環境以及文件,並通過測試,成功生成Makefile)
接下來,除非編譯出錯(這就是上面兩個“若需”的工作),直接
#make;make install
就行了。
II.如何使用/運行編譯的成果?
1.基本使用
收先你要有root權限,可以參考我寫的XT800 MOTO的刷機經歷 。相信大家注意到前面那個奇怪的prefix=/data/loc
al 了,Android平臺上即使root用戶(開發者)也只是對設備的部分文件夾有權限修改,最常用的就是/data/local 和/data/bin了。而JAVA程序都在/data/data下,比如我們的Helloworld.apk安裝後
#adb shell ls /data/data/my.helloworld/lib/
-rw-r--r-- system system 13225 2011-02-28 09:17 libhelloworld.so
可見它“自帶的”C庫也在裏面(如果有多個庫,只要確保 ant 最終生成之前將所有的.so放到libs/armeabi/下即可被打包進入.apk,java程序使用時別忘了所有自帶庫都要load一下)還有android裏面庫的標準路徑是/system/lib/,jni所用的自帶庫在/data/data/...裏面自己能找到,那麼C/C++程序呢?要放到允許放的地方去。比如我們上篇的 libahoo.so 和 a
#adb push libahoo.so /data/local/lib
#adb push a /data/local
#adb shell
進入android 設備的shell:
##ls
tmp
pds
cdrom
sqlite_stmt_journals
config
cache
sdcard
d
etc
system
sys
sbin
proc
init_prep_keypad_ttnm.sh
init.rc
init.mapphone_cg.rc
init.goldfish.rc
init
default.prop
data
root
dev
##ps
.....
system 1503 1169 122740 14612 ffffffff afe0d984 S com.motorola.process.system
app_33 1549 1169 121964 14556 ffffffff afe0d984 S com.android.alarmclock
app_51 1557 1169 121632 14024 ffffffff afe0d984 S com.motorola.firewall
app_54 1563 1169 121464 14260 ffffffff afe0d984 S com.motorola.extdisp
app_21 1611 1169 128052 15704 ffffffff afe0d984 S com.android.vending
app_32 1622 1169 123528 14428 ffffffff afe0d984 S com.motorola.apncontrol
app_3 1632 1169 133956 14700 ffffffff afe0d984 S com.hoho.campage
app_48 1648 1169 130216 15652 ffffffff afe0d984 S com.cooliris.media
app_81 1723 1169 123436 15032 ffffffff afe0d984 S com.moto.mobile.appstore
app_1 2507 1169 145004 26464 ffffffff afe0d984 S com.google.android.apps.maps
app_15 2559 1169 122940 16352 ffffffff afe0d984 S android.process.media
dhcp 2691 1 820 428 c00d4b28 afe0d7fc S /system/bin/dhcpcd
app_38 2738 1169 121404 14336 ffffffff afe0d984 S com.svox.pico
app_73 2745 1169 123112 15672 ffffffff afe0d984 S com.eshore.android
root 2770 1148 708 328 c006cb7c afe0d62c S /system/bin/sh
app_92 2776 1169 122612 17108 ffffffff afe0d984 S my.helloworld
root 2781 2770 860 344 00000000 afe0c75c R ps
##cat /proc/2776/maps
.....
80d00000-80d1d000 r-xp 00000000 1f:06 417 /system/lib/libmetainfo.so
80d1d000-80d1e000 rwxp 0001d000 1f:06 417 /system/lib/libmetainfo.so
80e00000-80e03000 r-xp 00000000 1f:08 1925 /data/data/my.helloworld/lib/libhelloworld.so
80e03000-80e04000 rwxp 00002000 1f:08 1925 /data/data/my.helloworld/lib/libhelloworld.so
80f00000-80f03000 r-xp 00000000 1f:06 275 /system/lib/hw/gralloc.omap3.so
80f03000-80f04000 rwxp 00003000 1f:06 275 /system/lib/hw/gralloc.omap3.so
....
##cd /data/local
##ls -l
-rwxrwxrwx shell shell 458405 2011-02-28 13:04 a
-rwxrwxrwx shell shell 76232 2009-07-31 19:08 su
drwxrwxrwx root root 2010-12-08 19:14 mnt
drwxrwxrwx root shell 2011-02-28 13:05 lib
drwxrwxrwx mot_tcmd shell 2011-03-01 13:04 tmp
##./a
link_image[1721]: 2786 could not load needed library 'libahoo.so' for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOT LINK EXECUTABLE
所以要把路徑加進去。
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a
link_image[1721]: 2786 could not load needed library 'libahoo.so' for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOT LINK EXECUTABLE
??因爲要超級權限
##su
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a
ahoooooooooo coming!
bagaaaaaaaaa coming!
bagaaaaaaaaa dying!
ahoooooooooo dying!
Horaaaaaaaaaaa
Woraaaaaaaaaaaa
sizeof hana:100
sizeof hana:100
libahoo.so:--exception.runtime_error.string: --
libahoo.so:--exception.catch.string: --You are Foooooooooyoooooooed!
a :--string:
這下總行了。
2.給SDK使用
說實話,在Android設備上運行c程序,有何意義?最常用的還是移植c庫給java使用,比如下面這位的工作就很典型:
abitno.me/compile-ffmpeg -android -ndk
Android提供的解碼功能有限,他將ffmpeg庫移植到Android上成爲libffmpeg.so,開放JNI接口供上層JAVA UI使用,其結果就是一個新的Android播放器。而移植一個庫的過程如上所述兩類:編寫Android.mk 利用ndk-build創建libdep.so;或者使用agcc直接生成lib.so;然後再寫一個JNI接口層libinterface.so庫(除非你直接在原工程內寫好接口);放到Android工程的./libs/armeabi裏,最後在java內調用接口;要確保最終的.apk內包含所需的自帶庫。
以下就是我寫的一個底層庫-->接口庫-->java的示例,可以參考:
#android create project -p ./ -t 4 -n Ahoo -k ore.ahoo -a Ahoo
#cat src/ore/ahoo/Ahoo.java
#cat res/values/styles.xml
(現在不清楚有什麼辦法讓單個Android.mk生成多個動態庫,大家可以試試)
#cat jni/dep.h
#cat jni/dep.cpp
#cat jni/ahoo.cpp
分別編譯(也可以用ndk-build):
#cd jni
#agcc dep.cpp -shared -o libdep.so -llog
Compile Thumb++ :dep.cpp ===> dep.o
arm-eabi-g++ dep.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale
-msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o dep.o
Link ARM shared lib : dep.o ====> libdep.so
arm-eabi-gcc dep.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib
-lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a
-o libdep.so -llog
#agcc ahoo.cpp -shared -o libahoo.so -ldep -L./ -llog
Compile Thumb++ :ahoo.cpp ===> ahoo.o
arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale
-msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o
Link ARM shared lib : ahoo.o ====> libahoo.so
arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib
-lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a
-o libahoo.so -ldep -L./ -llog
#ls
ahoo.cpp dep.cpp dep.h libahoo.so libdep.so
#cd ..
#cp jni/lib* libs/armeabi/
#ant debug
........
BUILD SUCCESSFUL
Total time: 3 seconds
#adb install bin/Ahoo-debug.apk
1663 KB/s (188420 bytes in 0.110s)
pkg: /data/local/tmp/Ahoo-debug.apk
Success