AndroidManifest清單文件

分類:編程 時間:2017-02-23

最近做二次開發,修改別人代碼的時候發現清單文件中多了很多奇怪的屬性和標簽(自己以前沒見過的),在不明白的情況下直接開發出現了很多奇怪的問題。所以痛下決心,重新復習下這些基礎知識,以下以6.0系統中的Settings模塊源碼為例講解。

< manifest/>標簽層:

這是整個清單文件的最上層,用來做一些最基本的聲明,如(包名,權限,資源命名空間等)。老規矩,通過栗子來講解:


<manifest coreApp="true"
          package="com.android.settings"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:sharedUserId="android.uid.system"
          android:versionCode="20150101"
          android:versionName="3.0.5">
    <original-package android:name="com.android.settings"/>
    <uses-sdk
        android:minSdkVersion="21"
        android:targetSdkVersion="21"/>

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

1.package=”com.android.settings”
整個應用的包名。這裏有個坑,當我們通過ComponentName來啟動某個Activity時,所用的包名一定是這個應用的包名,而不是當前Activity的包名。

2.xmlns:android=”http://schemas.android.com/apk/res/android”
命名空間的聲明,使得各種Android系統級的屬性能讓我們使用。當我們需要使用自定義屬性時,可以將其修改為res-auto,編譯時會為我們自動去找到該自定義屬性。

3.android:sharedUserId=”android.uid.system”
將當前應用進程設置為系統級進程(不推介隨意這麽做,會產生很多隱患)。擁有此屬性後,我們的應用就可以無視用戶,無法無天地處理很多事情,比如擅自修改手機system分區的內容、靜默安裝等。之前開發過一個類似切換多套開關機動畫和音效的模塊,添加此屬性後,就可以明目張膽地將我們的數據節點存在system分區,可以讓用戶恢復出廠設置都清空不了我們的數據。
但是添加此屬性後,我們需要在當前模塊的MakeFile中添加LOCAL_CERTIFICATE := platform,然後在安卓源碼環境下使用原生make命令編譯才能生效(原生編譯雖然比使用ide工具麻煩很多,但是卻能使用很多ide工具無權限使用的api)。
如果非要在ide工具中使用則必須通過系統密鑰重簽名生成的apk才行(未親自驗證)。

4.uses-permission
為我們的應用添加必須的權限。同時我們也可以該層聲明自定義的權限。

<permission
      android:name="com.cold.permission.appfreeze"
      android:protectionLevel="signatureOrSystem"/>
<application/>標簽層:

應用層標簽,用來配置我們的apk的整體屬性,也可以統一指定所有界面的主題。栗子如下:

<application
    android:name=".SettingsApp"
    android:allowBackup="false"
    android:hardwareAccelerated="true"
    android:icon="@mipmap/ic_launcher_settings"
    android:label="@string/settings_label"
    android:requiredForAllUsers="true"
    android:supportsRtl="true"
    android:taskAffinity=""
    android:theme="@style/Theme.Aui">

1.”android:name”、”android:icon”、”android:label”
顧名思義,用來指定應用的名稱、在桌面的啟動圖標、應用的標簽名

2.”android:theme”
為當前應用的每個界面都默認設置一個主題,可以後續在activity標簽層單獨覆蓋此Theme。

3.”android:allowBackup”
關閉應用程序數據的備份和恢復功能,註意該屬性值默認為true,如果你不需要你的應用被恢復導致隱私數據暴露(如果值為true,甚至可以直接通過adb命令獲取該應用中的數據),必須手動設置此屬性。

4.android:hardwareAccelerated=”true”
開啟硬件加速,一般應用不推介使用。就算非要使用也最好在某個Activity單獨開啟,避免過大的內存開銷。

5.android:taskAffinity
設置Activity任務棧的名稱,可忽略。

<具體組件/>標簽層:

因為< /provider >、< /service>在實際開發中接觸得不多,這部分主要講解 < /activity> 、< /receiver>標簽。

關於Activity標簽的屬性,個人最覺得繞和難掌握的就是Intent-filter的匹配規則了,每次使用錯了都要去查資料修改,所以這邊總結得盡可能仔細。

</activity>

先來一段熱身的代碼,一個最簡單的Activity聲明:

    <activity
        android:name="AgedModeActivity"
        android:icon="@drawable/ic_aged_mode"
        android:label="@string/app_name_label"
        android:theme="@android:style/Theme.NoDisplay"
        android:exported="true"
        android:configChanges="orientation|screenSize|fontScale">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

1.android:configChanges
當我們的界面大小,方向,字體等config參數改變時,我們的Activity就會重新執行onCreate的生命周期。而當我們設置此屬性後,就可以強制讓Activity不重新啟動,而是只會調用一次onConfigurationChanged方法,所以我們可以在這裏做一些相關參數改變的操作。

2.”android.intent.category.LAUNCHER”、”android.intent.action.MAIN”
這兩個屬性共同將當前Activity聲明為了我們應用的入口,將應用註冊至系統的應用列表中,缺一不可。

這裏還有一點需要註意,如果希望我們的應用有多個入口,每個入口能進入到app的不同Activity中時,光設置這兩個屬性還不夠,還要為它指定一個進程和啟動模式。

android:process=”.otherProcess”
android:launchMode =”singleInstance”
至於Activity的四種啟動模式請各位看官自己復習,就不在這兒重述了。

3.android:exported=”true”
將當前組件暴露給外部。屬性決定它是否可以被另一個Application的組件啟動。
熱身結束,我們就來重點分析的匹配規則(顯式調用只需正確使用包名類名即可,隱式調用才需要考慮匹配的問題)。

    <activity android:name="Settings$WirelessSettingsActivity"
            android:taskAffinity="com.android.settings"
            android:label="@string/wireless_Networks_settings_title"
            android:parentActivityName="Settings">
        <intent-filter android:priority="1">
            <action android:name="android.settings.WIRELESS_SETTINGS" />
            <action android:name="android.settings.AIRPLANE_MODE_SETTINGS" />
            <action android:name="android.settings.NFC_SETTINGS" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.VOICE_LAUNCH" />
            <data
                android:scheme="content"
                android:host="com.android.externalstorage.documents"
                android:mimeType="vnd.android.document/root" />
        </intent-filter>
        <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
            android:value="http://www.ithao123.cn/com.android.settings.WirelessSettings" />
        <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
            android:resource="@id/wireless_settings" />
        <!-- Note that this doesn't really show any Wireless settings. -->
        <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
            android:value="http://www.ithao123.cn/true" />
    </activity>

當我們通過intent去隱式調用一個Activity時,需要同時匹配註冊activity中的action、category、data才能正常啟動,而這三個屬性的匹配規則也略有不同。

1.action
action是最簡單的匹配項,我們將其理解為一個區分大小寫的字符串即可,一般用來代表某一種特定的動作,隱式調用時intent必須setAction。一個過濾器中可以有多個action屬性,只要我們的itent和其中任意一項equal則就算匹配成功。

2.category
category屬性也是一個字符串,匹配時也必須和過濾器中定義的值相同。當我們不為intent主動地addCategory時,系統為幫我們默認添加一個值為”android.intent.category.DEFAULT”的category。反過來說,如果我們需要我們自己寫的Activity能接受隱式intent啟動,我們就必須在它的過濾器中添加”android.intent.category.DEFAULT”(深坑!),否則無法成功啟動。

3.data
data比較復雜,幸運地是我們幾乎用不到它。data可以分為mimeType和URI路徑兩部分:
mimeType指定媒體格式類型,音頻、文件、圖片都有特定的屬性值。
URI則有android:scheme、android:host、android:port等屬性組成,scheme代表模式(常用的有http,content,file,package),Host就是一個主機地址,Port則是端口號。
依照上面給出的代碼,為intent設置data時我們可以這樣做:
intent.setDataAndType(Uri.parse(“content://com.android.externalstorage.documents”), “vnd.android.document/root”);

額外擴展一些關於activity的屬性:

<meta-data/>標簽:

標簽 < meta-data>是提供組件額外的數據用的,它本身是一個鍵值對,寫在清單文件中之後,可以在代碼中獲取。栗:

private void getMetaData() {
PDebug.Start(“getMetaData”);
try {
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
if (ai == null || ai.metaData =http://www.ithao123.cn/= null) return;
mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);

      // Check if it has a parent specified and create a Header object
      final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
      String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
      if (parentFragmentClass != null) {
          mParentHeader = new Header();
          mParentHeader.fragment = parentFragmentClass;
          if (parentHeaderTitleRes != 0) {
              mParentHeader.title = getResources().getString(parentHeaderTitleRes);
          }
      }
  } catch (NameNotFoundException nnfe) {
      // No recovery
  }
  PDebug.End("getMetaData");

}
android:excludeFromRecents=”true”
設置為true後,當用戶按了“最近任務列表”時候,該activity不會出現在最近任務列表中,可達到隱藏應用的目的。很黑科技吧~

</receiver>

關於receiver,個人覺得容易混淆的就一個permission問題:

<receiver
    android:name="com.android.settings.AliAgeModeReceiver"
    android:permission="com.android.settings.permission.SWITH_SETTING">
    <intent-filter>
        <action android:name="com.android.settings.action.SWITH_AGED_MODE"/>
    </intent-filter>
</receiver>

起初認為這是receiver中處理一些操作需要使用到此權限,後來查閱資料後發現是通過在中添加permission標簽,我可以發送一些敏感的廣播,只有添加了該permission的receiver才能接收到,而不讓其他的應用收到。栗:

Intent intent = new Intent(“com.android.settings.action.SWITH_AGED_MODE”);
sendBroadcast(intent,”com.android.settings.permission.SWITH_SETTING”);
這要就只有我們自己的接收者才能收到該廣播,但是當我們

Intent intent = new Intent(“com.android.settings.action.SWITH_AGED_MODE”);
sendBroadcast(intent);
則所有有此action的接收者都能收到我們發出的廣播。
總結來說就是:

一些敏感的廣播並不想讓第三方的應用收到 ;
要限制自己的Receiver接收某廣播來源,避免被惡意的同樣的ACTION的廣播所幹擾。
11.01更新:

發現一個可以處理Activity中界面與軟鍵盤顯示的屬性:
android:WindowsoftInputMode=”stateAlwaysHidden”
共有9個屬性,可以分別為軟鍵盤設置禁止、顯示、大小調整等情況。具體怎麽使用,同學們請自行使用搜索引擎~


Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad