我們?cè)谶M(jìn)行APP開發(fā)的時(shí)候都會(huì)遇到一個(gè)文件:AndroidManifest.xml。從剛開始進(jìn)行Android開發(fā),到現(xiàn)在已經(jīng)過(guò)去了幾個(gè)月,還是對(duì)這個(gè)文件一知半解,只知道它是配置用的。但是這文件里的東西具體有什么用,該怎么用一直都沒(méi)有理解。借著做項(xiàng)目的機(jī)會(huì),仔細(xì)研究一下這個(gè)文件。
研究AndroidManifest.xml最好的方式自然就是對(duì)照著官方文檔詳細(xì)理解項(xiàng)目中每個(gè)字段的作用,并且做出一些修改來(lái)驗(yàn)證。
AndroidManifest是什么?
AndroidManifest官方解釋是應(yīng)用清單(manifest意思是貨單),每個(gè)應(yīng)用的根目錄中都必須包含一個(gè),并且文件名必須一模一樣。這個(gè)文件中包含了APP的配置信息,系統(tǒng)需要根據(jù)里面的內(nèi)容運(yùn)行APP的代碼,顯示界面。
AndroidManifest的作用是什么?
上述的功能是非?;\統(tǒng)的解釋,具體到細(xì)節(jié)就是:
- 為應(yīng)用的 Java 軟件包命名。軟件包名稱充當(dāng)應(yīng)用的唯一標(biāo)識(shí)符。
- 描述應(yīng)用的各個(gè)組件,包括構(gòu)成應(yīng)用的 Activity、服務(wù)、廣播接收器和內(nèi)容提供程序。它還為實(shí)現(xiàn)每個(gè)組件的類命名并發(fā)布其功能,例如它們可以處理的 Intent 消息。這些聲明向 Android 系統(tǒng)告知有關(guān)組件以及可以啟動(dòng)這些組件的條件的信息。
- 確定托管應(yīng)用組件的進(jìn)程。
- 聲明應(yīng)用必須具備哪些權(quán)限才能訪問(wèn) API 中受保護(hù)的部分并與其他應(yīng)用交互。還聲明其他應(yīng)用與該應(yīng)用組件交互所需具備的權(quán)限
- 列出 Instrumentation類,這些類可在應(yīng)用運(yùn)行時(shí)提供分析和其他信息。這些聲明只會(huì)在應(yīng)用處于開發(fā)階段時(shí)出現(xiàn)在清單中,在應(yīng)用發(fā)布之前將移除。
- 聲明應(yīng)用所需的最低 Android API 級(jí)別
- 列出應(yīng)用必須鏈接到的庫(kù)
上面是官方的解釋。很多東西筆者現(xiàn)在還不能理解,也沒(méi)有用到,先挑筆者理解的進(jìn)行解釋。
第一條:提供軟件包名。這就是我們的apk的名字,通常我們的名字都是類似"com.android.gles3jni"這種,和Java類名類似,目的是確定使其成為一個(gè)唯一值。
第二條:描述應(yīng)用的各個(gè)組件。這是用來(lái)定義四大組件用的。我們最常用的就是Activity組件。它需要定義組件的表現(xiàn)形式(組件名、主題、啟動(dòng)類型),組件可以響應(yīng)的操作(例如某個(gè)啟動(dòng)意圖)等。
第三條、第四條和第五條:還沒(méi)用到,不做解釋。
第五條:聲明最低API級(jí)別。這個(gè)級(jí)別在build.gradle文件中也能定義,字段是minSdkVersion。在AndroidManifest.xml文件中定義的情況比較少。
第六條:列出必要的lib庫(kù)。這東西在3.0以后的Android Studio似乎也沒(méi)什么功能,因?yàn)樵?.0以后編譯用的是CMakeLists.txt文件,以及build.gradle文件來(lái)指定庫(kù)。
一份真實(shí)的AndroidManifest.xml文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sample.teapot"
android:versionCode="1"
android:versionName="1.0.0.1" >
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
<application
android:allowBackup="false"
android:fullBackupContent="false"
android:supportsRtl="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="com.sample.teapot.TeapotApplication"
>
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name="com.sample.teapot.TeapotNativeActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="TeapotNativeActivity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
這是Google官方示例中的teapots項(xiàng)目中的一個(gè)文件,我們就針對(duì)這份文件來(lái)分析字段的意義。字段的意義參考的是官方文檔。
<manifest>元素
首先,所有的xml都必須包含<manifest>元素。這是文件的根節(jié)點(diǎn)。它必須要包含<application>元素,并且指明xmlns:android和package屬性。
<manifest>元素中的屬性
xmlns:android
這個(gè)屬性定義了Android命名空間。必須設(shè)置成"http://schemas.android.com/apk/res/android"。不要手動(dòng)修改。
package
這是一個(gè)完整的Java語(yǔ)言風(fēng)格包名。包名由英文字母(大小寫均可)、數(shù)字和下劃線組成。每個(gè)獨(dú)立的名字必須以字母開頭。
構(gòu)建APK的時(shí)候,構(gòu)建系統(tǒng)使用這個(gè)屬性來(lái)做兩件事:
- 1、生成R.java類時(shí)用這個(gè)名字作為命名空間(用于訪問(wèn)APP的資源)
比如:package被設(shè)置成com.sample.teapot,那么生成的R類就是:com.sample.teapot.R - 2、用來(lái)生成在manifest文件中定義的類的完整類名。比如package被設(shè)置成com.sample.teapot,并且activity元素被聲明成<activity android:name=".MainActivity">,完整的類名就是com.sample.teapot.MainActivity。
包名也代表著唯一的application ID,用來(lái)發(fā)布應(yīng)用。但是,要注意的一點(diǎn)是:在APK構(gòu)建過(guò)程的最后一步,package名會(huì)被build.gradle文件中的applicationId屬性取代。如果這兩個(gè)屬性值一樣,那么萬(wàn)事大吉,如果不一樣,那就要小心了。
android:versionCode
內(nèi)部的版本號(hào)。用來(lái)表明哪個(gè)版本更新。這個(gè)數(shù)字不會(huì)顯示給用戶。顯示給用戶的是versionName。這個(gè)數(shù)字必須是整數(shù)。不能用16進(jìn)制,也就是說(shuō)不接受"0x1"這種參數(shù)
android:versionName
顯示給用戶看的版本號(hào)。

<manifest>元素中的元素
<uses-feature>元素
Google Play利用這個(gè)元素的值從不符合應(yīng)用需要的設(shè)備上將應(yīng)用過(guò)濾。
這東西的作用是將APP所依賴的硬件或者軟件條件告訴別人。它說(shuō)明了APP的哪些功能可以隨設(shè)備的變化而變化。
使用的時(shí)候要注意,必須在單獨(dú)的<uses-feature>元素中指定每個(gè)功能,如果要多個(gè)功能,需要多個(gè)<uses-feture>元素。比如要求設(shè)備同時(shí)具有藍(lán)牙和相機(jī)功能:
<uses-feature android:name="android.hardware.bluetooth" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature>的屬性
android:name
該屬性以字符串形式指定了APP要用的硬件或軟件功能。
android:required
這項(xiàng)屬性如果值為true表示需要這項(xiàng)功能否則應(yīng)用無(wú)法工作,如果為false表示應(yīng)用在必要時(shí)會(huì)使用該功能,但是如果沒(méi)有此功能應(yīng)用也能工作。
android:glEsVersion
指明應(yīng)用需要的Opengl ES版本。高16位表示主版本號(hào),低16位表示次版本號(hào)。例如,如果是要3.2的版本,就是0x00030002。如果定義多個(gè)glEsVersion,應(yīng)用會(huì)自動(dòng)啟用最高的設(shè)置。
<application>元素
此元素描述了應(yīng)用的配置。這是一個(gè)必備的元素,它包含了很多子元素來(lái)描述應(yīng)用的組件,它的屬性影響到所有的子組件。許多屬性(例如icon、label、permission、process、taskAffinity和allowTaskReparenting)都可以設(shè)置成默認(rèn)值。
<application>的屬性
android:allowBackup
表示是否允許APP加入到備份還原的結(jié)構(gòu)中。如果設(shè)置成false,那么應(yīng)用就不會(huì)備份還原。默認(rèn)值為true。
android:fullBackupContent
這個(gè)屬性指向了一個(gè)xml文件,該文件中包含了在進(jìn)行自動(dòng)備份時(shí)的完全備份規(guī)則。這些規(guī)則定義了哪些文件需要備份。此屬性是一個(gè)可選屬性。默認(rèn)情況下,自動(dòng)備份包含了大部分app文件。
android:supportsRtl
聲明你的APP是否支持RTL(Right To Left)布局。如果設(shè)置成true,并且targetSdkVersion被設(shè)置成17或更高。很多RTL API會(huì)被集火,這樣你的應(yīng)用就可以顯示RTL布局了。如果設(shè)置成false或者targetSdkVersion被設(shè)置成16或更低。哪些RTL API就不起作用了。
該屬性的默認(rèn)的值是false。
android:icon
APP的圖標(biāo),以及每個(gè)組件的默認(rèn)圖標(biāo)??梢栽诮M價(jià)中自定義圖標(biāo)。這個(gè)屬性必須設(shè)置成一個(gè)引用,指向一個(gè)可繪制的資源,這個(gè)資源必須包含圖片。系統(tǒng)不設(shè)置默認(rèn)圖標(biāo)。例如mipmap/ic_launcher引用的就是下面的資源

android:label
一個(gè)用戶可讀的標(biāo)簽,以及所有組件的默認(rèn)標(biāo)簽。子組件可以用他們的label屬性定義自己的標(biāo)簽,如果沒(méi)有定義,那么就用這個(gè)標(biāo)簽。
標(biāo)簽必須設(shè)置成一個(gè)字符串資源的引用。這樣它們就能和其他東西一樣被定位,比如@string/app_name。當(dāng)然,為了開發(fā)方便,你也可以定義一個(gè)原始字符串。

android:theme
該屬性定義了應(yīng)用使用的主題的,它是一個(gè)指向style資源的引用。各個(gè)activity也可以用自己的theme屬性設(shè)置自己的主題。

android:name
Application子類的全名。包括前面的路徑。例如com.sample.teapot.TeapotApplication。當(dāng)應(yīng)用啟動(dòng)時(shí),這個(gè)類的實(shí)例被第一個(gè)創(chuàng)建。這個(gè)屬性是可選的,大多數(shù)APP都不需要這個(gè)屬性。在沒(méi)有這個(gè)屬性的時(shí)候,Android會(huì)啟動(dòng)一個(gè)Application類的實(shí)例。
<activity>元素
該元素聲明一個(gè)實(shí)現(xiàn)應(yīng)用可視化界面的Activity(Activity類子類)。這是<application>元素中必要的子元素。所有Activity都必須由清單文件中的<activity>元素表示。任何未在該處聲明的Activity對(duì)系統(tǒng)都不可見,并且永遠(yuǎn)不會(huì)被執(zhí)行。
android:name
Activity類的名稱,是Activity類的子類。該屬性值為完全限定類名稱,例如com.sample.teapot.TeapotNativeActivity。為了方便起見,如果第一個(gè)字符是點(diǎn)('.'),就需要加上<manifest>元素中的包名。應(yīng)用一旦發(fā)布,不應(yīng)更改該名稱。
沒(méi)有默認(rèn)值,必須指定該名稱。
android:label
Activity標(biāo)簽,可以被用戶讀取。該標(biāo)簽會(huì)在Activity激活時(shí)顯示在屏幕上。如果未設(shè)置,用<application>中的label屬性。對(duì)屬性的設(shè)置要求和<application>中一樣。
android:configChanges
列出 Activity 將自行處理的配置更改消息。在運(yùn)行時(shí)發(fā)生配置更改時(shí),默認(rèn)情況下會(huì)關(guān)閉 Activity 然后將其重新啟動(dòng),但使用該屬性聲明配置將阻止 Activity 重新啟動(dòng)。 Activity 反而會(huì)保持運(yùn)行狀態(tài),并且系統(tǒng)會(huì)調(diào)用其 onConfigurationChanged()方法。
注:應(yīng)避免使用該屬性,并且只應(yīng)在萬(wàn)不得已的情況下使用。 如需了解有關(guān)如何正確處理配置更改所致重新啟動(dòng)的詳細(xì)信息,請(qǐng)閱讀處理運(yùn)行時(shí)變更。
這屬性可以設(shè)置的項(xiàng)很多,這里列出常用的項(xiàng):
- orientation
屏幕放心啊發(fā)生了變化,比如用戶旋轉(zhuǎn)了設(shè)備 - keyboardHidden
鍵盤無(wú)障礙功能發(fā)生了變化,比如用戶顯示了硬件鍵盤 - android:launchMode
關(guān)于如何啟動(dòng)Activity的指令。一共有四種指令:
“standard”
“singleTop”
“singleTask”
“singleInstance”
默認(rèn)情況下是standard。這些模式被分為兩大類:"standard"和"singleTop"是一類。該模式的Activity可以多次實(shí)例化。實(shí)例可屬于任何任務(wù),并且可以位于Activity堆棧中的任何位置。"singleTask"和"singleInstance"是一類。該模式只能啟動(dòng)任務(wù),它們始終位于Activity堆棧的根位置。此外,設(shè)備一次只能保留一個(gè)Activity實(shí)例。
設(shè)置成singleTask后,系統(tǒng)在新任務(wù)的根位置創(chuàng)建Activity并向其傳送Intent。如果已經(jīng)存在一個(gè)Activity實(shí)例,則系統(tǒng)會(huì)通過(guò)調(diào)用該實(shí)例的onNewIntent()方法向其傳送Intent而不是創(chuàng)建一個(gè)新的Activity實(shí)例。
android:theme
設(shè)定主題格式,與<application>中的theme類似。
<meta-data>元素
指定額外的數(shù)據(jù)項(xiàng),該數(shù)據(jù)項(xiàng)是一個(gè)name-value對(duì),提供給其父組件。這些數(shù)據(jù)會(huì)組成一個(gè)Bundle對(duì)象,可以由PackageItemInfo.metaData字段使用。雖然可以使用多個(gè)<meta-data>元素標(biāo)簽,但是不推薦這么使用。如果有多個(gè)數(shù)據(jù)項(xiàng)要指定,推薦做法是:將多個(gè)數(shù)據(jù)項(xiàng)合并成一個(gè)資源,然后使用一個(gè)<meta-data>包含進(jìn)去。
該元素有三個(gè)屬性:
android:name
數(shù)據(jù)項(xiàng)名稱,這是一個(gè)唯一值。
android:resource
一個(gè)資源的引用。
android:value
數(shù)據(jù)項(xiàng)的值。
<intent-filter>元素
指明這個(gè)activity可以以什么樣的意圖(intent)啟動(dòng)。該元素有幾個(gè)子元素可以包含。我們先介紹遇到的這兩個(gè):
<action>元素
表示activity作為一個(gè)什么動(dòng)作啟動(dòng),android.intent.action.MAIN表示作為主activity啟動(dòng)。
<category>元素
這是action元素的額外類別信息,android.intent.category.LAUNCHER表示這個(gè)activity為當(dāng)前應(yīng)用程序優(yōu)先級(jí)最高的Activity。
總結(jié)
至此,所有的元素信息已經(jīng)分析完畢,如有錯(cuò)誤,歡迎各位讀者指正。后面再遇到什么元素會(huì)繼續(xù)往里面添加。