Android研究
http://antkillerfarm.github.io/
1.JNI
(1)Java call Native C
JNI的基本概念可以參考以下文獻:
http://blog.csdn.net/believefym/archive/2007/06/08/1644635.aspx
這里需要注意的是javah命令處理的是.class文件,而不是.java文件。你需要指定package的路徑和package名。javap命令也有類似的要求。
(2)Native C call Java
基本方法參考下列文獻:
http://icepeer.itpub.net/post/3982/19158
注意事項:
使用構造函數時,JDK1.1的寫法是:
jmethodID mid = (*env)->GetMethodID(env,cls,"","(Ljava/lang/String;)V");
而JDK1.2的寫法是:
jmethodID mid = (*env)->GetMethodID(env,cls,"","(Ljava/lang/String;)V");
(3)Java call Native C & Native C callback Java
Android由于提供的是Java接口,所以這里最常見的情況是
1)Java啟動程序。
2)Java調用Native C。
3)Native C回調Java。
有上面的編程經驗,這個也不是太難的事。和(2)中的區別在于:(2)中由于程序是用C啟動的,所以在調用Java之前,需要啟動JVM,并實例化相關的Java對象,而(3)中例子由于程序是用Java啟動的,在C回調Java時,JVM已經啟動,相關的Java對象實例也已存在,所以做法要簡單的多。
使用javah生成的.h文件中,函數的聲明在Java中聲明的參數之前,還有兩個參數JNIEnv和jobject。env是調用Java方法的接口,它的功能非常多。jobject傳入的是調用Native C的那個Java對象實例的引用。jobject指針不能在多個線程中共享. 就是說,不能直接在保存一個線程中的jobject指針到全局變量中,然后在另外一個線程中使用它.幸運的是,可以用gs_object=env->NewGlobalRef(obj);來將傳入的obj保存到gs_object中,從而其他線程可以使用這個gs_object來操縱那個java對象了。
2.在Android上編譯C程序
(1)風臨左岸在這方面頗有建樹,以下是他的blog:
http://blog.sina.com.cn/flza
最簡單的hello world程序可以參看下面這篇文章的做法。
Android原生(Native)C開發之一:環境搭建篇
http://blog.sina.com.cn/s/blog_4a0a39c30100auh9.html
這里有個概念要弄清楚,之前的例子都是針對x86-win32平臺的,而這里我們要在arm-linux下編程。我這里有個同事,曾將x86-win32下的dll放到Android模擬器中,然后抱怨無法使用JNI,這就是這類錯誤的一個典型的例子。
還有一點需要注意的是,風臨左岸使用的交叉編譯工具,所編出的程序雖然可以在模擬器中運行,但卻是無法直接用于JNI的,需要使用一定的技巧,可參見以下網頁:
Shared library “Hello World!” for Android
http://honeypod.blogspot.com/2007/12/shared-library-hello-world-for-android.html
從這篇文章可以看出,風臨左岸使用的交叉編譯工具的動態庫的默認格式,和Android平臺的動態庫的格式是不同的,這也是之前有人說Android無法使用JNI的原因。
更好的辦法是直接使用google提供的交叉編譯工具。
(2)獲得Android的源代碼
獲得源代碼的官方方法如下:
http://source.android.com/source/download.html
雖然源代碼在http://source.android.com下,但用瀏覽器是無法獲得代碼的,只能用上文提到的方法才行。
當然諸如www.androidin.com之類的網站也提供了非官方的源代碼下載。
源代碼的大小有1G左右,解壓源代碼,在源代碼的prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin文件夾下可以找到google提供的交叉編譯工具。
使用prebuilt工具編譯C程序的方法可以參考以下文章:
http://www.j2medev.com/android/native/200901/20090119222445.html
3.Android JNI
正統的做法可以參照以下網頁:
http://www.j2medev.com/android/native/200901/20090119222617.html
當然簡單的做法也是有的,可以只解壓源代碼中的bionic、dalvik、prebuilt這三個文件夾。
需要注意的是,和第三方的交叉編譯工具不同,prebuilt下只有相關的頭文件而沒有相應的.o或.a文件,所以用一般的makefile的話,沒有辦法編譯靜態可執行文件,但是動態庫文件是可以編的。
這里還有一個奇怪的地方,如果直接使用cc生成.so的話,會出錯。而先cc生成.o,再ld生成.so就沒問題。不知道這是什么原因,尚需高手指點。
這里需要指出一點,普通的JNI調用使用System.loadLibrary加載動態庫,而Android平臺要使用System.load加載動態庫。這就是很多人套用PC上的語法,但卻在Android上失敗的原因。
4.關于一個語法現象
AlertDialog dialog = new AlertDialog.Builder(SmartGuider.this).setTitle("設置錯誤").setMessage("GPS功能未開啟,請先開啟GPS后再使用本程序!\n\n點擊Ok進入系統設置頁面,點擊Cancel退出程序。").create();在apidemo中,有很多類似于這樣的語句。剛閱讀到的時候,先是覺得是不是語法有誤,怎么能在一條語句中,調用兩個成員函數。接著一想,這是人家出的demo,怎么可能犯這種低級錯誤,一處也就罷了,總不可能到處都出這種錯吧。
于是就考慮是不是Java的新語法,畢竟Java這種語言從1.0到1.7,已經有8個版本了,像@Override和模板之類的特性都是后來添加進去的。但查了半天也沒查到出處。
于是去Android SDK中查看相關類的方法,才發現了奧妙。
AlertDialog create() AlertDialog.Builder setTitle(CharSequence title) AlertDialog.Builder setMessage(CharSequence message)由于setTitle和setMessage返回的都是AlertDialog.Builder類型的引用(多半就是this),從而使得這樣連寫的語法得以實現。如果把create放到setTitle或setMessage之前,顯然就會出錯了。因此這根本就不是什么新語法,而只是一種技巧而已。
在C語言中,其實也有類似的情況,例如
char *strcpy(char *strDestination,const char *strSource);
為什么不寫成
void strcpy(char *strDestination,const char *strSource);
或者
char *strcpy(const char *strSource);
呢?
不采用第一種,是因為這樣做可以使用諸如strlen(strcpy(...))之類的便捷寫法。
不采用第二種,當然是和內存分配有關了,這里就不多說了。
5.Activity生命周期初探
Android SDK上關于Activity生命周期的圖,無疑是權威的,但相關文檔中并沒有Android手機功能鍵對Activity生命周期所造成的改變的內容。
我這里通過重載Activity派生類的相關函數,并輸出日志的方法,探討該問題。
先說一下日志,可以使用android.util.Log類來輸出日志,eclipse在Debug狀態下可以看到輸出的日志。輸出日志的方法有很多種,他們并不是各自獨立的,而是一種信息內容包含的關系,從最簡略到最詳細依次為ERROR, WARN, INFO, DEBUG, VERBOSE,也就是說ERROR中的日志一定在VERBOSE中也能看到。還有Android運行時生成的日志很多,可以自定義過濾器過濾無關的日志。
這里僅對onCreate、onDestroy、onPause、onRestart、onResume、onStart、onStop進行重載,并輸出日志。
1)啟動程序
onCreate->onStart->onResume
2)重啟動程序(按下左側的主頁鍵和左側的撥號按鈕,不會關閉當前的Activity)
onRestart->onStart->onResume
3)按下左側的主頁鍵和左側的撥號按鈕
onPause->onStop
4)按下右側的返回鍵
onPause->onStop->onDestroy
5)右側的掛機按鈕
onPause
6.添加新的View
利用向導生成的代碼中只有一個View,相應的UI布局文件在res/layout/main.xml,找了半天也沒找到如何快捷的添加View,于是只好自己手動添加相關的xml文件,好在eclipse可以定制添加的xml文件的模板,于是把main.xml復制一下,做成模板,以后添加就方便了。
7.編譯Froyo(部分轉貼)
說點題外話,這個Blog本來打算完全寫些自己的原創內容,對于轉貼只給鏈接,但鏈接這東西,有利有弊。常常過上幾個月,原來的鏈接就不好使了。所以只好有選擇的粘貼一些了。
Froyo出來有一陣子了,一時興起,從官網上git了代碼,打算編譯。不料根據出錯信息得知,Froyo及其以后的版本需要64-bit的OS才能編譯。所以只好重新安裝64-bit的Ubuntu。
按照官網上的步驟一步一步的做,然后卡在apt-get install sun-java5-jdk上了。出錯信息告訴我,找不到這個包。Google了一下,找到以下解決方法:
9.10/10.04 add ubuntu 9.04 line to you /etc/apt/sources.list
deb http://us.archive.ubuntu.com/ubuntu/ jaunty multiverse
deb http://us.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse
sudo apt-get update
sudo apt-get install sun-java5-jdk
(注意安裝會一直停留在閱讀sun的同意書上,使勁按確定都沒反應的(確定是文本不是按鈕),后來按鍵盤Tab解決。)
更改預設jdk的方法如下:同理,更改 默認的javac,方法為
update-alternatives --config java
update-alternatives --config javac
顯示如下,然后鍵入java-1.5.0-sun的 編號:
有 2 個選項可用于替換項 java (提供 /usr/bin/java)。
選擇 路徑 優先級 狀態
- 0 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 自動模式
1 /usr/lib/jvm/java-1.5.0-sun/jre/bin/java 53 手動模式
2 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 手動模式
查看當前的java版本:
java -version
java version “1.5.0_22”
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03)
Java HotSpot(TM) Client VM (build 1.5.0_22-b03, mixed mode, sharing)
最郁悶的是,在安裝好sun-java5-jdk之后,make的時候,出錯信息告訴我,Froyo已經改用Java 1.6了。
make一切順利,之后在out/host/linux-x86/bin下找到emulator,但卻無法執行,提示缺少AVD device,使用export ANDROID_PRODUCT_OUT=~/android/out/target/product/generic解決之。
8.JDK 1.6 + eclipse 3.6.2 + ADT 10.0.1
今天撿起許久不曾弄過的Android應用開發,重新來過。
1) JDK 1.6和eclipse 3.6.2順利安裝。
2) ADT 10.0.1的安裝碰到麻煩。在Eclipse的菜單欄Help->Install New Software中添加https://dl-ssl.google.com/android/eclipse/下載ADT時,發現還需要安裝其他的依賴模塊。
按照網上的文章說需要安裝如下依賴模塊:
Eclipse GEF - http://download.eclipse.org/tools/gef/updates/releases
Eclipse EMF - http://download.eclipse.org/modeling/emf/updates/releases
Eclipse GMF - http://download.eclipse.org/modeling/gmf/updates/releases
Eclipse Webtools - http://download.eclipse.org/webtools/updates
Google eclipse Plugin - http://dl.google.com/eclipse/plugin/3.6
但這些更新都很麻煩,而且有的和eclipse 3.6.2有沖突。一直都試不成功。
試了半天之后,終于發現其實不需要這么麻煩,可以按以下步驟操作:
1)在eclipse的官網下載Eclipse Modeling Tools (includes Incubating components),這個包已經包含了Eclipse Classic的內容,所以如果下載了它的話,就沒必要下載Eclipse Classic了。
2)下載WTP包,WTP就夠了,不需要WTP-SDK。
3)下載ADT 10.0.1。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: linux学习心得(一)
- 下一篇: android fm模块学习,Andro