androidstub
① android開發如何調試
能夠在eclipse上運行調試應用程序之前,你必須為它創建一個啟動項。啟動項指定哪個工程將被啟動,哪個activity開始工作,以及使用哪些模擬器選項等。
按照以下步驟為Eclipse版本的應用程序創建合適的啟動項:
打開啟動項管理工具。
在Eclipse 3.3 (Europa)的版本中,酌情選擇 Run > Open RunDialog... or Run > Open Debug Dialog... 。
在Eclipse3.4 (Ganymede)版本中,酌情選擇 Run > Run Configurations...or Run > Debug Configurations... 。
在左邊的工程類型列表選擇Android Application選擇,雙擊(或者點擊右鍵選擇new),創建一個新的啟動項。
輸入啟動項名稱。
在Android標簽中,瀏覽要開始的工程和Activity 。
在Target標簽中,設置想要顯示的屏幕及網路屬性,以及其他任何模擬器啟動選項。
你可以在Common標簽中設置更多的選項.
按下Apply保存啟動配置,或者按下Run或Debug()。
運行和調試應用程序
一旦你設定了工程和工程啟動配置,你就可以按照以下的說明運行和調試應用程序了。
從eclipse主菜單,根據情況選擇Run>Run 或者 Run>Debug,開始運行或者調試活動啟動項。
注意,這里活動啟動項是在運行配置管理中最最近一次選中的那個。它不一定就是在Eclipse Navigation 面板中選擇的程序(如果有的話)
設置和修改活動啟動項,可以使用啟動項管理工具。如何獲得啟動項管理工具可以參考創建一個啟動項
運行或調試應用程序將觸發以下動作:
啟動模擬器,如果他還沒有開始運行。
編譯工程, 如果在上次編譯的基礎上修改過代碼,將重新編譯。在模擬器上安裝應用程序。
Run選項,開始運行程序。
Debug 在"Wait for debugger "模式下啟動程序,然後打開調試窗口並將Eclipse java調試器和程序關聯。
利用其他IDEs和工具開發Android應用程序
通常我們使用安裝有ADT插件的eclipse Eclipse with the ADT plugin.來開發Android程序,這個插件將編輯,build和調試功能集成到IDE上。
然而,如果你想在其他的IDE上開發程序,例如IntelliJ,或者使用沒有ADT插件的eclipse也可以。SDK提供了安裝,編譯,調試應用程序所需要的工具。
創建一個android工程
Android SDK包含一個activityCreator的程序,它將為工程產生多個stub文件和一個build文件。你可以用這個程序創建一個新的 Android工程或者在現有代碼上創建工程,如SDK中包含的例子。對於linux 和Mac系統,SDK提供activityCreator.py,一個 Python腳本,Windows上則是activityCreator.bat一個批處理腳本。無論是哪種平台,用法是一樣的。
按以下步驟運行activityCreator創建Android工程:
在命令行下,切換到SDK下的tools/目錄下,為你的工程文件新建一個目錄。如果你是在現有代碼上創建工程,切換到程序的根目錄下。
運行activityCreator。在命令行下,你必須指定完全合格的類名作為參數。如果你是創建一個全新的工程,這個類代表的與它同名的stub類和腳本文件。如果是在現有代碼上創建工程,必須指定軟體包中其中一個Activity類的名稱。命令選項的腳本包括:
--out <folder> 設定輸出目錄。默認情況下輸出目錄為當前目錄。如果你想為工程文件創建一個新的目錄,可以使用這個選項來指向它。
--ide intellij, 在一個新的項目中生成IntelliJIDEA 工程文件。
這里有個例子:
~/android_linux_sdk/tools $ ./activityCreator.py --out myprojectyour.package.name.ActivityName
package: your.package.name
out_dir: myproject
activity_name: ActivityName
~/android_linux_sdk/tools $
activityCreator腳本生成以下文件和目錄(但是不能重寫已有文件):
AndroidManifest.xml 程序的清單文件,同時為工程指定Activity類。
build.xml 一個Ant文件,用來編譯/打包應用程序。
src/your/package/name/ActivityName.java 你指定的輸入Activity類。
your_activity.iml, your_activity.ipr, your_activity.iws [only with the-ide intelliJ flag] intelliJ工程文件
res/ 資源目錄.
src/ 源代碼目錄.
bin/ build腳本的輸出目錄.
現在你可以將開發文件夾移到任何地方,但是記住,必須使用tool/文件夾下的adb程序將文件發送到模擬器上。因此你需要在你工作環境和tools/文件夾之間活動。
當然你需要避免移動SDK目錄,因為它將打斷編譯腳本。(再重新build之前需要手動更新SDK的映射路徑)
編譯 android應用程序
使用activityCreator生成的Ant文件build.xml來編譯程序
如果你沒有,你可以通過Apache Ant home page得到Ant文件。安裝它,並確定它在你的可執行文件路徑下。
呼叫Ant之前,你需聲明JAVA_HOME環境變數,並將它設置為JDK的安裝路徑。
注 意:在windows上,JDK默認的安裝路徑為"ProgramFiles",這個路徑將會引起Ant失敗,因為路徑中間有空格。解決這個問題,你可以像這樣指定環境變數 JAVA_HOME:JAVA_HOME=c:\Prora~1\Java\ 然而簡單的解決方法是將JDK安裝在沒有空格的目錄下。例如:c:\java\jdk1.6.0_02.
如果你還沒有這么准備好,按照上面創建一個新的工程的介紹建立一個工程。
現在你可以為你的工程運行Ant編譯文件,只需在build.xml同文件夾下輸入ant即可。每次修改原文件或是資源,都需要重新運行ant,它將把最新版的應用程序打包以便deploy.
運行Android程序
運行一個編譯好的程序,你需要用adb工具將.apk文件載入到模擬器的/data/app/目錄下,用法如下面介紹。
啟動模擬器(命令行下運行sdk目錄下的/tools/emulator)。
模擬器切換到主畫面(最好不要在程序運行的時候向模擬器安裝程序,可以按home鍵離開應用程序)。
運 行adb,安裝myproject/bin./<appname>.apk文件。例如,安裝Lunar Lander 示例,命令行下,切換到SDK目錄下的/sample/LunarLander子目錄下,輸入../../tools/adbinstall bin/LunarLander.apk
在模擬器中,打開可執行程序列表,卷動屏幕,選中並啟動你的應用程序。
注意:當你第一次安裝一個Activity時,你可能需要在啟動項顯示之前,或者其它程序調用它之前重新啟動模擬器。因為軟體包管理工具通常只有在模擬器啟動時才能完全的審查manifests。
為程序附加調試器
這一節我們介紹如何在屏幕上顯示調試信息(例如CPU使用率),以及如何將IDE和模擬器上運行的程序關聯起來。
使用eclipse插件可以自動的生成調試器。但你也可以通過配置IDES來監聽調試埠得到調試信息。
啟動Dalvik Debug Monitor Server (DDMS) 工具 ,它在IDE和模擬器之間扮演著埠轉換服務的角色。?
設置模擬器調試配置選項。例如,等到調試信息被載入後才啟動應用程序。注意,很多調試選項無需DDMS也可以使用,例如模擬器上顯示CPU的使用效率,或者屏幕的刷新頻率。
配置IDE,使得調試時IDE與8700埠關聯 .how to set up Eclipse to debug your project. 包含以下信息。
配置IDE附加調試埠
DDMS將為每一個虛擬機分配一個特殊的調試埠,這個埠在模擬器上可以找到。你必須將你的IDE與此埠(虛擬機上信息欄中有列出這些埠)關聯或者是默認的埠8700。這樣可以使IDE 連接到模擬器上程序列表中的任一個程序。
你的IDE需要能夠關聯模擬器上正在運行的程序,顯示它的線程,並允許你掛起它,檢查它的狀態,設置斷點。如果你在開發設置面板選擇了「等待調試」,應用程序將等到Eclipse連接後才運行,所以你需要在連接之前設置斷點。
修改正在調試的程序,或者在當前程序運行時選擇「等待調試」將引起系統殺死這個應用程序。如果你的程序處於一種壞的狀態,你可以使用方式殺死它,方法很簡單,只需要設置和鉤掉復選框。
② Android源碼解析RPC系列(一)---Binder原理
看了幾天的Binder,決定有必要寫一篇博客,記錄一下學習成果,Binder是Android中比較綜合的一塊知識了,目前的理解只限於JAVA層。首先Binder是幹嘛用的?不用說,跨進程通信全靠它,操作系統的不同進程之間,數據不共享,對於每個進程來說,它都天真地以為自己獨享了整個系統,完全不知道其他進程的存在,進程之間需要通信需要某種系統機制才能完成,在Android整個系統架構中,採用了大量的C/S架構的思想,所以Binder的作用就顯得非常重要了,但是這種機制為什麼是Binder呢?在Linux中的RPC方式有管道,消息隊列,共享內存等,消息隊列和管道採用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開辟的緩存區中,然後再從內核緩存區拷貝到接收方緩存區,這樣就有兩次拷貝過程。共享內存不需要拷貝,但控制復雜,難以使用。Binder是個折中的方案,只需要拷貝一次就行了。其次Binder的安全性比較好,好在哪裡,在下還不是很清楚,基於安全性和傳輸的效率考慮,選擇了Binder。Binder的英文意思是粘結劑,Binder對象是一個可以跨進程引用的對象,它的實體位於一個進程中,這個進程一般是Server端,該對象提供了一套方法用以實現對服務的請求,而它的引用卻遍布於系統的各個進程(Client端)之中,這樣Client通過Binder的引用訪問Server,所以說,Binder就像膠水一樣,把系統各個進程粘結在一起了,廢話確實有點多。
為了從而保障了系統的安全和穩定,整個系統被劃分成內核空間和用戶空間
內核空間:獨立於普通的應用程序,可以訪問受保護的內存空間,有訪問底層硬體設備的所有許可權。
用戶空間:相對與內核空間,上層運用程序所運行的空間就是用戶空間,用戶空間訪問內核空間的唯一方式就是系統調用。一個4G的虛擬地址空間,其中3G是用戶空間,剩餘的1G是內核空間。如果一個用戶空間想與另外一個用戶空間進行通信,就需要內核模塊支持,這個運行在內核空間的,負責各個用戶進程通過Binder通信的內核模塊叫做Binder驅動,雖然叫做Binder驅動,但是和硬體並沒有什麼關系,只是實現方式和設備驅動程序是一樣的,提供了一些標准文件操作。
在寫AIDL的時候,一般情況下,我們有兩個進程,一個作為Server端提供某種服務,然後另外一個進程作為Client端,連接Server端之後,就 可以使用Server裡面定義的服務。這種思想是一種典型的C/S的思想。值得注意的是Android系統中的Binder自身也是C/S的架構,也有Server端與Client端。一個大的C/S架構中,也有一個小的C/S架構。
先籠統的說一下,在整個Binder框架中,由系列組件組成,分別是Client、Server、ServiceManager和Binder驅動程序,其中Client、Server和ServiceManager運行在用戶空間,Binder驅動程序運行內核空間。運行在用戶空間中的Client、Server和ServiceManager,是在三個不同進程中的,Server進程中中定義了服務提供給Client進程使用,並且Server中有一個Binder實體,但是Server中定義的服務並不能直接被Client使用,它需要向ServiceManager注冊,然後Client要用服務的時候,直接向ServiceManager要,ServiceManager返回一個Binder的替身(引用)給Client,這樣Client就可以調用Server中的服務了。
場景 :進程A要調用進程B裡面的一個draw方法處理圖片。
分析 :在這種場景下,進程A作為Client端,進程B做為Server端,但是A/B不在同一個進程中,怎麼來調用B進程的draw方法呢,首先進程B作為Server端創建了Binder實體,為其取一個字元形式,可讀易記的名字,並將這個Binder連同名字以數據包的形式通過Binder驅動發送給ServiceManager,也就是向ServiceManager注冊的過程,告訴ServiceManager,我是進程B,擁有圖像處理的功能,ServiceManager從數據包中取出名字和引用以一個注冊表的形式保留了Server進程的注冊信息。為什麼是以數據包的形式呢,因為這是兩個進程,直接傳遞對象是不行滴,只能是一些描述信息。現在Client端進程A聯系ServiceManager,說現在我需要進程B中圖像處理的功能,ServiceManager從注冊表中查到了這個Binder實體,但是呢,它並不是直接把這個Binder實體直接給Client,而是給了一個Binder實體的代理,或者說是引用,Client通過Binder的引用訪問Server。分析到現在,有個關鍵的問題需要說一下,ServiceManager是一個進程,Server是另一個進程,Server向ServiceManager注冊Binder必然會涉及進程間通信。當前實現的是進程間通信卻又要用到進程間通信,這就好象蛋可以孵出雞前提卻是要找只雞來孵蛋,確實是這樣的,ServiceManager中預先有了一個自己的Binder對象(實體),就是那隻雞,然後Server有個Binder對象的引用,就是那個蛋,Server需要通過這個Binder的引用來實現Binder的注冊。雞就一隻,蛋有很多,ServiceManager進程的Binder對象(實體)僅有一個,其他進程所擁有的全部都是它的代理。同樣一個Server端Binder實體也應該只有一個,對應所有Client端全部都是它的代理。
我們再次理解一下Binder是什麼?在Binder通信模型的四個角色裡面;他們的代表都是「Binder」,一個Binder對象就代表了所有,包括了Server,Client,ServiceManager,這樣,對於Binder通信的使用者而言,不用關心實現的細節。對Server來說,Binder指的是Binder實體,或者說是本地對象,對於Client來說,Binder指的是Binder代理對象,也就是Binder的引用。對於Binder驅動而言,在Binder對象進行跨進程傳遞的時候,Binder驅動會自動完成這兩種類型的轉換。
簡單的總結一下,通過上面一大段的分析,一個Server在使用的時候需要經歷三個階段
1、定義一個AIDL文件
Game.aidl
GameManager .aidl
2、定義遠端服務Service
在遠程服務中的onBind方法,實現AIDL介面的具體方法,並且返回Binder對象
3、本地創建連接對象
以上就是一個遠端服務的一般套路,如果是在兩個進程中,就可以進程通信了,現在我們分析一下,這個通信的流程。重點是GameManager這個編譯生成的類。
從類的關系來看,首先介面GameManager 繼承 IInterface ,IInterface是一個介面,在GameManager內部有一個內部類Stub,Stub繼承了Binder,(Binder實現了IBinder),並且實現了GameManager介面,在Stub中還有一個內部類Proxy,Proxy也實現了GameManager介面,一個整體的結構是這樣的
現在的問題是,Stub是什麼?Proxy又是什麼?在上面說了在Binder通信模型的四個角色裡面;他們的代表都是「Binder」,一個Binder對象就代表了所有,包括了Server,Clinet,ServiceManager,為了兩個進程的通信,系統給予的內核支持是Binder,在抽象一點的說,Binder是系統開辟的一塊內存空間,兩個進程往這塊空間裡面讀寫數據就行了,Stub從Binder中讀數據,Proxy向Binder中寫數據,達到進程間通信的目的。首先我們分析Stub。
Stub 類繼承了Binder ,說明了Stub有了跨進程傳輸的能力,實現了GameManager介面,說明它有了根據游戲ID查詢一個游戲的能力。我們在bind一個Service之後,在onServiceConnecttion的回調裡面,就是通過asInterface方法拿到一個遠程的service的。
asInterface調用queryLocalInterface。
mDescriptor,mOwner其實是Binder的成員變數,Stub繼承了Binder,在構造函數的時候,對著兩個變數賦的值。
如果客戶端和服務端是在一個進程中,那麼其實queryLocalInterface獲取的就是Stub對象,如果不在一個進程queryLocalInterface查詢的對象肯定為null,因為不同進程有不同虛擬機,肯定查不到mOwner對象的,所以這時候其實是返回的Proxy對象了。拿到Stub對象後,通常在onServiceConnected中,就把這個對象轉換成我們多定義AIDL介面。
比如我們這里會轉換成GameManager,有了GameManager對象,就可以調用後querryGameById方法了。如果是一個進程,那直接調用的是自己的querryGameById方法,如果不是一個進程,那調用了就是代理的querryGameById方法了。
看到其中關鍵的一行是
mRemote就是一個IBinder對象,相對於Stub,Proxy 是組合關系(HAS-A),內部有一個IBinder對象mRemote,Stub是繼承關系(IS-A),直接實現了IBinder介面。
transact是個native方法,最終還會回掉JAVA層的onTransact方法。
onTransact根據調用號(每個AIDL函數都有一個編號,在跨進程的時候,不會傳遞函數,而是傳遞編號指明調用哪個函數)調用相關函數;在這個例子裡面,調用了Binder本地對象的querryGameById方法;這個方法將結果返回給驅動,驅動喚醒掛起的Client進程裡面的線程並將結果返回。於是一次跨進程調用就完成了。
***Please accept mybest wishes for your happiness and success ! ***
③ android啟動後怎麼查看其裡面的進程和線程
1)一個 Android 程序開始運行時,會單獨啟動一個Process。
默認情況下,所有這個程序中的Activity或者Service都會跑在這個Process。
默認情況下,一個Android程序也只有一個Process,但一個Process下卻可以有許多個Thread。
2)一個 Android 程序開始運行時,就有一個主線程Main Thread被創建。該線程主要負責UI界面的顯示、更新和控制項交互,所以又叫UI Thread。
3)一個Android程序創建之初,一個Process呈現的是單線程模型--即MainThread,所有的任務都在一個線程中運行,所以,MainThread所調用的每一個函數,其耗時應該越短越好,而對於比較耗時的工作,應該交給子線程去做,以避免主線程(UI線程)被阻塞,導致程序出現ANR(Application not response)
一個Activity就運行在一個線程中嗎?或者編碼時,如果不是明確安排在不同線程中的兩個Activity,其就都是在同一個線程中?那從一個Activity跳轉到另一個Activity時,是不是跳出的那個Activity就處在睡眠狀態了?
【答】 每個Activity都有一個Process屬性,可以指定該Activity是屬於哪個進程的。當然如果不明確指明,應該就是從屬於默認進程(Application指定的,如其未指定,應該就是默認主進程)。
Android中有Task的概念,而同一個Task的各個Activity會形成一個棧,只有站定的Activity才有機會與用戶交互。
原文地址:Android中的進程與線程 原文作者:江鵬
當應用程序的組件第一次運行時,Android將啟動一個只有一個執行線程的Linux進程。默認,應用程序所有的組件運行在這個進程和線程中。然而,你可以安排組件運行在其他進程中,且你可以為進程衍生出其它線程。本文從下面幾點來介紹Android的進程與線程:
1、進程
組件運行於哪個進程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個process屬性可以指定組件運行在哪個進程中。這個屬性可以設置為每個組件運行在自己的進程中,或者某些組件共享一個進程而其他的不共享。他們還可以設置為不同應用程序的組件運行在同一個進程中——假設這些應用程序共享同一個Linux用戶ID且被分配了同樣的許可權。<application>元素也有process屬性,為所有的組件設置一個默認值。
所有的組件都在特定進程的主線程中實例化,且系統調用組件是由主線程派遣。不會為每個實例創建單獨的線程,因此,對應這些調用的方法——諸如View.onKeyDown()報告用用戶的行為和生命周期通知,總是運行在進程的主線程中。這意味著,沒有組件當被系統調用時應該執行很長時間或阻塞操作(如網路操作或循環計算),因為這將阻塞進程中的其它組件。你可以為長操作衍生獨立的線程。
public boolean onKeyDown(int keyCode,KeyEvent event):默認實現KeyEvent.Callback.onKeyMultiple(),當按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然後釋放時執行,如果視圖可用且可點擊。
參數
keyCode-表示按鈕被按下的鍵碼,來自KeyEvent
event-定義了按鈕動作的KeyEvent對象
返回值
如果你處理事件,返回true;如果你想下一個接收者處理事件,返回false。
當內存剩餘較小且其它進程請求較大內存並需要立即分配,Android要回收某些進程,進程中的應用程序組件會被銷毀。當他們再次運行時,會重新開始一個進程。
當決定終結哪個進程時,Android會權衡他們對用戶重要性的相對權值。例如,與運行在屏幕可見的活動進程相比(前台進程),它更容易關閉一個進程,它的活動在屏幕是不可見(後台進程)。決定是否終結進程,取決於運行在進程中的組件狀態。關於組件的狀態,將在後面一篇——組件生命周期中介紹。
2、線程
雖然你可能會將你的應用程序限制在一個進程中,但有時候你會需要衍生一個線程做一些後台工作。因為用戶界面必須很快地響應用戶的操作,所以活動寄宿的線程不應該做一些耗時的操作如網路下載。任何不可能在短時間完成的操作應該分配到別的線程。
線程在代碼中是用標準的Java線程對象創建的,Android提供了一些方便的類來管理線程——Looper用於在線程中運行消息循環、Handler用戶處理消息、HandlerThread用戶設置一個消息循環的線程。
Looper類
該類用戶在線程中運行消息循環。線程默認沒有消息循環,可以在線程中調用prepare()創建一個運行循環;然後調用loop()處理消息直到循環結束。大部分消息循環交互是通過Handler類。下面是一個典型的執行一個Looper線程的例子,分別使用prepare()和loop()創建一個初始的Handler與Looper交互:
1. Android中進程與進程、線程與線程之間如何通信?
1)一個 Android 程序開始運行時,會單獨啟動一個Process。
默認情況下,所有這個程序中的Activity或者Service都會跑在這個Process。
默認情況下,一個Android程序也只有一個Process,但一個Process下卻可以有許多個Thread。
2)一個 Android 程序開始運行時,就有一個主線程Main Thread被創建。該線程主要負責UI界面的顯示、更新和控制項交互,所以又叫UI Thread。
3)一個Android程序創建之初,一個Process呈現的是單線程模型--即MainThread,所有的任務都在一個線程中運行,所以,MainThread所調用的每一個函數,其耗時應該越短越好,而對於比較耗時的工作,應該交給子線程去做,以避免主線程(UI線程)被阻塞,導致程序出現ANR(Application not response)
一個Activity就運行在一個線程中嗎?或者編碼時,如果不是明確安排在不同線程中的兩個Activity,其就都是在同一個線程中?那從一個Activity跳轉到另一個Activity時,是不是跳出的那個Activity就處在睡眠狀態了?
【答】 每個Activity都有一個Process屬性,可以指定該Activity是屬於哪個進程的。當然如果不明確指明,應該就是從屬於默認進程(Application指定的,如其未指定,應該就是默認主進程)。
Android中有Task的概念,而同一個Task的各個Activity會形成一個棧,只有站定的Activity才有機會與用戶交互。
原文地址:Android中的進程與線程 原文作者:江鵬
當應用程序的組件第一次運行時,Android將啟動一個只有一個執行線程的Linux進程。默認,應用程序所有的組件運行在這個進程和線程中。然而,你可以安排組件運行在其他進程中,且你可以為進程衍生出其它線程。本文從下面幾點來介紹Android的進程與線程:
1、進程
組件運行於哪個進程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個process屬性可以指定組件運行在哪個進程中。這個屬性可以設置為每個組件運行在自己的進程中,或者某些組件共享一個進程而其他的不共享。他們還可以設置為不同應用程序的組件運行在同一個進程中——假設這些應用程序共享同一個Linux用戶ID且被分配了同樣的許可權。<application>元素也有process屬性,為所有的組件設置一個默認值。
所有的組件都在特定進程的主線程中實例化,且系統調用組件是由主線程派遣。不會為每個實例創建單獨的線程,因此,對應這些調用的方法——諸如View.onKeyDown()報告用用戶的行為和生命周期通知,總是運行在進程的主線程中。這意味著,沒有組件當被系統調用時應該執行很長時間或阻塞操作(如網路操作或循環計算),因為這將阻塞進程中的其它組件。你可以為長操作衍生獨立的線程。
public boolean onKeyDown(int keyCode,KeyEvent event):默認實現KeyEvent.Callback.onKeyMultiple(),當按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然後釋放時執行,如果視圖可用且可點擊。
參數
keyCode-表示按鈕被按下的鍵碼,來自KeyEvent
event-定義了按鈕動作的KeyEvent對象
返回值
如果你處理事件,返回true;如果你想下一個接收者處理事件,返回false。
當內存剩餘較小且其它進程請求較大內存並需要立即分配,Android要回收某些進程,進程中的應用程序組件會被銷毀。當他們再次運行時,會重新開始一個進程。
當決定終結哪個進程時,Android會權衡他們對用戶重要性的相對權值。例如,與運行在屏幕可見的活動進程相比(前台進程),它更容易關閉一個進程,它的活動在屏幕是不可見(後台進程)。決定是否終結進程,取決於運行在進程中的組件狀態。關於組件的狀態,將在後面一篇——組件生命周期中介紹。
2、線程
雖然你可能會將你的應用程序限制在一個進程中,但有時候你會需要衍生一個線程做一些後台工作。因為用戶界面必須很快地響應用戶的操作,所以活動寄宿的線程不應該做一些耗時的操作如網路下載。任何不可能在短時間完成的操作應該分配到別的線程。
線程在代碼中是用標準的Java線程對象創建的,Android提供了一些方便的類來管理線程——Looper用於在線程中運行消息循環、Handler用戶處理消息、HandlerThread用戶設置一個消息循環的線程。
Looper類
該類用戶在線程中運行消息循環。線程默認沒有消息循環,可以在線程中調用prepare()創建一個運行循環;然後調用loop()處理消息直到循環結束。大部分消息循環交互是通過Handler類。下面是一個典型的執行一個Looper線程的例子,分別使用prepare()和loop()創建一個初始的Handler與Looper交互:
2.1、遠程過程調用(Remote procere calls,RPCs)
Android有一個輕量級的遠程過程調用機制——方法在本地調用卻在遠程(另外一個進程中)執行,結果返回給調用者。這需要將方法調用和它伴隨的數據分解為操作系統能夠理解的層次,從本地進程和地址空間傳輸到遠程進程和地址空間,並重新組裝調用。返回值以相反方向傳輸。Android提供了做這些工作的所有代碼,這樣我們可以專注於定義和執行RPC介面本身。
一個RPC介面僅包含方法。所有的方法同步地執行(本地方法阻塞直到遠程方法執行完成),即使是沒有返回值。簡言之,該機制工作原理如下:首先,你用簡單的IDL(interface definition language,介面定義語言)聲明一個你想實現的RPC介面。從這個聲明中,aidl工具生成一個Java介面定義,提供給本地和遠程進程。它包含兩個內部類,如下圖所示:
內部類有管理你用IDL定義的介面的遠程過程調用所需要的所有代碼。這兩個內部類都實現了IBinder介面。其中之一就是在本地由系統內部使用,你寫代碼可以忽略它。另外一個是Stub,擴展自Binder類。除了用於有效地IPC(interprocess communication)調用的內部代碼,內部類在RPC介面聲明中還包含方法聲明。你可以定義Stub的子類實現這些方法,如圖中所示。
通常情況下,遠程過程有一個服務管理(因為服務能通知系統關於進程和它連接的其它進程的信息)。它有由aidl工具生成的介面文件和Stub子類實現的RPC方法。服務的客戶端僅有由aidl工具生成的介面文件。
下面介紹服務如何與它的客戶端建立連接:
· 服務的客戶端(在本地端的)應該實現onServiceConnected() 和onServiceDisconnected() 方法,因此當與遠程服務建立連接成功和斷開連接是會通知它。然後調用bindService() 建立連接。
· 服務的onBind()方法將實現為接受或拒絕連接,者取決於它接受到的意圖(該意圖傳送到binServive())。如果連接被接受,它返回一個Stub子類的實例。
· 如果服務接受連接,Android調用客戶端的onServiceConnected()方法且傳遞給它一個IBinder對象,返回由服務管理的Stub子類的一個代理。通過代理,客戶端可以調用遠程服務。
這里只是簡單地描述,省略了一些RPC機制的細節。你可以查閱相關資料或繼續關注Android開發之旅,後面將為你奉上。
2.2、線程安全方法
在一些情況下,你實現的方法可能會被不止一個線程調用,因此必須寫成線程安全的。這對遠程調用方法是正確的——如上一節討論的RPC機制。當從IBinder進程中調用一個IBinder對象中實現的一個方法,這個方法在調用者的線程中執行。然而,當從別的進程中調用,方法將在Android維護的IBinder進程中的線程池中選擇一個執行,它不在進程的主線程中執行。例如,一個服務的onBind()方法在服務進程的主線程中被調用,在onBind()返回的對象中執行的方法(例如,實現RPC方法的Stub子類)將在線程池中被調用。由於服務可以有一個以上的客戶端,所以同時可以有一個以上的線程在執行同一個IBinder方法。因此,IBinder的方法必須是線程安全的。
同樣,一個內容提供者可以接受其它進程產生的數據請求。雖然ContentResolver 和 ContentProvider 類隱藏進程通信如何管理的,對應哪些請求的ContentResolver 方法——query()、insert()、delete()、update()、getType(),在內容提供者的進程的線程池中被調用,而不是在這一進程的主線程中。因為這些方法可以同時從任意數量的線程中調用,他們也必須實現為線程安全的。
④ Android service 中的stub類是什麼意思
stub是為了方便client,service交互而生成出來的代碼。
AIDL(android 介面描述語言)是一個IDL語言,它可以生成一段代碼,可以使在一個android設備上運行的兩個進程使用內部通信進程進行交互。如果你需要在一個進程中(例如:在一個Activity中)訪問另一個進程中(例如:一個Service)某個對象的方法,你就可以使用AIDL來生成這樣的代碼來偽裝傳遞各種參數。
要使用AIDL,Service需要以aidl文件的方式提供服務介面,AIDL工具將生成一個相應的java介面,並且在生成的服務介面中包含一個功能調用的stub服務樁類。Service的實現類需要去繼承這個stub服務樁類。Service的onBind方法會返回實現類的對象,之後你就可以使用它了。
交互過程client<-->proxy<-->stub<-->service
stub和proxy是為了方便client/service交互而生成出來的代碼,這樣client/service的代碼就會比較干凈,不會嵌入很多很難懂的與業務無關的代碼
⑤ 安卓的安全機制
Android以Linux操作系統內核為基礎,實現硬體設備驅動、進程和內存管理、網路協議棧、電源管理等核心系統功能。除此以外,Android還增加了一些面向移動設備的特有功能,如低內存管理LMK(Low Memory Killer)、匿名共享內存(Ashmem: Anonymous Shared Memory),以及進程間通信Binder機制。這些功能的增強進一步提升了Android在內存管理、進程間通信等方面的安全性。
Android之前的版本並不存在硬體抽象層。鑒於硬體廠商並不希望公開其設備驅動的源代碼,Google對此將Linux內核驅動程序進行封裝,屏蔽掉底層的實現細節,向上提供統一的介面,這就是硬體抽象層。
HAL(Hardware Abstraction Layer)規定了一套應用層對硬體層的讀寫和配置的統一介面,本質上是將硬體的驅動分為用戶空間和內核空間,其中內核驅動程序運行在內核空間,HAL運行在用戶空間。上圖中的Stub,以so庫的形式存在,可以理解為proxy。上層通過調用標識獲得HAL的相關Stub,進而取得相應操作。
系統運行時庫由系統類庫和Android運行時構成。系統類庫基本上用C/C++編寫,基本功能說明如下:
當然,還有Android NDK(Native Development Kit),使得應用程序可以不依賴Dalvik虛擬機進行開發。Android運行時核心庫提供android.os, android.net, android.media等核心API,而Dalvik虛擬機依賴Linux內核,實現進程隔離與線程調度管理、安全與異常管理、垃圾回收等功能,並被改進以適應低內存、低處理器速度的移動設備環境。
再往上就是應用程序框架層了。一系列的Android應用程序所需的類庫,使得開發人員可以快速地進行程序開發,也可以通過繼承實現個性化的擴展。如Activity Manager負責主線程ActivityThread的創建、Activity生命周期的維護,並為窗口提供交互的介面。
應用層就是與用戶直接交互的應用程序,如SMS簡訊、圖片瀏覽器、地圖以及開發人員所開發的應用程序。
⑥ android應用程序開發中run和debug 有什麼區別
能夠在eclipse上運行調試應用程序之前,你必須為它創建一個啟動項。啟動項指定哪個工程將被啟動,哪個activity開始工作,以及使用哪些模擬器選項等。
按照以下步驟為Eclipse版本的應用程序創建合適的啟動項:
打開啟動項管理工具。
在Eclipse 3.3 (Europa)的版本中,酌情選擇 Run > Open RunDialog... or Run > Open Debug Dialog... 。
在Eclipse3.4 (Ganymede)版本中,酌情選擇 Run > Run Configurations...or Run > Debug Configurations... 。
在左邊的工程類型列表選擇Android Application選擇,雙擊(或者點擊右鍵選擇new),創建一個新的啟動項。
輸入啟動項名稱。
在Android標簽中,瀏覽要開始的工程和Activity 。
在Target標簽中,設置想要顯示的屏幕及網路屬性,以及其他任何模擬器啟動選項。
你可以在Common標簽中設置更多的選項.
按下Apply保存啟動配置,或者按下Run或Debug()。
運行和調試應用程序
一旦你設定了工程和工程啟動配置,你就可以按照以下的說明運行和調試應用程序了。
從eclipse主菜單,根據情況選擇Run>Run 或者 Run>Debug,開始運行或者調試活動啟動項。
注意,這里活動啟動項是在運行配置管理中最最近一次選中的那個。它不一定就是在Eclipse Navigation 面板中選擇的程序(如果有的話)
設置和修改活動啟動項,可以使用啟動項管理工具。如何獲得啟動項管理工具可以參考創建一個啟動項
運行或調試應用程序將觸發以下動作:
啟動模擬器,如果他還沒有開始運行。
編譯工程, 如果在上次編譯的基礎上修改過代碼,將重新編譯。在模擬器上安裝應用程序。
Run選項,開始運行程序。
Debug 在"Wait for debugger "模式下啟動程序,然後打開調試窗口並將Eclipse Java調試器和程序關聯。
利用其他IDEs和工具開發Android應用程序
通常我們使用安裝有ADT插件的eclipse Eclipse with the ADT plugin.來開發Android程序,這個插件將編輯,build和調試功能集成到IDE上。
然而,如果你想在其他的IDE上開發程序,例如IntelliJ,或者使用沒有ADT插件的eclipse也可以。SDK提供了安裝,編譯,調試應用程序所需要的工具。
創建一個android工程
Android SDK包含一個activityCreator的程序,它將為工程產生多個stub文件和一個build文件。你可以用這個程序創建一個新的 Android工程或者在現有代碼上創建工程,如SDK中包含的例子。對於Linux 和Mac系統,SDK提供activityCreator.py,一個 Python腳本,Windows上則是activityCreator.bat一個批處理腳本。無論是哪種平台,用法是一樣的。
按以下步驟運行activityCreator創建Android工程:
在命令行下,切換到SDK下的tools/目錄下,為你的工程文件新建一個目錄。如果你是在現有代碼上創建工程,切換到程序的根目錄下。
運行activityCreator。在命令行下,你必須指定完全合格的類名作為參數。如果你是創建一個全新的工程,這個類代表的與它同名的stub類和腳本文件。如果是在現有代碼上創建工程,必須指定軟體包中其中一個Activity類的名稱。命令選項的腳本包括:
--out <folder> 設定輸出目錄。默認情況下輸出目錄為當前目錄。如果你想為工程文件創建一個新的目錄,可以使用這個選項來指向它。
--ide intellij, 在一個新的項目中生成IntelliJIDEA 工程文件。
這里有個例子:
~/android_linux_sdk/tools $ ./activityCreator.py --out myprojectyour.package.name.ActivityName
package: your.package.name
out_dir: myproject
activity_name: ActivityName
~/android_linux_sdk/tools $
activityCreator腳本生成以下文件和目錄(但是不能重寫已有文件):
AndroidManifest.xml 程序的清單文件,同時為工程指定Activity類。
build.xml 一個Ant文件,用來編譯/打包應用程序。
src/your/package/name/ActivityName.java 你指定的輸入Activity類。
your_activity.iml, your_activity.ipr, your_activity.iws [only with the-ide intelliJ flag] intelliJ工程文件
res/ 資源目錄.
src/ 源代碼目錄.
bin/ build腳本的輸出目錄.
現在你可以將開發文件夾移到任何地方,但是記住,必須使用tool/文件夾下的adb程序將文件發送到模擬器上。因此你需要在你工作環境和tools/文件夾之間活動。
當然你需要避免移動SDK目錄,因為它將打斷編譯腳本。(再重新build之前需要手動更新SDK的映射路徑)
編譯 android應用程序
使用activityCreator生成的Ant文件build.xml來編譯程序
如果你沒有,你可以通過Apache Ant home page得到Ant文件。安裝它,並確定它在你的可執行文件路徑下。
呼叫Ant之前,你需聲明JAVA_HOME環境變數,並將它設置為JDK的安裝路徑。
注 意:在windows上,JDK默認的安裝路徑為"ProgramFiles",這個路徑將會引起Ant失敗,因為路徑中間有空格。解決這個問題,你可以像這樣指定環境變數 JAVA_HOME:JAVA_HOME=c:\Prora~1\Java\ 然而簡單的解決方法是將JDK安裝在沒有空格的目錄下。例如:c:\java\jdk1.6.0_02.
如果你還沒有這么准備好,按照上面創建一個新的工程的介紹建立一個工程。
現在你可以為你的工程運行Ant編譯文件,只需在build.xml同文件夾下輸入ant即可。每次修改原文件或是資源,都需要重新運行ant,它將把最新版的應用程序打包以便deploy.
運行Android程序
運行一個編譯好的程序,你需要用adb工具將.apk文件載入到模擬器的/data/app/目錄下,用法如下面介紹。
啟動模擬器(命令行下運行sdk目錄下的/tools/emulator)。
模擬器切換到主畫面(最好不要在程序運行的時候向模擬器安裝程序,可以按home鍵離開應用程序)。
運 行adb,安裝myproject/bin./<appname>.apk文件。例如,安裝Lunar Lander 示例,命令行下,切換到SDK目錄下的/sample/LunarLander子目錄下,輸入../../tools/adbinstall bin/LunarLander.apk
在模擬器中,打開可執行程序列表,卷動屏幕,選中並啟動你的應用程序。
注意:當你第一次安裝一個Activity時,你可能需要在啟動項顯示之前,或者其它程序調用它之前重新啟動模擬器。因為軟體包管理工具通常只有在模擬器啟動時才能完全的審查manifests。
為程序附加調試器
這一節我們介紹如何在屏幕上顯示調試信息(例如CPU使用率),以及如何將IDE和模擬器上運行的程序關聯起來。
使用eclipse插件可以自動的生成調試器。但你也可以通過配置IDES來監聽調試埠得到調試信息。
啟動Dalvik Debug Monitor Server (DDMS) 工具 ,它在IDE和模擬器之間扮演著埠轉換服務的角色。?
設置模擬器調試配置選項。例如,等到調試信息被載入後才啟動應用程序。注意,很多調試選項無需DDMS也可以使用,例如模擬器上顯示CPU的使用效率,或者屏幕的刷新頻率。
配置IDE,使得調試時IDE與8700埠關聯 .how to set up Eclipse to debug your project. 包含以下信息。
配置IDE附加調試埠
DDMS將為每一個虛擬機分配一個特殊的調試埠,這個埠在模擬器上可以找到。你必須將你的IDE與此埠(虛擬機上信息欄中有列出這些埠)關聯或者是默認的埠8700。這樣可以使IDE 連接到模擬器上程序列表中的任一個程序。
你的IDE需要能夠關聯模擬器上正在運行的程序,顯示它的線程,並允許你掛起它,檢查它的狀態,設置斷點。如果你在開發設置面板選擇了「等待調試」,應用程序將等到Eclipse連接後才運行,所以你需要在連接之前設置斷點。
修改正在調試的程序,或者在當前程序運行時選擇「等待調試」將引起系統殺死這個應用程序。如果你的程序處於一種壞的狀態,你可以使用方式殺死它,方法很簡單,只需要設置和鉤掉復選框。
⑦ android stub.asinterface是什麼意思
參考如下博客內容:
IxxxxService.Stub.asInterface(IBinder obj) :
這個函數是幹啥用呢?首先當bindService之後,客戶端會得到一個Binder引用,是Binder 喲,不是IxxxxService.Proxy實例,那這樣的話,我們第一個想法是利用Binder引用作為參數實例化出一個IxxxxService.Proxy。Ok, 但如果服務端和客戶端都是在同一個進程呢,還需要利用IPC嗎?這樣就不需要了,直接將IxxxxService當做普通的對象調用就成了。Google 的同志們他們利用IxxxxService.Stub.asInterface函數對這兩種不同的情況進行了統一,也就是不管你是在同一進程還是不同進程,那麼在拿到Binder引用後,調用IxxxxService.Stub.asInterface(IBinder obj) 即可得到一個IxxxxService 實例,然後你只管調用IxxxxService里的函數就成了。
⑧ Android常見知識點
跳槽無非就是錢少了或不爽了,無論怎麼樣,記住:
不要裸辭!
不要裸辭!
不要裸辭!
為什麼呢?
1、裸辭就沒有錢拿了,還不如騎驢找馬。
2、裸辭之後如果一個月內沒有找到工作,那麼社保就會斷了,除非你自己找渠道交了。
3、裸辭之後真的會很頹廢!
當初還在上班的時候就想著,裸辭了,首先花幾天時間吧簡歷完善一下,把知識點惡補一下,然後投簡歷,面試,妥妥的妥妥。
結果呢?每次裸辭之後都是:
首先躺屍一個星期;
然後用了一個星期才慢吞吞的改完簡歷;
然後海投,沒回復,修改簡歷;
再次海投,面試,被虐得體無完膚,懷疑人生;
再改簡歷,再海投,一不小心中了。
當然海投也是有個目標范圍的。
如果不是裸辭,那麼現在應該還是在公司上班,在完成工作之餘,就會逼著自己復習知識點了,起碼不會在家墮落。在家不上班就是睡覺、看電影,檣櫓灰飛煙滅,所以不要裸辭。
然並卵,我依然裸辭了。請假面試真的很煩。
onPause,假如從ActivityA啟動B,如果B是透明的,則不會回調A的onStop方法。
方法一:
方法二:
1、寫好動畫文件 R.anim.enter 、 R.anim.exit
2、調用 overridePendingTransition 設置動畫
引申:如Activity設置為singleInstance,則應該怎麼設置跳轉動畫?
1、 startService 啟動方與Service並沒有關聯,只有當Service調用 stopSelf 或者其它組件調用 stopService 的時候服務才會終止。
2、 bindService 啟動方綁定Service,並且可以通過Binder與之交互,當啟動方銷毀時,也會自動unbindService,當所有啟動方都unbindService之後,Service也就自動銷毀了。
為什麼呢?官方文檔是這樣寫的:
大概意思是 onReceive() 執行完畢之後,它所在的進程就會變成低優先順序進程,極易被系統殺死。
分兩種情況分析一下:
一、收到廣播的時候,應用正在運行:
此時如果沒有在Manifest中設置了獨立進程,則 onReceive() 就直接在主進程主線程執行,這里很明顯不能執行耗時操作。
二、收到廣播的時候,應用沒有啟動:
這時候系統會啟動一個進程去執行 onReceive() ,(如果Manifest中沒有設置進程名,則進程名為包名),(插一句,所有進程都會創建一個Application實例),當onReceive執行完畢之後,此進程就變成低優先順序了,隨時有可能被系統殺死,如果你在onReceive裡面啟動了線程執行耗時任務,那很有可能子線程沒執行完畢,進程就被殺死了,進程沒了,線程自然就掛了。
那麼確實要執行耗時操作呢,怎麼辦?
方法一:goAsync()
方法二:schele a JobService from the receiver using the JobScheler
三種實現方法
1、繼承現有的組件,如TextView等,進行拓展。
2、繼承ViewGroup,自定義布局。
3、繼承View,在onDraw()中描繪。
onMeasure()
onLayout()
onDraw()
其它
attachToRoot 從字面理解就是是否綁定到 root 上面去了。
1、 attachToRoot=true :則返回的view為root的子view;
2、 attachToRoot=false :則返回的view是個單獨的view,傳入的root只是提供一些參數給view使用而已。
那麼這里不傳入 attachToRoot 呢?那就看root是否為空了,如果傳入root不為空,則默認綁定到root,作為root的子view返回。
也就是所謂的Frame動畫。指通過指定每一幀的圖片和播放時間,有序的進行播放而形成動畫效果。
可以通過插入器 Interpolator 控制動畫的變化速度。
也就是所謂補間動畫。指通過指定View的初始狀態、變化時間、方式,通過一系列的演算法去進行圖形變換,從而形成動畫效果,主要有 AlphaAnimation 、 TranslateAnimation 、 ScaleAnimation 、 RotateAnimation 四種。
注意:只是在視圖層實現了動畫效果,並沒有真正改變View的屬性。
屬性動畫,通過不斷的改變View的屬性,不斷的重繪而形成動畫效果。相比於視圖動畫,View的屬性是真正改變了。
注意:Android 3.0(API 11)以上才支持。
最常用的類有 ObjectAnimator
P.S. 我不明白cancel存在的意義。
另外, DialogFragment 是沒有cancel的。
ping
內存大致分為三個區:棧區、堆區、方法區。
棧區
堆區
方法區
JAVA不允許手動釋放內存,只能通過垃圾回收程序不定期對那些不再被引用的對象進行回收。
那麼怎麼判斷哪些對象需要回收?
1、引用計數法
就是給對象添加一個引用計數器,引用對象時+1,引用失效時-1。但是這種方法解決不了對象相互引用的情況。
2、可達性分析法
通過一系列「GCRoots」對象作為起點進行搜索,當GCRoots和一個對象之間沒有可達路徑,則認為此對象不可用,但是不可用不一定會成為可回收對象。
編寫AIDL文件,定義介面。
編譯生成JAVA文件。
定義進程級Service,onBind中返回Interface.Stub()。
onServiceConnected中Interface aidl = Interface.Stub.asInterface(service);
把已修復的class文件打包成dex文件,網路傳輸到用戶手機中,利用類載入器把這些類載入到類隊列的前面即可。
【未完待續】
如果公司錄用我,不管是三年還是五年,首先我都會先把公司的任務做好,然後不斷深入研究Android的相關技術,特別是Android源碼,了解Android底層原理,以便更好的優化性能,避免一些不必要的奇葩問題,還有就是研究一些新的框架的原理,學習別人的思維。最後就是學習周邊語言,比如後台,前端等等。
⑨ android中 throw new RuntimeException("Stub!");是干什麼用的為什麼幾乎每個介面函數里都有謝謝!
拋出運行時異常