第8章 AndroidManifest.xml檔案
每個Android應用程式在根目錄下必定有一個AndroidManifest.xml檔案(檔案名稱必須是這個)。這個manifest檔案向android系統列出了應用程式的必要資訊,有了這些資訊,系統才能運行應用程式(linux你懂的)。除此之外,manifest還有以下作用:
◆列舉了應用程式的java包。包名是識別應用程式的唯一標誌。
◆描述了應用程式的組件——Activity、Service、Broadcast receivers,Content providers。列舉了實現每個組件的類,並給出可能的值(例如,類能處理的intent資訊)。這些聲明使Android系統瞭解了應用程式套件組合含的組件及其運行條件。
◆確定了宿主應用程式組件的進程。
◆聲明了應用程式擁有的許可權,使其可以使用API保護的內容,與其他應用程式進行互動。
◆同時,也聲明了其他應用程式與該應用程式組件互動所需要的許可權。
◆列舉了為應用程式運行時提供效能和其他資訊的Instrumentation類的聲明。這些聲明只有在開發與測試的時候才會在manifest中使用,發布的時候需要將這些聲明刪除。
◆聲明了應用程式支援的Android API的最低等級。
◆列舉了應用程式必須連結的庫。
8.1 Manifest檔案結構
下面代碼清單8-1中顯示了manifest檔案的整體結構以及可以使用的所有元素結構。每一個元素都所有屬性都在另一個單獨的檔案中顯示。它們按元素的字母順序排序。其實這種xml格式相信很多人應該非常熟悉了。(請參考http://developer.android.com/intl/zh-CN/guide/topics/manifest/manifest-intro.html)
<?xml version="1.0" encoding="utf-8"?><manifest> <uses-permission /> <permission /> <permission-tree /> <permission-group /> <instrumentation /> <uses-sdk /> <uses-configuration /> <uses-feature /> <supports-screens /> <compatible-screens /> <supports-gl-texture /> <application> <activity> <intent-filter> <action /> <category /> <data /> </intent-filter> <meta-data /> </activity> <activity-alias> <intent-filter> . . . </intent-filter> <meta-data /> </activity-alias> <service> <intent-filter> . . . </intent-filter> <meta-data/> </service> <receiver> <intent-filter> . . . </intent-filter> <meta-data /> </receiver> <provider> <grant-uri-permission /> <meta-data /> </provider> <uses-library /> </application></manifest>
代碼清單 8-1
下面按字母順序列出了manifest檔案中的所有元素。這些已經是所有的合法元素,使用者不能添加自訂的元素或屬性。
<action>
<activity>
<activity-alias>
<application>
<category>
<data>
<grant-uri-permission>
<instrumentation>
<intent-filter>
<manifest>
<meta-data>
<permission>
<permission-group>
<permission-tree>
<provider>
<receiver>
<service>
<supports-screens>
<uses-configuration>
<uses-feature>
<uses-library>
<uses-permission>
<uses-sdk>
8.2檔案慣例
一些慣例和規則一般適用於manifest檔案中的所有元素和屬性:
1. Elements(元素,節點)
只有<manifest>和<application>元素是必須的,而且只能出現一次。大多數其他元素都可以出現多次或者不出現,並且要實現有意義的功能時,有些元素是必不可少的。同等級的元素通常沒有固定順序。例如:<activity>, <provider>,
和<service>可以按任何順序混合出現。(<activity-alias>通常要要按順序出現:必須在<activity>之後出現。)
2. Attributes(屬性)
正常情況下來說,所有的屬性都是可選的。然而,為了實現功能,元素的某些屬性是必須要指明的。你可以將這份文檔作為指南。對於真正可選的屬性,意味著在未指明的時候會有一個預設值或預設狀態。
除了<manifest>根項目的某些屬性,其他所有的屬性都以 android:為首碼——例如,android:alwaysRetainTaskState。因為首碼是通用的,所以當引用屬性的名字的時候本檔案會自動將其忽略。
3. 聲明類名
很多元素都對應著java對象,包括應用程式元素本身(<application>及其主要的組件——<activity>,<service>, <receiver>和<provider)。如果定義一個子類,比如使用者通常會定義的組件子類(Activity,Service,BroadcastReceiver,ContentProvider),通常由name屬性聲明。這個名字必須包括完整的包名。例如,Service的子類必須按如下方法定義:如代碼清單8-2所示:
<manifest . . . > <application . . . > <service android:name="com.example.project.SecretService" . . . > . . . </service> . . . </application></manifest>
代碼清單 8-2
但是,作為簡寫,如果字串的第一個字元為一個點,那麼字串將會被添加到應用程式的包名(由manifest的package屬性指定)之後,下面的賦值跟上面是一樣的效果,如代碼清單8-3所示:
<manifest package="com.example.project" . . . > <application . . . > <service android:name=".SecretService" . . . > . . . </service> . . . </application></manifest>
代碼清單 8-3
當使用組件時,android會執行個體化命名的子類。如果子類沒有指定,將會執行個體化父類。
4. 多個值
如果元素可以賦多個值,通常會重複進行。例如,一個intent filter可以列舉多個action,如代碼清單8-4所示:
<intent-filter . . . > <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.INSERT" /> <action android:name="android.intent.action.DELETE" /> . . .</intent-filter>
代碼清單 8-4
5. 資源值
某些屬性的值可以顯示給使用者看——例如,Activity的label和icon。這些屬性的值應該本地化,因此可以從一個資源或主題中擷取。資源值通常按以下格式表示:@[package:]type:name
其中,如果資源跟應用程式在同一個包中,那麼包名可以省略。type是資源的類型——例如“string”或者“drawable”——name是識別具體資源的標識。具體樣本如代碼清單8=5所示:
<activity android:icon="@drawable/smallPic" . . . >
代碼清單 8-5
從主題中擷取的值可以用類似的方法表示,只不過首字元使用?而不是@:?[package:]type:name
6. 字串值
當屬性值是一個字串的時候,需要使用雙反斜線('\\')來逸出字元——例如'\\n'代表換行,或者'\\uxxxx'代表Unicode字元。
8.3 檔案特性
以下內容描述了manifest檔案中表現出來的Android特性:
1. Intent Filters
應用程式的核心組件(activities,services,broadcast
receivers)由intent啟用。intent是一組描述要做的動作的資訊(一個intent對象)——包括依賴的資料、執行動作的組件種類和其他相關的說明。Android選用對應的組件來響應intent,需要的時候執行個體化組件,並將其傳給intent對象。
組件通過intent filters表明了自身的能力——能響應的intent的種類。由於android系統在運行之前必須明確組件能夠處理哪些intent,因此可以在manifest檔案中聲明intent過濾器。一個組件可以有多個不同的過濾器,代表不同的能力。顯式地指定目標組件的intent將啟用該組件;filters並不起作用。但是,如果一個intent沒有通過名字指定目標,那麼只有在通過組件的某一filters時才會啟用組件。
2. Icons和labels
很多元素都有icon和label屬性,用於給使用者顯示一個小表徵圖或者一個文本。有些元素還有一個description屬性,用於在螢幕上顯示更長的擴充資訊。例如,<permission>元素以上三個屬性都有,所以當使用者要求為應用程式授予許可權的時候,將會看到代表許可權的表徵圖、許可權的名稱,以及描述許可權作用的資訊。在application元素中設定的表徵圖和標籤,將會是應用程式中每個組件的預設設定。類似的,組件的表徵圖和標籤——例如,activity元素——將會是該組件的每一個intent-filter元素的預設設定。如果application元素設定了一個標籤,但是activity和intent filters沒有設定,那麼應用程式標籤將同時適用於activity和intent filters。不管組件何時展現給使用者,intent filters設定的表徵圖和標籤都代表實現該過濾器(filters)功能的組件。
例如,設定了“android.intent.action.MAIN”和“android.intent.category.LAUNCHER”的過濾器代表了由這個activity來啟動應用程式——也就是說,應用程式啟動的時候,這個activity最先顯示。因此,啟動畫面顯示的表徵圖和標籤就是過濾器中設定的表徵圖和標籤。
3. 許可權(Permissions)
許可權是限制訪問裝置上的代碼或資料。這個限制用於保護關鍵代碼和資料,以免被濫用導致出現錯誤或影響使用者體驗。每個許可權都有一個唯一的標記。通常這個標記表示被限制的行為。例如,以下是android中定義的一些許可權:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
一個特性最多由一個許可權控制。如果應用程式需要訪問有許可權保護的特性,必須在manifest中用<uses-permission>元素宣告該應用程式需要使用該許可權。然後,安裝應用程式的時候,安裝程式將檢查使用者簽署的應用程式認證的許可權,或者,在某些情況下,詢問使用者,從而決定是否需要給應用程式授予要求的許可權。如果授權成功了,那麼應用程式就可以使用被保護的特性了。如果授權失敗,那麼應用程式嘗試訪問被保護的特性的時候,將會直接失敗,而不通知使用者。
應用程式也可以使用許可權保護自己的組件(activities,services,broadcast
receivers,content providers)。android定義的所有許可權(請參考)
http://developer.android.com/intl/zh-CN/reference/android/Manifest.permission.html
或者其他應用程式聲明的許可權,都可以使用。或者應用程式也可以定義自己的許可權。新的許可權通過<permission>元素宣告。例如,可以按照以下方法保護activity,如代碼清單8-6所示:
<manifest . . . > <permission android:name="com.example.project.DEBIT_ACCT" . . . /> <uses-permission android:name="com.example.project.DEBIT_ACCT" /> . . . <application . . .> <activity android:name="com.example.project.FreneticActivity" android:permission="com.example.project.DEBIT_ACCT" . . . > . . . </activity> </application></manifest>
代碼清單 8-6
注意,在這個例子中,DEBIT_ACCT許可權不僅使用<permission>元素宣告,同時也需要使用<uses-permission>聲明。應用程式的其他組件想要運行被保護的activity的時候,就需要使用該許可權,即使該activity是被應用程式本身保護的。還是這個例子,如果permission屬性已經在其他地方聲明過了(比如android.permission.CALL_EMERGENCY_NUMBERS中),那麼就無需再用<permission>元素宣告了,但是<uses-permission>元素的聲明還是需要的。
<permission-tree>元素為代碼中需要使用的許可權組定義了一個命名空間。<permission-group>元素為許可權組定義了一個標籤(無論許可權是在manifest中使用<permission>元素宣告的,還是在其他地方聲明的)。區別只是展現給使用者的時候,許可權是如何組合的。<permission-group>元素不會指明許可權屬於哪一個組,只給出了組的名字。把組名添加到<permission>元素的<permission-group>屬性就可以把該許可權分配到該組了。
4. 庫
每一個應用程式都會串連到android的預設庫,這個庫中包含了編譯應用程式需要的基礎包(包中含有常用的類,如Activity, Service, Intent, View, Button, Application, ContentProvider等)。
但是,有些包有自己的庫。如果應用程式要使用這些包中的代碼,就必須顯式地連結這些包的庫。在manifest檔案中必須包含獨立的<uses-library>元素,將需要的庫全部列舉出來。
FAQ群:213821767