Android知識點回顧之Manifest檔案-上篇

星泉毅發表於2019-03-01

定義:AndrodiManifest.xml檔案為Android程式的入口檔案,並且是必須的,位於整個專案的根目錄下。拿到一個Android專案,可以先從AndroidManifest.xml檔案入手,進行分析。它提供了一些必要的資訊,比如程式的入口Activity,其他元件的宣告,許可權的宣告,包名,版本資訊等。

Manifest可以做以下事情:

  • 定義包名,包名為APP的唯一標識,每個不同APP的包名必然不同。
  • 元件宣告。Activity,Service,BroadcastReceiver,ContentProvider
  • 確定應用程式元件的程式
  • 許可權宣告
  • 列出Instrumentation類的資訊,提供效能分析和APP在執行的其他資訊
  • 宣告應用支援最低Android API的版本
  • 宣告必須連結的共享類庫

Manifest檔案結構

<?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 />
            <path-permission />
        </provider>

        <uses-library />

    </application>

</manifest>複製程式碼

manifest

清單檔案的根元素,必須包含標籤,指定名稱空間xmlns:android和package屬性

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="string"
          android:sharedUserId="string"
          android:sharedUserLabel="string resource" 
          android:versionCode="integer"
          android:versionName="string"
          android:installLocation=["auto" | "internalOnly" | "preferExternal"] >
    . . .
</manifest>複製程式碼

xmlns:android,定義android名稱空間,通常設定為“schemas.android.com/apk/res/and… 關於xml的名稱空間,可以看這裡

package:不同的APP具有不同的包名。以Java包名風格進行命名,必須唯一。

sharedUserId:具有相同的uderId並且具有相同簽名的APP可以共享和訪問彼此的資料,甚至可以在同一個程式裡面執行,此時必須設定相同。

sharedUserLabel:給共享userId定義了使用者可讀標籤,只有設定了sharedUserId,此屬性才有意義。

versionCode:內部版本號。必須是整數,Integer型別。用來判斷版本的升級,每一次釋出都必須必之前的要大。如果versionName沒有設定,則設定成此值。

versionName:展示給使用者看的版本號。為String型別。

installLocation:設定apk檔案的預設安裝路徑。

  • internalOnly,只能安裝在裝置ROM上(內部儲存),如果裝置ROM空間滿了,則會安裝失敗。如果沒定義androdi:installLocation,則預設設定的是此項。
  • auto,系統優先安裝apk包到內部儲存,如果內部儲存滿了,則會安裝到SD卡。使用者也可以把外部儲存安裝好的應用移到內部儲存上
  • preferExternal,會優先安裝在外部儲存上(SD卡),當無SD卡或SD卡滿了的話,則會安裝到內部儲存上。當然,使用者可以把外部儲存安裝好的應用移到內部儲存上
    關於外部儲存的幾個注意點:
    • .apk檔案是安裝在SD卡上,但是資料還是保持在內部儲存上
    • SD卡上安裝的apk檔案和裝置關聯,把SD卡放到另外一臺裝置進行訪問是不行的。
    • 使用者可以把已安裝好的應用移入內部儲存

許可權

user-permission

宣告APP需要使用到的許可權,Android5.1或以下在安裝的時候聲請,Android6.0或以上的需要執行時許可權申請

<uses-permission android:name="string"
        android:maxSdkVersion="integer" />複製程式碼

name:許可權的名稱。可以是系統定義的許可權,也可以是其他應用的許可權,或者是使用自定義的許可權

maxSdkVersion:此申請的許可權最高的作用Android版本。當一些許可權在高版本無需申請的時候可以設定此值,比如 WRITE_EXTERNAL_STORAGE,在API 19就不需要進行申請了,可以進行如下操作

<uses-permission
     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
     android:maxSdkVersion="18" />複製程式碼

permission

自定義許可權,以限制訪問指定的元件或APP——本APP或其他APP,起到保護的作用。

<permission android:description="string resource"
            android:icon="drawable resource"
            android:label="string resource"
            android:name="string"
            android:permissionGroup="string"
            android:protectionLevel=["normal" | "dangerous" |
                                     "signature" | "signatureOrSystem"] />複製程式碼

description:自定義的使用者可讀的許可權描述,

icon:許可權的icon圖示

label:展示給使用者的許可權名字

name:許可權的命名,為一串唯一的英文字元,如:com.example.READ_ACTIVITY。需要注意的是Android系統不允許不同的包名定義相同的許可權名(permission name),除非不同的包名具有相同的簽名證照。如果一個APP1宣告瞭許可權名A,則系統不允許另外一個宣告瞭許可權名A的不同簽名證照的APP2進行安裝。為了避免這種情況發生,可以以自己APP的包名為字首進行許可權宣告

permissionGroup:許可權所屬的許可權組,此項的值必須為中宣告的name或者是其他APP宣告的。如果此項不設定,則此許可權不屬於許可權組。

protectionLevel:許可權的級別。

  • normal:預設值。低風險的。系統會自動分配此類許可權,而不需要通過使用者來點選確認
  • dangerous:危險的許可權。需要經使用者允許才能夠獲取此類許可權
  • signature:申請許可權的APP必須也宣告此許可權的APP具有相同的簽名才允許獲得。
  • signatureOrSystem:申請許可權的APP必須為系統簽名或是和宣告此許可權的APP具有相同的簽名才允許獲得許可權

要訪問受許可權保護的元件,必須在進行宣告,不論是官方定義的還是自定義的,如:

<manifest>
    <permission android:name="com.example.READ_ACTIVITY"/>
    <uses-permission android:name="com.example.READ_ACTIVITY" />

    <application>
        <activity android:name="com.example.TestActivity"
                  android:permission="com.example.READ_ACTIVITY"
                  >
        </activity>
    </application>
</manifest>複製程式碼

TestActivity宣告瞭READ_ACTIVITY許可權保護,如果要啟動TestActivity,必須要申請READ_ACTIVITY許可權

permission-tree

宣告一個許可權樹,可以在此節點上動態新增許可權,PackageManager.addPermission()。如宣告瞭許可權樹com.example.project.taxes,在此節點上可以動態新增許可權:
com.example.project.taxes.CALCULATE
com.example.project.taxes.deductions.MAKE_SOME_UP
com.example.project.taxes.deductions.EXAGGERATE

需要注意的是此項宣告的不是許可權,是許可權的名稱空間。

<permission-tree android:icon="drawable resource"
                 android:label="string resource" ]
                 android:name="string" />複製程式碼

icon和label與permission的類似。
name為許可權的命名,如:com.example.project.taxes

permission-group

宣告一個邏輯上的許可權分組

<permission-group android:description="string resource"
                  android:icon="drawable resource"
                  android:label="string resource"
                  android:name="string" />複製程式碼

instrumentation

宣告一個Instrumentation類,用來監控APP和系統的互動。Instrumentation物件會在APP的所有元件之前進行例項化。

<instrumentation android:functionalTest=["true" | "false"]
                 android:handleProfiling=["true" | "false"]
                 android:icon="drawable resource"
                 android:label="string resource"
                 android:name="string"
                 android:targetPackage="string" />複製程式碼

functionalTest:是否進行功能性的測試。true:是。false:否。預設值為false

handleProfiling:true:自定義效能分析的開始和結束時間。false:效能分析整個執行過程。預設值為false

name:Instrumentation子類的全名。比如:com.example.project.StringInstrumentation

targetPackage:Instrumentation物件所依賴的目標包名

Instrumentation具體的可看這裡

uses-sdk

<uses-sdk android:minSdkVersion="integer"
          android:targetSdkVersion="integer"
          android:maxSdkVersion="integer" />複製程式碼

minSdkVersion:指定APP執行的所需最低API級別的整數,如果系統API級別低於此值,則會阻止使用者安裝。如果不宣告該屬性,則預設為1。

targetSdkVersion:指定APP目標API級別的整數,不過不宣告該屬性,則預設和minSdkVersion一樣

maxSdkVersion:APP能夠執行在系統的最大API級別。在Android2.0.1以下,如果APP指定的此項低於系統的API級別,則會安裝不了,已安裝的會被隱藏掉。Android2.0.1(不包含)以上的系統不會檢查安裝的APP的此項屬性,所以不會出現2.0.1以下的情況。此值一般不進行設定。

uses-configuration

用來設定APP需要的相關硬體和軟體的配置。大部分APP都不需要此屬性。

<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"] />複製程式碼

reqFiveWayNav:是否需要五維導航控制,如方向版(D-pad),軌跡球等。

reqHardKeyboard:是否需要物理鍵盤

reqKeyboardType:設定所需鍵盤的型別

reqNavigation:指定方向控制的確切型別或不指定(undefined,為預設值)

reqTouchScreen:觸控式螢幕的型別。

uses-feature

用來宣告APP所要使用和依賴的單一的軟硬體功能。該項所提供的require屬性如果是需要的功能,那麼如果缺少的話就會無法使用。比如宣告瞭<uses-feature android:name=”android.hardware.camera” require=”true”/>,如果缺少攝像頭,那麼就會無法使用。並且必須單獨地為每個功能進行宣告。很重要的一點是GooglePlay會根據此項所宣告的功能進行過濾提供給相容裝置的使用者,使用者只能下載和其裝置相容的APP。

<uses-feature
  android:name="string"
  android:required=["true" | "false"]
  android:glEsVersion="integer" />複製程式碼

name:硬體或軟體功能的字串描述。

required:true,當裝置沒有改指定的功能(name)時,APP無法正常工作或設計為無法正常工作;false,有該功能優先使用該功能,無也可正常工作。預設值為true

glEsVersion:所需要的OpenGL ES版本。高16位表示主版本號,底16位表示次版本號。例如,要指定 OpenGL ES 2.0 版,您需要將其值設定為“0x00020000”;要指定 OpenGL ES 3.2,則需將其值設定為“0x00030002”。如果宣告多個,則選擇最高版本的那個,其它的忽略。如果不宣告,則預設為1.0版本,所有Android裝置都支援。

相關文章