Android Process 詳解


Android基礎之Process
進程
默認情況下,同一個應用程序中的所有組件運行在同一個進程中,而且絕大多數的應用程序也都是這樣的。但是,如果我們想要控制讓某個特定的組件屬於某個進程,我們可以在manifest文件中進行配置。
在每種組件元素(activity、service、receiver、provider)的manifest條目中,都支持一個“android:process”的屬性,通過這個屬性,我們可以指定某個組件運行的進程。我們可以通過設置這個屬性,讓每個組件運行在它自己的進程中,也可以只讓某些組件共享一個進程。我們要可以通過設置“android:process”屬性,讓不同應用程序中的組件運行在相同的進程中,這些應用程序共享相同的Linux用戶ID,擁有相同的證書。
<application>元素也有一個“android:process”屬性,可以設置一個應用於全部組件的默認值。
    當可用內存數量低,而一些與用戶即時交互的進程又需要內存時,Android隨時可能會終止某個進程。運行在被終止的進程中的組件會因此被銷燬,但是,當再次需要這些組件工作時,就會再啓動一個進程。
    在決定要終止哪個進程時,Android系統會權衡它們對於用戶的重要性。例如,相較於運行可見activities的進程,終止一個運行不可見activities的進程會更加合理。是否終止一個進程,依賴於運行在這個進程中的組件的狀態。
 
進程生命週期
Android系統會儘可能讓一個應用程序進程運行更長的時間,但是它也需要移除舊的進程,爲那些新創建的進程或者相比起來更加重要的進程釋放內存空間。要決定哪個進程保留,哪個進程終止,系統會將每個進程放置到“importance hierarchy”中,“importance hierarchy”是基於運行在進程中的組件以及這些組件的狀態的。擁有最低重要性的進程會首先被幹掉,然後就是那些次低重要性的進程,依次類推。
在“importance hierarchy”中,共有五個等級。下面的列表中,按照重要性列出了五種不同類型的進程:
1、 前臺進程(Foreground process)
2、 可見進程(Visible process)
3、 服務進程(Service process)
4、 後臺進程(Background process)
5、 空進程(Empty process)
 
Android process與Thread 的問題
 
Android process與Thread 的問題
public class Activity2 extends Activity
{
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);




new Thread()
{
public void run()
{
dosomething();


}
}
.start();


}
在啓動新線程時,出現如下錯誤:
W/ActivityManager( 81): Launch timeout has expired, giving up wake lock!
W/ActivityManager( 81): Activity idle timeout for HistoryRecord
解決辦法:爲相應的Activity1及Activity2增加Android:process屬性,強制使兩個Activity處於不同的應用程序私有進程之中。
問題出現的具體原因待進一步研究。
/guide/topics/manifest/activity-element.html
< Activity>元素 Android:process屬性定義了運行Activity所在進程的名稱。通常,一個應用程序的所有組件運行在應用程序創建的默認的進程。它具有與應用程序包相同的名稱。<application>元素的 android:process屬性可以爲所有組件設置不同的默認進程名稱。但是,每個組件都可以覆蓋默認設置,讓應用程序跨多個進程。
如果分配給此屬性的名稱以一個冒號(':')開頭,發將創建一個新的屬於應用程序的私有的進程,在這一進程中運行。
如果進程的名稱由小寫字母開始,活動將在該名稱的全局進程中運行,只要它有這樣做的權限。這樣做將使在不同的應用程序中的組件共享一個進程,減少資源的使用。






android:process可以針對一個組件(activity,broadcast等)。




<application android:process="com.android.phone">


應用程序的所有組件運行在該進程中。每個組件可以通過設置它自己的process屬性來覆蓋該設置。
默認情況下,Android爲每個應用程序創建一個單獨的進程,所有組件運行在該進程中,這個默認進程的名字通常與該應用程序的包名相同。
比如<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.lt.mytest" >
那麼該程序默認的進程名爲com.lt.mytest
設置該屬性可以使得本應用程序與其它應用程序共享相同的進程,僅僅當這兩個應用程序也共享一個擁有相同簽名的UserId。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:sharedUserId="android.uid.phone" >
與其它應用程序共享的一個Linux User Id的名字。
默認情況下,Android爲每個應用程序分配一個唯一的User Id。然而,如果有多個應用程序都將該屬性設置爲一個相同的值,那麼它們將共享相同的Id。如果這些應用程序再被設置成運行在一個相同的進程,它們便可以彼此訪問對方的數據。






AndroidManifest.xml的Service元素 android:process設置




AndroidManifest.xml的Service元素
< service  android:name =".RemoteService"  android:process =":remote" >  
         < intent-filter >  
                 < action  android:name ="com.demo.IMyService"  />  
         </ intent-filter >  
< / service >
    這裏的android:process=":remote",一開始我沒有添加的,在同一個程序裏使用IPC,即同一個程序作爲客戶端/服務器端,結果運行mRemoteService = IMyService.Stub.asInterface(service);時提示空指針異常。觀察了人家的在不同程序裏進行IPC的代碼,也是沒有這個android:process=":remote"的。後來在官方文檔 http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html裏瞭解到(留意第二段文字):
android:process
The name of the proces s where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The <application> element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.
 
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process.  If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
 也就是說android:process=":remote",代表在應用程序裏,當需要該service時,會自動創建新的進程。而如果是android:process="remote",沒有“:”分號的,則創建全局進程,不同的應用程序共享該進程。




看過很多關於Android Service開發的文章, 而其中大部分在講解遠程服務時, 都只是照搬了代碼格式, 即便是使用了AIDL (Android Interface Definition Language), 也用了IBinder接口, 但是App在實際運行中還是以本地服務的方式啓動的.
 
除此之外, 在調試時, 我們還可以看到 ServiceConnection::onServiceConnected(ComponentName name, IBinder binder) 中binder的實際類型, 通過該類型, 即可知App到底調用的是本地對象還是遠程對象.
 
P.S. IBinder是Android RPC (Remote Procedure Call) 的核心接口, 其中Camera, MediaPlayer等都是通過RPC技術實現的, 而爲之服務的就是一個獨立的進程, 這個可以通過adb shell ps 可以看到.
 
具體請參考 Android 源碼 http://source.android.com/ .
 
 
進入正題
 
本地/遠程服務最大的區別在於對 AndroidManifest.xml中service屬性 android:process 的設置, 而該屬性是可以隨意設置的, 比如 android:process=":remote_1".
 
該屬性一旦設置, 那麼App啓動之後, Service肯定會以遠程服務方式啓動, ---- 可通過adb shell ps 就可以看到有一個獨立的進程啓動了. 
 
假設項目 Package爲 net.oschina.demo , 並設置 android:process=":remote_1", 那麼App運行時, 通過 adb shell ps | grep net.oschina.demo , 可以看到有兩個進程:
 
    * net.oschina.demo
    * net.oschina.demo:remote_1
 
 
官方文檔
http://developer.android.com/guide/components/services.html
http://developer.android.com/reference/android/app/Service.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章