在manifest文件里->activity 添加
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*">
</intent-filter>
這樣就把當前程序注冊為 可以打開/查看所有類型的文件. 或者要查看jpeg, mimeType要改為: image/jpeg
當在文件管理器里點擊任何文件, 系統都會試圖去執行你的程序.
轉自 http://chaozhong84.spaces.live.com/blog/cns!FC149E9A3FC0182B!297.trak
【Android】【轉】Android Log Analysis
---------------------------------------------------
本文原創,轉載請注明出處,如有錯誤之處歡迎指出
---------------------------------------------------
Get Log from Android System
adb bugreport > bugreport.txt
copy bugreport to the current directory.
bugreport里面包含了各種log信息,大部分log也可以通過直接運行相關的程序來直接獲得.
步驟如下:
1.adb shell 2.進入相關工具程式的目錄 3.執行相關程式 4.得到相關信息
下面以輸出進程信息為例 1.adb shell 2.輸入ps -P 3.可以看到相關進程信息
Log Archive Analysis
1.bugreport
bugreport記錄android啟動過程的log,以及啟動后的系統狀態,包括進程列表,內存信息,VM信息等等到.
2.bugreport結構分析
(1)dumpstate
MEMORY INFO
獲取該log:讀取文件/proc/meminfo
系統內存使用狀態
CPU INFO
獲取該log:執行/system/bin/top -n 1 -d 1 -m 30 -t
系統CPU使用狀態
PROCRANK
獲取該log:執行/system/bin/procrank
執行/system/xbin/procrank后輸出的結果,查看一些內存使用狀態
VIRTUAL MEMORY STATS
獲取該log:讀取文件/proc/vmstat
虛擬內存分配情況
vmalloc申請的內存則位于vmalloc_start~vmalloc_end之間,與物理地址沒有簡單的轉換關系,雖然在邏輯上它們也是連續的,但是在物理上它們不要求連續。
VMALLOC INFO
獲取該log:讀取文件/proc/vmallocinfo
虛擬內存分配情況
SLAB INFO
獲取該log:讀取文件/proc/slabinfo
SLAB是一種內存分配器.這里輸出該分配器的一些信息
ZONEINFO
獲取該log:讀取文件/proc/zoneinfo
zone info
SYSTEM LOG(需要著重分析)
獲取該log:執行/system/bin/logcat -v time -d *:v
會輸出在程序中輸出的Log,用于分析系統的當前狀態
VM TRACES
獲取該log:讀取文件/data/anr/traces.txt
因為每個程序都是在各自的VM中運行的,這個Log是現實各自VM的一些traces
EVENT LOG TAGS
獲取該log:讀取文件/etc/event-log-tags
EVENT LOG
獲取該log:執行/system/bin/logcat -b events -v time -d *:v
輸出一些Event的log
RADIO LOG
獲取該log:執行/system/bin/logcat -b radio -v time -d *:v
顯示一些無線設備的鏈接狀態,如GSM,PHONE,STK(Satellite Tool Kit)...
NETWORK STATE
獲取該log:執行/system/bin/netcfg (得到網絡鏈接狀態)
獲取該log:讀取文件/proc/net/route (得到路由狀態)
顯示網絡鏈接和路由
SYSTEM PROPERTIES
獲取該log:參考代碼實現
顯示一些系統屬性,如Version,Services,network...
KERNEL LOG
獲取該log:執行/system/bin/dmesg
顯示Android內核輸出的Log
KERNEL WAKELOCKS
獲取該log:讀取文件/proc/wakelocks
內核對一些程式和服務喚醒和休眠的一些記錄
KERNEL CPUFREQ
(Linux kernel CPUfreq subsystem) Clock scaling allows you to change the clock speed of the CPUs on the fly.
This is a nice method to save battery power, because the lower the clock speed is, the less power the CPU consumes.
PROCESSES
獲取該log:執行ps -P
顯示當前進程
PROCESSES AND THREADS
獲取該log:執行ps -t -p -P
顯示當前進程和線程
LIBRANK
獲取該log:執行/system/xbin/librank
剔除不必要的library
BINDER FAILED TRANSACTION LOG
獲取該log:讀取文件/proc/binder/failed_transaction_log
BINDER TRANSACTION LOG
獲取該log:讀取文件/proc/binder/transaction_log
BINDER TRANSACTIONS
獲取該log:讀取文件/proc/binder/transactions
BINDER STATS
獲取該log:讀取文件/proc/binder/stats
BINDER PROCESS STATE
獲取該log:讀取文件/proc/binder/proc/*
bind相關的一些狀態
FILESYSTEMS
獲取該log:執行/system/bin/df
主要文件的一些容量使用狀態(cache,sqlite,dev...)
PACKAGE SETTINGS
獲取該log:讀取文件/data/system/packages.xml
系統中package的一些狀態(訪問權限,路徑...),類似Windows里面的一些lnk文件吧.
PACKAGE UID ERRORS
獲取該log:讀取文件/data/system/uiderrors.txt
錯誤信息
KERNEL LAST KMSG LOG
最新kernel message log
LAST RADIO LOG
最新radio log
KERNEL PANIC CONSOLE LOG
KERNEL PANIC THREADS LOG
控制臺/線程的一些錯誤信息log
BACKLIGHTS
獲取該log:獲取LCD brightness讀/sys/class/leds/lcd-backlight/brightness
獲取該log:獲取Button brightness讀/sys/class/leds/button-backlight/brightness
獲取該log:獲取Keyboard brightness讀/sys/class/leds/keyboard-backlight/brightness
獲取該log:獲取ALS mode讀/sys/class/leds/lcd-backlight/als
獲取該log:獲取LCD driver registers讀/sys/class/leds/lcd-backlight/registers
獲取相關亮度的一些信息
(2)build.prop
VERSION INFO輸出下列信息
當前時間
當前內核版本:可以讀取文件(/proc/version)獲得
顯示當前命令:可以讀取文件夾(/proc/cmdline)獲得
顯示系統build的一些屬性:可以讀取文件(/system/build.prop)獲得
輸出系統一些屬性
gsm.version.ril-impl
gsm.version.baseband
gsm.imei
gsm.sim.operator.numeric
gsm.operator.alpha
(3)dumpsys
執行/system/bin/dumpsys后可以獲得這個log.
經常會發現該log輸出不完整,因為代碼里面要求該工具最多只執行60ms,可能會導致log無法完全輸出來.
可以通過修改時間參數來保證log完全輸出.
信息:
Currently running services
DUMP OF SERVICE services-name(running)
Log Code Analysis
Site: ."frameworks"base"cmds"dumpstate"
相關Log程序的代碼可以從上面目錄獲取
Log Analysis Experience
分析步驟
1.查看一些版本信息
確認問題的系統環境
2.查看CPU/MEMORY的使用狀況
看是否有內存耗盡,CPU繁忙這樣的背景情況出現.
3.分析traces
因為traces是系統出錯以后輸出的一些線程堆棧信息,可以很快定位到問題出在哪里.
4.分析SYSTEM LOG
系統Log詳細輸出各種log,可以找出相關log進行逐一分析
實例分析
下面分析我寫的一個測試例子,在OnCreate做一個死循環,這樣主線程會被鎖住,在按下硬件的Back之后會出現ANR的錯誤.
在traces中發現該程序的堆棧信息如下:
----- pid 20597 at 2010-03-15 01:29:53 -----
Cmd line: com.android.test
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=N obj=0x2aac6240 self=0xbda8
| sysTid=20597 nice=0 sched=0/0 cgrp=default handle=1877232296
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1306)
at java.lang.Thread.sleep(Thread.java:1286)
at android.os.SystemClock.sleep(SystemClock.java:114)
at com.android.test.main.onCreate(main.java:20)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
at android.app.ActivityThread.access$2200(ActivityThread.java:119)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #2" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c260 self=0x143860
| sysTid=20601 nice=0 sched=0/0 cgrp=default handle=1211376
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c1a0 self=0x14c980
| sysTid=20600 nice=0 sched=0/0 cgrp=default handle=1207920
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=N obj=0x2fb7a1e8 self=0x126cc0
| sysTid=20599 nice=0 sched=0/0 cgrp=default handle=1269048
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=N obj=0x2e31daf0 self=0x135c08
| sysTid=20598 nice=0 sched=0/0 cgrp=default handle=1268528
at dalvik.system.NativeStart.run(Native Method)
----- end 20597 -----
該文件的堆棧結構從下往上進行分析
(1)棧底at dalvik.system.NativeStart.run(Native Method)
系統為當前的task(應用程式)啟動一個專用的虛擬機
(2) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
Activity Services是在后臺負責管理Activity,它此時將測試例子的Activity啟動起來了
(3)at com.android.test.main.onCreate(main.java:20)
啟動測試程序
(4)棧頂at java.lang.VMThread.sleep(Native Method)
線程被sleep掉了,所以無法響應用戶,出現ANR錯誤.
上面是對一個非常簡單的問題的分析.
如果遇到比較復雜的問題還需要詳細分析SYSTEM LOG.
1.比如網絡異常,要通過SYSTEM LOG里面輸出的網絡鏈接信息來判斷網絡狀態
2.數據傳輸,網絡鏈接等耗時的操作需要分析SYSTEM LOG里面ActivityManager的響應時間
(1) Looper類別用來為一個線程開啟一個消息循環。默認情況下Android中新誕生的線程是沒有開啟消息循環的。(主線程除外,主線程系統會自動為其創建Looper對象,開啟消息循環)
Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。
(2) 通常是通過Handler對象來與Looper交互的。Handler可看做是Looper的一個接口,用來向指定的Looper發送消息及定義處理方法。
默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,在主線程中定義,其是與主線程的Looper綁定。
mainHandler = new Handler() 等價于new Handler(Looper.myLooper()).
Looper.myLooper():Return the Looper object associated with the current thread 獲取當前進程的looper對象。
還有一個類似的 Looper.getMainLooper() 用于獲取主線程的Looper對象。
(3) 在非主線程中直接new Handler() 會報如下的錯誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主線程中默認沒有創建Looper對象,需要先調用Looper.prepare()啟用Looper。
(4) Looper.loop(); 讓Looper開始工作,從消息隊列里取消息,處理消息。
注意:寫在Looper.loop()之后的代碼不會被執行,這個函數內部應該是一個循環,當調用mHandler.getLooper().quit()后,loop才會中止,其后的代碼才能得以運行。
(5) 基于以上知識,可實現主線程給子線程(非主線程)發送消息。
把下面例子中的mHandler聲明成類成員,在主線程通過mHandler發送消息即可。
(6) Android官方文檔中Looper的介紹:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation ofprepare() and loop() to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
px (pixels) 像素
dip (device independent pixels) 設備獨立像素
sp (scaled pixels - best for text size ) 放大像素,對文本大小最好
pt (points) 點
in (inches) 英寸
mm (millimeters) 毫米
很多網友可能發現在Android的layout文件中layout_width或layout_height有時候可能會指定具體的單位,比如有時候為px、dip或者sp等等。下面android123把常見的單位做下簡單的介紹,比如說
px (pixels)像素 -- 一般我們HVGA代表320x480像素,這個用的比較多。
dip或dp (device independent pixels)設備獨立像素 -- 這個和設備硬件有關,一般我們為了支持WVGA、HVGA和QVGA cwj推薦使用這個,不依賴像素。
sp (scaled pixels — best for text size)放大像素-- 主要處理字體的大小。
下面的幾個是不常用的,大家也知道這里android123就不再過多的贅述。
in (inches)英寸
mm (millimeters)毫米
pt (points)點
px像素如何轉為dip設備獨立像素
最近有網友問如何將px像素轉為dip獨立設備像素,由于Android的設備分辨率眾多,目前主流的為wvga,而很多老的設備為hvga甚至低 端的qvga,對于兼容性來說使用dip無非是比較方便的,由于他和分辨率無關和屏幕的密度大小有關,所以推薦使用,不過這里android123提示大 家,ophone os的手機對于dip的支持糟糕透了,顯示的結果會放大很多,同時黑色的主題會導致常規的黑色文字讓用戶無法分辨。
px= (int) (dip*density+0.5f) //這里android開發網提示大家很多網友獲取density的方法存在問題,從資源中獲取的是靜態定義的,一般為1.0對于HVGA是正好的,而對于wvga這樣的應該從WindowsManager中獲取,WVGA為1.5
QVGA HVGA WVGA區別
文章分類:移動開發
QVGA即"Quarter VGA"。顧名思義即VGA的四分之一尺寸,亦即在液晶屏幕(LCD)上輸出的分辨率是240×320像素。QVGA支持屏幕旋轉,可以開發出相應的程序,以顯示旋轉90°、180°、270°屏幕位置。由HandEra公司發布。多用于手持/移動設備。 需要說明的是有些媒體把QVGA屏幕當成與TFT和TFD等LCD材質相同的東西是錯誤的,QVGA屏幕的說法多見與日本的一些手機中,目前采用微軟Pocket PC操作系統的智能手機屏幕也大多是320×240像素的QVGA屏幕。 所謂QVGA液晶技術,就是在液晶屏幕上輸出的分辨率是240×320的液晶輸出方式。這個分辨率其實和屏幕本身的大小并沒有關系。比如說,如果2.1英寸液晶顯示屏幕可以顯示240×320分辨率的圖像,就叫做“QVGA 2.1英寸液晶顯示屏”;如果3.8英寸液晶顯示屏幕可以顯示240×320的圖像,就叫做“QVGA 3.8英寸液晶顯示屏”,以上兩種情況雖然具有相同的分辨率,但是由于尺寸的不同實際的視覺效果也不同,一般 HVGA 即VGA(640*480)的一半,分辨率為(480*320),(3:2寬高比) 它是用于各種各樣的PDA設備,首先是2002年的索尼Clie PEG - NR70, 來說屏幕小的一個畫面自然也會細膩一些。 WVGA 數碼產品屏幕材質的一種,VGA的另一種形式,比VGA分辨率高,別名 : Wide VGA, ,其分辯率為800×480象素。是擴大了VGA(640×480)的分辨率。應用于PDA和手機等,因為很多網頁的寬度都是800,所以WVGA的屏幕會更加適和于瀏覽網頁,可以說是未來手持設備的分辨率的大趨勢
android:padding 屬性允許你設置相同的4個方向的間距值,組件的內容在間距內的中間。如果你要四個不同數值的間距值,,可以分別使用 android:paddingLeft,android:paddingRight,android:paddingTop和 android:paddingBottom。間距值是一個具體的數值,如果要5像素,則可以對應填寫”5px”.
如 果你應用組件的默認背景(例如,通過android:backgound屬性),背景將會同時顯示在間距和組件上。為了避免這種情況,用 padding,還不如用margin,這可以只增加空白的空間,并不會撐大組件。你可以通過android:layoout_margin屬性來實現。
例如:<com.android.motoswitch.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:src="@drawable/all_apps_button"
switcher:direction="horizontal"
/>
Android核心分析(22)-----Android應用框架之Activity 收藏
3 Activity設計框架
3.1 外特性空間的Activity
我們先來看看,Android應用開發人員接觸的外特性空間中的Activity,對于AMS來講,這個Activity就是客服端的Activity。應用程序員在建立Android應用時,構建Activity的子類就是Andoid外特性空間展現的接口。我們可以從下面的簡單的例子描述看看Activity,到底如何建立的。
DemoActivity extend Activity
{
onCreate
onResume
onPause
onStop
}
在Android的外特性空間(SDK)中,Android應用程序員根本不知道進程是什么時候起來的,系統消息是如何傳遞過來的。這個DemoActivity是如何實例化的呢?并且該Activity是托管在哪個進程的呢?本節的分析將給出答案。
我們從ActivityThread中可以看到在應用進程中的Activity都被放置在mActivities中。

這些ActivityRecord記錄了應用進程中,程序員建立的Activity子類的實例,我們稱之為外特性空間的Activity。這些Activity類實例是放在應用程序端進行實際交互的Activity,而為了管理這些Activity,AMS內核中還有一個影子Activity,被稱為HistoryRecord。
3.2 Activity與HistoryRecord的關系
在整個系統中,Activity實際上有兩個實體。一個在應用進程中跟應用程序員打交道的Activity,一個是在AMS的中具有管理功能的History Record。應用進程中的Activity都登記ActivityThread實例中的mActivity數組中,而在AM端,HistroytRecord實例放置在mHistroy棧中。mHistory棧是Android管理Activity的場所,放置在棧頂的就是User看到的處于活動狀態的Activity。
Activity與HistrotyRecord的關系圖可以表示如下:

Activity的內核實體是依靠在ProcessRecord的成員變量中,通過ProcessRecord我們可以訪問到所有的屬于該Process的Activity。而在ProcessRecord記錄了與應用進程之間的聯系:IActivtityThread接口。通過該接口,可以訪問到所對應的Activity的方法。在Launch Activity時,AMS將對應的HistoryRecord作為token傳遞到客服端和客服端的Activity建立聯系。在AMS中Activity狀態變化時,將通過該聯系找到客服端的Activity,從而將消息或者動作傳遞應用程序面對的接口:xxxActivity。
3.3 Actvity的Launch過程
1)發起請求startActivity(intent)
2)Activity Service Manager接收到請求執行StartActivity函數。
建立:HistoryRecord實例r.
將r 加入到mHistory頂。
(3)通過app.thread.scheduleLaunchActvity( app,r)@ActivityThread.java
(4)在App應用中建立新的ActivityRecord。
(5)建立新的Activity對象并放入到ActivityRecord中。
(6)將ActivityRecord加入到mActivites@ActivityThread
(7)發起Activity.onCreate(..),,該onCreate就是在你的應用程序XXXActivity中的onCreate。

3.4 Activity的Resume
(1)Activity什么時候被Resume

(2)Rusume的過程
通過該過程的研究我們會進一步的了解到AMS與應用進程的交互過程。
在AMS端,滿足resume條件都會調用:Resume的核心函數:resumeTopActivityLocked@ActivityManagerService
XXX當前棧頂的HistroyRecord
1)窗口切換:隱藏前一個Activity的窗口,
2)更新LRUList,(LRUList是淘汰應用程序的依據之一)
3) XXX.app.thread.scheduleResumeActivity(XXX,
isNextTransitionForward());
4)completeResumeLocked
setFocusedActivityLocked
mFocusActivity=xxx //此時焦點Actvitiy切換了。
WM.setFocusedApp(xxx,
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
在應用程序端:
(5)scheduleResumeActivity
handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityRecord r = performResumeActivity(token, clearHide);
ActivityRecord r = mActivities.get(token);
r.activity.performResume()
performResume
整個Resume的過程如下:

Android Application
Android提供給開發程序員的概念空間中Application只是一個松散的表征概念,沒有多少實質上的表征。在Android實際空間中看不到實際意義上的應用程序的概念,即使有一個叫Application的類,這個也就是個應用程序上下文狀態,是一個極度弱化的概念。Application只是一個空間范疇的概念,Application就是Activity,Service之類的組件上下文描述。Application并不是Android的核心概念,而Activity才是Android的核心概念。
從Android的SDK文檔中,我們知道一般情況Android應用程序是由以下四種組件構造而成的:Activity,Broadcast Intent Receiver,服務(Service),內容提供器(Content Provider)。我們可以使用下面的圖來表示一下Android的概念空間。這些組件依附于應用程序中,應用程序并不會一開始就建立起來,而是在這些組件建立起來后,需要運行時,才開始建立應用程序對象。

2.1應用進程名稱
為什么要從應用進程名稱開始?作為內核研究,我們還是回到問題的最本質處:不管Activity,Service等組件如何設計和運行,它要提供服務,就必須要依附在Linux的進程上,建立消息循環,組件才能夠真正的運作。Activity實例是如何Hosting在Linux進程上的?這個是我們首先想要弄明白的。
我們在的項目中看到android:process="string"這個定義。
allowClearUserData=["true" | "false"]
android:allowTaskReparenting=["true" | "false"]
android:backupAgent="string"
…
android:label="string resource"
android:manageSpaceActivity="string"
android:name="string"
android:permission="string"
android:persistent=["true" | "false"]
android:process="string"
android:restoreAnyVersion=["true" | "false"]
android:taskAffinity="string"
android:theme="resource or theme" >
. . .
在SDK用已經描述的很清楚到了。
android:process
The name of a process where all components of the application should run. Each component can override this default by setting its own process attribute.
By default, Android creates a process for an application when the first of its components needs to run. All components then run in that process. The name of the default process matches the package name set by the element.
By setting this attribute to a process name that's shared with another application, you can arrange for components of both applications to run in the same process — but only if the two applications also share a user ID and be signed with the same certificate.
為什么要提出這么一個定義?android:process名稱。
默認狀態下,Activity Manager Service在應用程序的第一個組件需要運行時將會為應用程序建立一個進程,而這個進程的名字就是android:process=”string”所指定,缺省的是應用程序包的名字。該進程一旦建立,后面的該應用的組件都將運行在該進程中,他們綁定的根據就是這個Android:Process指定的名稱,因為在他們都在同一個應用程序包里,也就具有了同樣的進程名字,于是他們都托管在了同一進程中。組件將通過ClassLoader從Package中獲取到應用程序的信息。
在建立Actvitiy時,如果在應用進程端沒有應用對象,系統在該過程中利用makeApplication建立一個Application對象,實例化"android.app.Application",建立一個應用程序上下文完成例如資源,package等信息管理。
2.2 ActivityThread運行框架
在分析中,我們可以看到真正對應應用進程的不是Application而是ActivityThread。我們從實際的應用堆棧可以看到:
NaiveStart.main()
ZygoteInit.main
ZygoteInit$MethodAndArgsCall.run
Method.Invoke
method.invokeNative
ActivityThread.main()
Looper.loop()
....
每個應用程序都以ActivityThread.main()為入口進入到消息循環處理。對于一個進程來講,我們需要這個閉合的處理框架。

ActivitiyThread是應用程序概念空間的重要概念,他建立了應用進程運行的框架,并提供了一個IActivityThread接口作為與Activity Manager Service的通訊接口.通過該接口AMS可以將Activity的狀態變化傳遞到客戶端的Activity對象。
2.3 ActivitiyThread的建立
為了敘述的方便我將Actvitiy Manager Service簡寫成AMS。
在AMS中關于應用程序的概念是ProcessRecord,請求都是從Activity,Service…等開始的,在Activity需要Resume時,此時如果與Activity相關的應用進程沒有起來,AM則啟動應用進程。
AMS與應用進程的綁定分為兩個部分,第一部分就是AM建立應用進程,第二部分就是應用進程Attach到AM,與AM建立通訊通道。
1)創建建立進程:startProcessLocked(processName,Appinfo.uid)。該函數在StartSecificActivityLocked等調用。
(1)建立ProcessRecord對象app,并將該對象添加到mProcessNames中。應用對象在mProcessNames中使用應用名字和uid來標識自己。如果在同一個Package中的Activity,如果都使用默認設置,那么這些Activity都會托管在同一個進程中,這是因為他們在帶的ApplicationInfo中的ProcessName都是一樣的。

mPidsSelfLocked數組記錄了PID,這個將會在應用進程跑起來后,將自己Attach到AM時,根據pid找到自己的前世:ProcessRecord.
2)android.app.ActivityThread進程啟動
Android.app.ActivityThread進程建立后,將跳入到ActivityThread的main函數開始運行,進入消息循環。
應用進程使用thread.attach()發起AMS的AttachApplicationLocked調用,并傳遞 ActvitiyThread對象和CallingPid。AttachApplicationLocked將根據CallingPid在mPidsSelfLocked找到對應的ProcessRecord實例app,將ActvitiyThread放置app.thread中。這樣應用進程和AMS建立起來雙向連接。AM可以使用AIDL接口,通過app.thread可以訪問應用進程的對象。
應用程序通過ActivityThread提供的框架,建立消息循環Looper和Handler。從前面的相關章節我們知道有Looper和Handler,整個系統就可以運作了。
為了更為系統的了解應用程序的建立時序及其涉及到數據操作,我給出了應用進程的建立過程示意圖:
