一、關於AndroidManifest.xml
AndroidManifest.xml 是每個android程式中必須的檔案。它位於整個專案的根目錄,描述了package中暴露的元件(activities, services, 等等),他們各自的實現類,各種能被處理的資料和啟動位置。 除了能宣告程式中的Activities, ContentProviders, Services, 和Intent Receivers,還能指定permissions和instrumentation(安全控制和測試)
二、AndroidManifest.xml結構
1 <?xmlversion="1.0"encoding="utf-8"?> 2 <manifest> 3 <application> 4 <activity> 5 <intent-filter> 6 <action/> 7 <category/> 8 </intent-filter> 9 </activity> 10 <activity-alias> 11 <intent-filter></intent-filter> 12 <meta-data/> 13 </activity-alias> 14 <service> 15 <intent-filter></intent-filter> 16 <meta-data/> 17 </service> 18 <receiver> 19 <intent-filter></intent-filter> 20 <meta-data/> 21 </receiver> 22 <provider> 23 <grant-uri-permission/> 24 <meta-data/> 25 </provider> 26 <uses-library/> 27 </application> 28 <uses-permission/> 29 <permission/> 30 <permission-tree/> 31 <permission-group/> 32 <instrumentation/> 33 <uses-sdk/> 34 <uses-configuration/> 35 <uses-feature/> 36 <supports-screens/> 37 </manifest
三、各個節點的詳細介紹
上面就是整個am(androidManifest).xml的結構,下面以外向內開始闡述~~
1、第一層(<Manifest>):(屬性)
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.woody.test" android:sharedUserId="string" android:sharedUserLabel="string resource" android:versionCode="integer" android:versionName="string" android:installLocation=["auto" | "internalOnly" | "preferExternal"] > </manifest>
A、xmlns:android
定義android名稱空間,一般為http://schemas.android.com/apk/res/android,這樣使得Android中各種標準屬效能在檔案中使用,提供了大部分元素中的資料。
B、package
指定本應用內java主程式包的包名,它也是一個應用程式的預設名稱
C、sharedUserId
表明資料許可權,因為預設情況下,Android給每個APK分配一個唯一的UserID,所以是預設禁止不同APK訪問共享資料的。若要共享資料,第一可以採用Share Preference方法,第二種就可以採用sharedUserId了,將不同APK的sharedUserId都設為一樣,則這些APK之間就可以互相共享資料了。詳見:http://wallage.blog.163.com/blog/static/17389624201011010539408/
D、sharedUserLabel
一個共享的使用者名稱,它只有在設定了sharedUserId屬性的前提下才會有意義
E、versionCode
是給裝置程式識別版本(升級)用的必須是一個interger值代表app更新過多少次,比如第一版一般為1,之後若要更新版本就設定為2,3等等。。。
F、versionName
這個名稱是給使用者看的,你可以將你的APP版本號設定為1.1版,後續更新版本設定為1.2、2.0版本等等。。。
G、installLocation
安裝引數,是Android2.2中的一個新特性,installLocation有三個值可以選擇:internalOnly、auto、preferExternal
選擇preferExternal,系統會優先考慮將APK安裝到SD卡上(當然終端使用者可以選擇為內部ROM儲存上,如果SD儲存已滿,也會安裝到內部儲存上)
選擇auto,系統將會根據儲存空間自己去適應
選擇internalOnly是指必須安裝到內部才能執行
(注:需要進行後臺類監控的APP最好安裝在內部,而一些較大的遊戲APP最好安裝在SD卡上。現預設為安裝在內部,如果把APP安裝在SD卡上,首先得設定你的level為8,並且要配置android:installLocation這個引數的屬性為preferExternal)
2、第二層(<Application>):屬性
一個AndroidManifest.xml中必須含有一個Application標籤,這個標籤宣告瞭每一個應用程式的元件及其屬性(如icon,label,permission等)
<application android:allowClearUserData=["true" | "false"] android:allowTaskReparenting=["true" | "false"] android:backupAgent="string" android:debuggable=["true" | "false"] android:description="string resource" android:enabled=["true" | "false"] android:hasCode=["true" | "false"] android:icon="drawable resource" android:killAfterRestore=["true" | "false"] 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" > </application>
A、android:allowClearUserData('true' or 'false')
使用者是否能選擇自行清除資料,預設為true,程式管理器包含一個選擇允許使用者清除資料。當為true時,使用者可自己清理使用者資料,反之亦然
B、android:allowTaskReparenting('true' or 'false')
是否允許activity更換從屬的任務,比如從簡訊息任務切換到瀏覽器任務
C、android:backupAgent
這也是Android2.2中的一個新特性,設定該APP的備份,屬性值應該是一個完整的類名,如com.project.TestCase,此屬性並沒有預設值,並且類名必須得指定(就是個備份工具,將資料備份到雲端的操作)
D、android:debuggable
這個從字面上就可以看出是什麼作用的,當設定為true時,表明該APP在手機上可以被除錯。預設為false,在false的情況下除錯該APP,就會報以下錯誤:
Device XXX requires that applications explicitely declare themselves as debuggable in their manifest.
Application XXX does not have the attribute 'debuggable' set to TRUE in its manifest and cannot be debugged.
E、android:description/android:label
此兩個屬性都是為許可提供的,均為字串資源,當使用者去看許可列表(android:label)或者某個許可的詳細資訊(android:description)時,這些字串資源就可以顯示給使用者。label應當儘量簡短,之需要告知使用者該許可是在保護什麼功能就行。而description可以用於具體描述獲取該許可的程式可以做哪些事情,實際上讓使用者可以知道如果他們同意程式獲取該許可權的話,該程式可以做什麼。我們通常用兩句話來描述許可,第一句描述該許可,第二句警告使用者如果批准該許可權會可能有什麼不好的事情發生
F、android:enabled
Android系統是否能夠例項化該應用程式的元件,如果為true,每個元件的enabled屬性決定那個元件是否可以被 enabled。如果為false,它覆蓋元件指定的值;所有元件都是disabled。
G、android:hasCode('true' or 'false')
表示此APP是否包含任何的程式碼,預設為true,若為false,則系統在執行元件時,不會去嘗試載入任何的APP程式碼
一個應用程式自身不會含有任何的程式碼,除非內建元件類,比如Activity類,此類使用了AliasActivity類,當然這是個罕見的現象
(在Android2.3可以用標準C來開發應用程式,可在androidManifest.xml中將此屬性設定為false,因為這個APP本身已經不含有任何的JAVA程式碼了)
H、android:icon
這個很簡單,就是宣告整個APP的圖示,圖片一般都放在drawable資料夾下
I、android:killAfterRestore
J、android:manageSpaceActivity
K、android:name
為應用程式所實現的Application子類的全名。當應用程式程式開始時,該類在所有應用程式元件之前被例項化。
若該類(比方androidMain類)是在宣告的package下,則可以直接宣告android:name="androidMain",但此類是在package下面的子包的話,就必須宣告為全路徑或android:name="package名稱.子包名成.androidMain"
L、android:permission
設定許可名,這個屬性若在<application>上定義的話,是一個給應用程式的所有元件設定許可的便捷方式,當然它是被各元件設定的許可名所覆蓋的
M、android:presistent
該應用程式是否應該在任何時候都保持執行狀態,預設為false。因為應用程式通常不應該設定本標識,持續模式僅僅應該設定給某些系統應用程式才是有意義的。
N、android:process
應用程式執行的程式名,它的預設值為<manifest>元素裡設定的包名,當然每個元件都可以通過設定該屬性來覆蓋預設值。如果你想兩個應用程式共用一個程式的話,你可以設定他們的android:process相同,但前提條件是他們共享一個使用者ID及被賦予了相同證照的時候
O、android:restoreAnyVersion
同樣也是android2.2的一個新特性,用來表明應用是否準備嘗試恢復所有的備份,甚至該備份是比當前裝置上更要新的版本,預設是false
P、android:taskAffinity
擁有相同的affinity的Activity理論上屬於相同的Task,應用程式預設的affinity的名字是<manifest>元素中設定的package名
Q、android:theme
是一個資源的風格,它定義了一個預設的主題風格給所有的activity,當然也可以在自己的theme裡面去設定它,有點類似style。
3、第三層(<Activity>):屬性
<activity android:allowTaskReparenting=["true" | "false"] android:alwaysRetainTaskState=["true" | "false"] android:clearTaskOnLaunch=["true" | "false"] android:configChanges=["mcc", "mnc", "locale", "touchscreen", "keyboard", "keyboardHidden", "navigation", "orientation", "screenLayout", "fontScale", "uiMode"] android:enabled=["true" | "false"] android:excludeFromRecents=["true" | "false"] android:exported=["true" | "false"] android:finishOnTaskLaunch=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:launchMode=["multiple" | "singleTop" | "singleTask" | "singleInstance"] android:multiprocess=["true" | "false"] android:name="string" android:noHistory=["true" | "false"] android:permission="string" android:process="string" android:screenOrientation=["unspecified" | "user" | "behind" | "landscape" | "portrait" | "sensor" | "nosensor"] android:stateNotNeeded=["true" | "false"] android:taskAffinity="string" android:theme="resource or theme" android:windowSoftInputMode=["stateUnspecified", "stateUnchanged", "stateHidden", "stateAlwaysHidden", "stateVisible", "stateAlwaysVisible", "adjustUnspecified", "adjustResize", "adjustPan"] > </activity>
(注:有些在application中重複的就不多闡述了)
1、android:alwaysRetainTaskState
是否保留狀態不變, 比如切換回home, 再從新開啟,activity處於最後的狀態。比如一個瀏覽器擁有很多狀態(當開啟了多個TAB的時候),使用者並不希望丟失這些狀態時,此時可將此屬性設定為true
2、android:clearTaskOnLaunch
比如 P 是 activity, Q 是被P 觸發的 activity, 然後返回Home, 重新啟動 P,是否顯示 Q
3、android:configChanges
當配置list發生修改時, 是否呼叫 onConfigurationChanged() 方法 比如 "locale|navigation|orientation".
這個我用過,主要用來看手機方向改變的. android手機在旋轉後,layout會重新佈局, 如何做到呢?
正常情況下. 如果手機旋轉了.當前Activity後殺掉,然後根據方向重新載入這個Activity. 就會從onCreate開始重新載入.
如果你設定了 這個選項, 當手機旋轉後,當前Activity之後呼叫onConfigurationChanged() 方法. 而不跑onCreate方法等.
4、android:excludeFromRecents
是否可被顯示在最近開啟的activity列表裡,預設是false
5、android:finishOnTaskLaunch
當使用者重新啟動這個任務的時候,是否關閉已開啟的activity,預設是false
如果這個屬性和allowTaskReparenting都是true,這個屬性就是王牌。Activity的親和力將被忽略。該Activity已經被摧毀並非re-parented
6、android:launchMode(Activity載入模式)
在多Activity開發中,有可能是自己應用之間的Activity跳轉,或者夾帶其他應用的可複用Activity。可能會希望跳轉到原來某個Activity例項,而不是產生大量重複的Activity。這需要為Activity配置特定的載入模式,而不是使用預設的載入模式
Activity有四種載入模式:
standard、singleTop、singleTask、singleInstance(其中前兩個是一組、後兩個是一組),預設為standard
standard:就是intent將傳送給新的例項,所以每次跳轉都會生成新的activity。
singleTop:也是傳送新的例項,但不同standard的一點是,在請求的Activity正好位於棧頂時(配置成singleTop的Activity),不會構造新的例項
singleTask:和後面的singleInstance都只建立一個例項,當intent到來,需要建立設定為singleTask的Activity的時候,系統會檢查棧裡面是否已經有該Activity的例項。如果有直接將intent傳送給它。
singleInstance:
首先說明一下task這個概念,Task可以認為是一個棧,可放入多個Activity。比如啟動一個應用,那麼Android就建立了一個Task,然後啟動這個應用的入口Activity,那在它的介面上呼叫其他的Activity也只是在這個task裡面。那如果在多個task中共享一個Activity的話怎麼辦呢。舉個例來說,如果開啟一個導遊服務類的應用程式,裡面有個Activity是開啟GOOGLE地圖的,當按下home鍵退回到主選單又啟動GOOGLE地圖的應用時,顯示的就是剛才的地圖,實際上是同一個Activity,實際上這就引入了singleInstance。singleInstance模式就是將該Activity單獨放入一個棧中,這樣這個棧中只有這一個Activity,不同應用的intent都由這個Activity接收和展示,這樣就做到了共享。當然前提是這些應用都沒有被銷燬,所以剛才是按下的HOME鍵,如果按下了返回鍵,則無效
7、android:multiprocess
是否允許多程式,預設是false
具體可看該篇文章:http://www.bangchui.org/simple/?t3181.html
8、android:noHistory
當使用者從Activity上離開並且它在螢幕上不再可見時,Activity是否從Activity stack中清除並結束。預設是false。Activity不會留下歷史痕跡
9、android:screenOrientation
activity顯示的模式
預設為unspecified:由系統自動判斷顯示方向
landscape橫屏模式,寬度比高度大
portrait豎屏模式, 高度比寬度大
user模式,使用者當前首選的方向
behind模式:和該Activity下面的那個Activity的方向一致(在Activity堆疊中的)
sensor模式:有物理的感應器來決定。如果使用者旋轉裝置這螢幕會橫豎屏切換
nosensor模式:忽略物理感應器,這樣就不會隨著使用者旋轉裝置而更改了
10、android:stateNotNeeded
activity被銷燬或者成功重啟時是否儲存狀態
11、android:windowSoftInputMode
activity主視窗與軟鍵盤的互動模式,可以用來避免輸入法皮膚遮擋問題,Android1.5後的一個新特性。
這個屬效能影響兩件事情:
【A】當有焦點產生時,軟鍵盤是隱藏還是顯示
【B】是否減少活動主視窗大小以便騰出空間放軟鍵盤
各值的含義:
【A】stateUnspecified:軟鍵盤的狀態並沒有指定,系統將選擇一個合適的狀態或依賴於主題的設定
【B】stateUnchanged:當這個activity出現時,軟鍵盤將一直保持在上一個activity裡的狀態,無論是隱藏還是顯示
【C】stateHidden:使用者選擇activity時,軟鍵盤總是被隱藏
【D】stateAlwaysHidden:當該Activity主視窗獲取焦點時,軟鍵盤也總是被隱藏的
【E】stateVisible:軟鍵盤通常是可見的
【F】stateAlwaysVisible:使用者選擇activity時,軟鍵盤總是顯示的狀態
【G】adjustUnspecified:預設設定,通常由系統自行決定是隱藏還是顯示
【H】adjustResize:該Activity總是調整螢幕的大小以便留出軟鍵盤的空間
【I】adjustPan:當前視窗的內容將自動移動以便當前焦點從不被鍵盤覆蓋和使用者能總是看到輸入內容的部分
4、第四層(<intent-filter>)
結構圖:
<intent-filter android:icon="drawable resource" android:label="string resource" android:priority="integer" > <action /> <category /> <data /> </intent-filter>
intent-filter屬性
android:priority(解釋:有序廣播主要是按照宣告的優先順序別,如A的級別高於B,那麼,廣播先傳給A,再傳給B。優先順序別就是用設定priority屬性來確定,範圍是從-1000~1000,數越大優先順序別越高)
Intent filter內會設定的資料包括action,data與category三種。也就是說filter只會與intent裡的這三種資料作對比動作
action屬性
action很簡單,只有android:name這個屬性。常見的android:name值為android.intent.action.MAIN,表明此activity是作為應用程式的入口。有關android:name具體有哪些值,可參照這個網址:http://hi.baidu.com/linghtway/blog/item/83713cc1c2d053170ff477a7.html
category屬性
category也只有android:name屬性。常見的android:name值為android.intent.category.LAUNCHER(決定應用程式是否顯示在程式列表裡)
有關android:name具體有哪些值,可參照這個網址:http://chroya.javaeye.com/blog/685871
data屬性
<data android:host="string" android:mimeType="string" android:path="string" android:pathPattern="string" android:pathPrefix="string" android:port="string" android:scheme="string"/>
【1】每個<data>元素指定一個URI和資料型別(MIME型別)。它有四個屬性scheme、host、port、path對應於URI的每個部分:
scheme://host:port/path
scheme的值一般為"http",host為包名,port為埠號,path為具體地址。如:http://com.test.project:200/folder/etc
其中host和port合起來構成URI的憑據(authority),如果host沒有指定,則port也會被忽略
要讓authority有意義,scheme也必須要指定。要讓path有意義,scheme+authority也必須要指定
【2】mimeType(指定資料型別),若mimeType為'Image',則會從content Provider的指定地址中獲取image型別的資料。還有'video'啥的,若設定為video/mp4,則表示在指定地址中獲取mp4格式的video檔案
【3】而pathPattern和PathPrefix主要是為了格式化path所使用的
5、第四層<meta-data>
<meta-data android:name="string" android:resource="resource specification" android:value="string"/>
這是該元素的基本結構.可以包含在<activity> <activity-alias> <service> <receiver>四個元素中。
android:name(解釋:後設資料項的名字,為了保證這個名字是唯一的,採用java風格的命名規範,如com.woody.project.fried)
android:resource(解釋:資源的一個引用,指定給這個項的值是該資源的id。該id可以通過方法Bundle.getInt()來從meta-data中找到。)
android:value(解釋:指定給這一項的值。可以作為值來指定的資料型別並且元件用來找回那些值的Bundle方法:[getString],[getInt],[getFloat],[getString],[getBoolean])
6、第三層<activity-alias>屬性
<activity-alias android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:targetActivity="string"> <intent-filter/> <meta-data/> </activity-alias>
<activity-alias>是為activity建立快捷方式的,如下例項:
<activity android:name=".shortcut"> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <activity-alias android:name=".CreateShortcuts" android:targetActivity=".shortcut" android:label="@string/shortcut"> <intent-filter> <action android:name="android.intent.action.CREATE_SHORTCUT" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity-alias>
其中android.targetActivity是指向對應快捷方式的activity,如上述的shortcut(此Activity名)
android:label是指快捷方式的名稱,而快捷方式的圖示預設是給定的application圖示
7、第三層<service>
【1】service與activity同級,與activity不同的是,它不能自己啟動的,執行在後臺的程式,如果我們退出應用時,Service程式並沒有結束,它仍然在後臺執行。比如聽音樂,網路下載資料等,都是由service執行的
【2】service生命週期:Service只繼承了onCreate(),onStart(),onDestroy()三個方法,第一次啟動Service時,先後呼叫了onCreate(),onStart()這兩個方法,當停止Service時,則執行onDestroy()方法,如果Service已經啟動了,當我們再次啟動Service時,不會在執行onCreate()方法,而是直接執行onStart()方法
【3】service與activity間的通訊
Service後端的資料最終還是要呈現在前端Activity之上的,因為啟動Service時,系統會重新開啟一個新的程式,這就涉及到不同程式間通訊的問題了(AIDL),Activity與service間的通訊主要用IBinder負責。具體可參照:http://zhangyan1158.blog.51cto.com/2487362/491358
【4】
<service android:enabled=["true" | "false"] android:exported[="true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:process="string"> </service>
service標籤內的屬性之前已有描述,在此不重複了~
8、第三層<receiver>
receiver的屬性與service一樣,這裡就不顯示了
BroadcastReceiver:用於傳送廣播,broadcast是在應用程式之間傳輸資訊的一種機制,而BroadcastReceiver是對傳送出來的 Broadcast進行過濾接受並響應的一類元件,具體參照http://kevin2562.javaeye.com/blog/686787
9、第三層<provider>屬性
<provider android:authorities="list" android:enabled=["true" | "false"] android:exported=["true" | "false"] android:grantUriPermissions=["true" | "false"] android:icon="drawable resource" android:initOrder="integer" android:label="string resource" android:multiprocess=["true" | "false"] android:name="string" android:permission="string" android:process="string" android:readPermission="string" android:syncable=["true" | "false"] android:writePermission="string"> <grant-uri-permission/> <meta-data/> </provider>
contentProvider(資料儲存)
【1】android:authorities:
標識這個ContentProvider,呼叫者可以根據這個標識來找到它
【2】android:grantUriPermission:
對某個URI授予的許可權
【3】android:initOrder
10、第三層<uses-library>
使用者庫,可自定義。所有android的包都可以引用
11、第一層
<supports-screens> <supports-screens android:smallScreens=["true" | "false"] android:normalScreens=["true" | "false"] android:largeScreens=["true" | "false"] android:anyDensity=["true" | "false"] />
這是在android1.6以後的新特性,支援多螢幕機制
各屬性含義:這四個屬性,是否支援大屏,是否支援中屏,是否支援小屏,是否支援多種不同密度
12、第二層<uses-configuration />與<uses-feature>效能都差不多
<uses-configuration android:reqFiveWayNav=["true" | "false"] android:reqHardKeyboard=["true" | "false"] android:reqKeyboardType=["undefined" | "nokeys" | "qwerty" | "twelvekey"] android:reqNavigation=["undefined" | "nonav" | "dpad" | "trackball" | "wheel"] android:reqTouchScreen=["undefined" | "notouch" | "stylus" | "finger"] /> <uses-feature android:glEsVersion="integer" android:name="string" android:required=["true" | "false"] />
這兩者都是在描述應用所需要的硬體和軟體特性,以便防止應用在沒有這些特性的裝置上安裝。
13、第二層<uses-sdk />
<uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="integer" android:maxSdkVersion="integer"/>
描述應用所需的api level,就是版本,目前是android 2.2 = 8,android2.1 = 7,android1.6 = 4,android1.5=3
在此屬性中可以指定支援的最小版本,目標版本以及最大版本
14、第二層
<instrumentation /> <instrumentation android:functionalTest=["true" | "false"] android:handleProfiling=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:targetPackage="string"/>
定義一些用於探測和分析應用效能等等相關的類,可以監控程式。在各個應用程式的元件之前instrumentation類被例項化
android:functionalTest(解釋:instrumentation類是否能執行一個功能測試,預設為false)
15、<permission>、<uses-permission>、<permission-tree />、<permission-group />區別~
最常用的當屬<uses-permission>,當我們需要獲取某個許可權的時候就必須在我們的manifest檔案中宣告,此<uses-permission>與<application>同級,具體許可權列表請看此處
通常情況下我們不需要為自己的應用程式宣告某個許可權,除非你提供了供其他應用程式呼叫的程式碼或者資料。這個時候你才需要使用<permission> 這個標籤。很顯然這個標籤可以讓我們宣告自己的許可權。比如:
<permission android:name="com.teleca.project.MY_SECURITY" . . . />
那麼在activity中就可以宣告該自定義許可權了,如:
<application . . .> <activity android:name="XXX" . . . > android:permission="com.teleca.project.MY_SECURITY"> </activity> </application>
當然自己宣告的permission也不能隨意的使用,還是需要使用<uses-permission>來宣告你需要該許可權
<permission-group> 就是宣告一個標籤,該標籤代表了一組permissions,而<permission-tree>是為一組permissions宣告瞭一個namespace。