Android is the first free, open source, and fully customizable mobile
platform. Android offers a full stack: an operating system, middleware,
and key mobile applications. It also contains a rich set of APIs that
allows third-party developers to develop great applications.
製作 cygwin 環境下的 Cross tool chain
在完全開源前,很多開發者在用 CodeSourcery
的 GNU Toolchains for ARM
。現在簡單了,下載到源碼
後,在 prebuild 目錄下就有完整的 toolchain 用了。如果需要在其他系統環境下使用,可以去下載 android-toolchain-20081019.tar.bz2
源碼重新編譯。在 cygwin 下編譯時,先檢查一下 gcc make flex bison gettext-devel
等是否裝全(編譯過程中會用到 msgfmt 命令,cygwin 把它放到 gettext-devel 包裏了),然後按照其
readme.txt 裏的 linux 方式編譯就可以了。cgywin 下有時會出現文件寫失敗的錯誤,用 chmod +w 修改即可解決。
在 <android source>/build/core/combo 目錄下的 linux-arm.mk
文件對我們來說非常有幫助,其中 C_INCLUDES 描述 C 語言的所有頭文件位置,在 android source
裏找到這些目錄,並複製到新編譯好的 <toolchain>/arm-eabi/include 目錄下,動態庫在編譯過的
<android source>/out/target/product/generic/system/lib 目錄下,也可以從
Android SDK 的模擬器中 /system/lib 下找到這些文件,並複製到
<toolchain>/arm-eabi/lib 目錄下。在 <android source>/build/core
下有 armelf.x armelf.xsc
,是以後編譯必須的連接腳本。在 <android source>/out/target/product/generic/obj/lib 下的 crtbegin_static.o crtbegin_dynamic.o crtend_android.o
編譯時還要根據自己情況選擇並連接到可執行文件中去,當然也可以在程序 main 函數後加如下函數代替。
void _start(int argc, char **argv) { exit( main(argc, argv) ); }
First native C application on android
製作好了 toolchain ,就可以寫個 hello.c 測試一下了。代碼如下:
int main(int argc, char **argv)
{
return 0;
-include AndroidConfig.h -lc -o hello hello.c crtbegin_dynamic.o crtend_android.o
$ adb push hello /data
$ adb shell chmod 777 /data/hello
$ adb shell /data/hello
Hello World!
$
Shared library for android
接下來測試 shared library ,編寫代碼 libhello.c :
int sayhello(char *name)
{
return 0x12345;
{
return 0;
編譯代碼及測試運行:
-L./ -lc -lhello -o hello2 hello2.c crtbegin_dynamic.o crtend_android.o
$ adb push libhello.so /data
$ adb push hello2 /data
$ adb shell chmod 777 /data/hello2
$ adb shell /data/hello2
Hello World!
$
呵呵,又邁進一步 ...
The Java Native Interface (JNI) for Android
在 eclipse 裏新建一個 android 項目,新增加一個類 hello.java :
public class hello {
public native int test1();
public native int test2(int[] name);
修改主程序
onCreate 的代碼,用來調用顯示結果:
hello h = new hello();
TextView tv = new TextView(this);
tv.setText( Integer.toHexString( h.test1() ) );
setContentView(tv);
android 使用的 JNI 頭文件在目錄 <android
source>/dalvik/libnativehelper/include/nativehelper 下。也許是爲了提高
android 映射庫函數的速度,android 另加了兩個函數,在加載和釋放庫時被VM調用,即:jint
JNI_OnLoad(JavaVM* vm, void*) 和 void JNI_OnUnload(JavaVM* vm, void*)
。通過
JNIEnv 的
RegisterNatives 用法把一個
JNINativeMethod 數組
註冊到 VM 。<android source>/
dalvik/libcore/dalvik/src/main 加有個簡單的例子,可以幫助理解 JNINativeMethod 中
signature 的寫法。
共享庫代碼 libhello_jni.c :
static int test1(JNIEnv* env, jclass clazz)
{
static int test2(JNIEnv* env, jclass clazz, jarray a)
{
#define gClassName "cn/oopsware/hello/hello"
static JNINativeMethod gMethods[] = {
{ "test1", "()I", test1 },
{ "test2", "([I)I", test2 },
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
jclass cls;
if ( (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4) ) return JNI_ERR;
cls = (*env)->FindClass(env, gClassName);
(*env)->RegisterNatives(env, cls, &gMethods[0], 2);
return JNI_VERSION_1_4;
void JNI_OnUnload(JavaVM* vm, void* reserved)
{
jclass cls;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4)) return;
cls = (*env)->FindClass(env, gClassName);
(*env)->UnregisterNatives(env, cls);
編譯並上傳到模擬器:
-lc -o libhello_jni.so hello_jni.c
$ adb push libhello_jni.so data/bin/libhello_jni.so
在 eclipse 裏運行 android 項目,即可看到正確結果。 測試環境 Android SDK 1.0-r2 ,測試代碼及編譯好的庫和apk可以到 http://sites.google.com/site/oopsware/android 下載。
http://hi.baidu.com/oopsware/blog/item/5a86550152edf7d1267fb56e.html