1. 程式人生 > >AndroidManifest詳解之Application(有圖更好懂)

AndroidManifest詳解之Application(有圖更好懂)

能夠包含的標籤:
  1.     <activity>
  2.     <activity-alias>
  3.     <service>
  4.     <receiver>
  5.     <provider>
  6. <uses-library>

常用的屬性:

android: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。如果這些應用程式再被設定成執行在一個相同的程序,它們便可以彼此訪問對方的資料。

android:allowbackup


是否將程式加入到系統的備份和恢復架構中。

android:taskAffinity
Activity的歸屬,也就是Activity應該在哪個Task中,Activity與Task的吸附關係。預設如果沒有設定taskAffinity,則taskAffinity跟包名是一樣的
taskAffinity 和 FLAG_ACTIVITY_NEW_TASK可用來決定activity啟動時是否需要新建一個task。我們分四種情況看一下這兩個標誌對啟動activity的影響:(前提:從MainActivity中啟動ActivityA)
1)、兩個標誌都不設定
2)、有FLAG_ACTIVITY_NEW_TASK  
3)、無FLAG_ACTIVITY_NEW_TASK有taskAffinity (不同於MainActivity)
4)、有FLAG_ACTIVITY_NEW_TASK有taskAffinity
注意上面的標誌都是針對於啟動的ActivityA,FLAG_ACTIVITY_NEW_TASK  是在啟動ActivityA的Intent中設定的,taskAffinity 是在AndroidManifest中ActivityA中設定,另外注意這裡兩個actiity的啟動模式都設定為standard
1、先看第一中情況:

主要程式碼:

<activity android:name=".ActivityA"    
			android:launchMode="standard"  
			android:label="@string/title_activityA">    
  <intent-filter>    
	  <action android:name="com.leaves.ipanel.ActivityA"/>    
	  <category android:name="android.intent.category.DEFAULT"/>    
  </intent-filter>    
</activity>  
MainActivity啟動activity  
public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      

	startActivity(intent);   
} 
啟動A之後的堆疊: 



2、有FLAG_ACTIVITY_NEW_TASK 
我們新增FLAG_ACTIVITY_NEW_TASK  

public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
	startActivity(intent);   
}  
啟動A之後的堆疊:

3、無FLAG_ACTIVITY_NEW_TASK有taskAffinity (不同於MainActivity)

<activity android:name=".ActivityA"    
            android:launchMode="standard"  
            android:taskAffinity="com.leaves.test.ActivityA"  
          android:label="@string/title_activityA">    
       <intent-filter>    
           <action android:name="com.leaves.ipanel.ActivityA"/>    
           <category android:name="android.intent.category.DEFAULT"/>    
       </intent-filter>    
</activity> 
    public void onClick(View arg0) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
        Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
          
        startActivity(intent);   
    }  
檢視一下啟動A之後的堆疊:


4、有FLAG_ACTIVITY_NEW_TASK有taskAffinity

把FLAG_ACTIVITY_NEW_TASK新增上去    

public void onClick(View arg0) {  
	// TODO Auto-generated method stub  
	Log.i(TAG, "--onClick--task id = " + getCurrentTaskId());  
	Intent intent = new Intent("com.leaves.ipanel.ActivityA");      
	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
	startActivity(intent);   
} 

檢視一下啟動A之後的堆疊:

上面我們測試的兩個Activity是在同一個應用中,如果他們在不同的應用中呢,例如ActivityA跟MainActivity不在一個apk中,其實情況還是一樣的.因為預設如果沒有設定taskAffinity,則taskAffinity跟包名是一樣的。若不考慮android:allowTaskReparenting,如果ActivityA跟MainActivity不在一個apk中,當沒有FLAG_ACTIVITY_NEW_TASK時,則兩者應該是在同一個task,但是如果有FLAG_ACTIVITY_NEW_TASK,則兩者應該會在不同的task中。

android:allowTaskReparenting

主要作用是activity的遷移,即從一個task遷移到另一個task,這個遷移跟activity的taskAffinity有關,必須是將該activity從舊的 taskAffinity遷移到新的taskAffinity中.只有設定了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標識才會用到該屬性。從home上啟動的程式都會設定該Flag,會進行task reset.

下面舉個例子,有兩個apk

apk1中含有個Activity:MainActivityA和ActivityB, ActivityB設定了allowTaskReparenting為false.
apk2中含有兩一個activity:MainActivityB,MainActivityB點選的時候會啟動ActivityB

首先我們啟動apk2,進入MainActivityB,點選MainActivityB會進入ActivityB, 按home鍵,再從Home鍵啟動apk1,用dumpsys工具得到這個時候的堆疊:



圖中藍色線框部分表示對應的Activity所屬的task

可以看到,然從Home啟動apk1的時候帶有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,但在任務重置的過程中什麼事也沒有做。
我們把ActivityB的allowTaskReparenting改為true,這個時候前面的步驟一樣,當我們從Home啟動apk1時,我們驚奇的發現,啟動的竟然是ActivityB,可以看到此時的堆疊:


這是由於重置任務的時候把它遷移到了新啟動的task中。分析android原始碼中的resetTaskIfNeededLocked函式時就會明白這個是怎麼回事了。

android:exported
這個屬性用於指示該服務是否能夠被其他應用程式元件呼叫或跟它互動。如果設定為true,則能夠被呼叫或互動,否則不能。設定為false時,只有同一個應用程式的元件或帶有相同使用者ID的應用程式才能啟動或繫結該服務。
它的預設值依賴與該服務所包含的過濾器。沒有過濾器則意味著該服務只能通過指定明確的類名來呼叫,這樣就是說該服務只能在應用程式的內部使用(因為其他外部使用者不會知道該服務的類名),因此這種情況下,這個屬性的預設值是false。另一方面,如果至少包含了一個過濾器,則意味著該服務可以給外部的其他應用提供服務,因此預設值是true。
這個屬性不是限制把服務暴露給其他應用程式的唯一方法。還可以使用許可權來限制能夠跟該服務互動的外部實體。