AndroidManifest--你真的理解了嗎聪廉?

最近做二次開發(fā)瞬痘,修改別人代碼的時候發(fā)現(xiàn)清單文件中多了很多奇怪的屬性和標(biāo)簽(自己以前沒見過的),在不明白的情況下直接開發(fā)出現(xiàn)了很多奇怪的問題板熊。所以痛下決心框全,重新復(fù)習(xí)下這些基礎(chǔ)知識,以下以6.0系統(tǒng)中的Settings模塊源碼為例講解。

<manifest/>標(biāo)簽層:

這是整個清單文件的最上層干签,用來做一些最基本的聲明津辩,如(包名,權(quán)限,資源命名空間等)喘沿。老規(guī)矩情萤,通過栗子來講解:

<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"
    整個應(yīng)用的包名。這里有個坑摹恨,當(dāng)我們通過ComponentName來啟動某個Activity時筋岛,所用的包名一定是這個應(yīng)用的包名,而不是當(dāng)前Activity的包名晒哄。

  • 2.xmlns:android="http://schemas.android.com/apk/res/android"
    命名空間的聲明睁宰,使得各種Android系統(tǒng)級的屬性能讓我們使用。當(dāng)我們需要使用自定義屬性時寝凌,可以將其修改為res-auto柒傻,編譯時會為我們自動去找到該自定義屬性。

  • 3.android:sharedUserId="android.uid.system"
    將當(dāng)前應(yīng)用進(jìn)程設(shè)置為系統(tǒng)級進(jìn)程(不推介隨意這么做较木,會產(chǎn)生很多隱患)红符。擁有此屬性后,我們的應(yīng)用就可以無視用戶伐债,無法無天地處理很多事情预侯,比如擅自修改手機(jī)system分區(qū)的內(nèi)容、靜默安裝等峰锁。之前開發(fā)過一個類似切換多套開關(guān)機(jī)動畫和音效的模塊萎馅,添加此屬性后,就可以明目張膽地將我們的數(shù)據(jù)節(jié)點存在system分區(qū)虹蒋,可以讓用戶恢復(fù)出廠設(shè)置都清空不了我們的數(shù)據(jù)糜芳。
    但是添加此屬性后,我們需要在當(dāng)前模塊的MakeFile中添加LOCAL_CERTIFICATE := platform魄衅,然后在安卓源碼環(huán)境下使用原生make命令編譯才能生效(原生編譯雖然比使用ide工具麻煩很多峭竣,但是卻能使用很多ide工具無權(quán)限使用的api)。
    如果非要在ide工具中使用則必須通過系統(tǒng)密鑰重簽名生成的apk才行(未親自驗證)晃虫。

  • 4.uses-permission
    為我們的應(yīng)用添加必須的權(quán)限皆撩。同時我們也可以該層聲明自定義的權(quán)限。

    <permission
        android:name="com.cold.permission.appfreeze"
        android:protectionLevel="signatureOrSystem"/>

--*

<application/>標(biāo)簽層:

應(yīng)用層標(biāo)簽傲茄,用來配置我們的apk的整體屬性毅访,也可以統(tǒng)一指定所有界面的主題沮榜。栗子如下:

    <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"
    顧名思義蟆融,用來指定應(yīng)用的名稱草巡、在桌面的啟動圖標(biāo)、應(yīng)用的標(biāo)簽名

  • 2."android:theme"
    為當(dāng)前應(yīng)用的每個界面都默認(rèn)設(shè)置一個主題型酥,可以后續(xù)在activity標(biāo)簽層單獨覆蓋此Theme山憨。

  • 3."android:allowBackup"
    關(guān)閉應(yīng)用程序數(shù)據(jù)的備份和恢復(fù)功能查乒,注意該屬性值默認(rèn)為true,如果你不需要你的應(yīng)用被恢復(fù)導(dǎo)致隱私數(shù)據(jù)暴露(如果值為true郁竟,甚至可以直接通過adb命令獲取該應(yīng)用中的數(shù)據(jù))玛迄,必須手動設(shè)置此屬性。

  • 4.android:hardwareAccelerated="true"
    開啟硬件加速棚亩,一般應(yīng)用不推介使用蓖议。就算非要使用也最好在某個Activity單獨開啟,避免過大的內(nèi)存開銷讥蟆。

  • 5.android:taskAffinity
    設(shè)置Activity任務(wù)棧的名稱,可忽略勒虾。
    --*

<具體組件/>標(biāo)簽層:

因為</provider>、</service>在實際開發(fā)中接觸得不多瘸彤,這部分主要講解 </activity> 修然、</receiver>標(biāo)簽。

關(guān)于Activity標(biāo)簽的屬性质况,個人最覺得繞和難掌握的就是Intent-filter的匹配規(guī)則了愕宋,每次使用錯了都要去查資料修改,所以這邊總結(jié)得盡可能仔細(xì)结榄。

</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
    當(dāng)我們的界面大小,方向潭陪,字體等config參數(shù)改變時雄妥,我們的Activity就會重新執(zhí)行onCreate的生命周期。而當(dāng)我們設(shè)置此屬性后依溯,就可以強制讓Activity不重新啟動老厌,而是只會調(diào)用一次onConfigurationChanged方法,所以我們可以在這里做一些相關(guān)參數(shù)改變的操作黎炉。

  • 2."android.intent.category.LAUNCHER"枝秤、"android.intent.action.MAIN"
    這兩個屬性共同將當(dāng)前Activity聲明為了我們應(yīng)用的入口,將應(yīng)用注冊至系統(tǒng)的應(yīng)用列表中慷嗜,缺一不可淀弹。

這里還有一點需要注意,如果希望我們的應(yīng)用有多個入口庆械,每個入口能進(jìn)入到app的不同Activity中時薇溃,光設(shè)置這兩個屬性還不夠,還要為它指定一個進(jìn)程和啟動模式缭乘。

 android:process=".otherProcess" 
 android:launchMode ="singleInstance"

至于Activity的四種啟動模式請各位看官自己復(fù)習(xí)沐序,就不在這兒重述了。

  • 3.android:exported="true"
    將當(dāng)前組件暴露給外部。屬性決定它是否可以被另一個Application的組件啟動策幼。

熱身結(jié)束邑时,我們就來重點分析<intent-filter>的匹配規(guī)則(顯式調(diào)用只需正確使用包名類名即可,隱式調(diào)用才需要考慮匹配的問題)特姐。

        <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="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="true" />
        </activity>

當(dāng)我們通過intent去隱式調(diào)用一個Activity時晶丘,需要同時匹配注冊activity中的action、category唐含、data才能正常啟動铣口,而這三個屬性的匹配規(guī)則也略有不同。

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

  • 2.category
    category屬性也是一個字符串争剿,匹配時也必須和過濾器中定義的值相同已艰。當(dāng)我們不為intent主動地addCategory時,系統(tǒng)為幫我們默認(rèn)添加一個值為"android.intent.category.DEFAULT"的category蚕苇。反過來說哩掺,如果我們需要我們自己寫的Activity能接受隱式intent啟動,我們就必須在它的過濾器中添加"android.intent.category.DEFAULT"(深坑I浴)嚼吞,否則無法成功啟動。

  • 3.data
    data比較復(fù)雜蹬碧,幸運地是我們幾乎用不到它舱禽。data可以分為mimeType和URI路徑兩部分:
    mimeType指定媒體格式類型,音頻恩沽、文件誊稚、圖片都有特定的屬性值。
    URI則有android:scheme罗心、android:host里伯、android:port等屬性組成,scheme代表模式(常用的有http,content,file,package)渤闷,Host就是一個主機(jī)地址疾瓮,Port則是端口號。
    依照上面給出的代碼肤晓,為intent設(shè)置data時我們可以這樣做:
    intent.setDataAndType(Uri.parse("content://com.android.externalstorage.documents"), "vnd.android.document/root");

額外擴(kuò)展一些關(guān)于activity的屬性:
  • <meta-data/>標(biāo)簽:
    標(biāo)簽<meta-data>是提供組件額外的數(shù)據(jù)用的爷贫,它本身是一個鍵值對,寫在清單文件中之后补憾,可以在代碼中獲取漫萄。栗:
    private void getMetaData() {
        PDebug.Start("getMetaData");
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == 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"
    設(shè)置為true后,當(dāng)用戶按了“最近任務(wù)列表”時候盈匾,該activity不會出現(xiàn)在最近任務(wù)列表中腾务,可達(dá)到隱藏應(yīng)用的目的。很黑科技吧~
</receiver>

關(guān)于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>

起初認(rèn)為這是receiver中處理一些操作需要使用到此權(quán)限岩瘦,后來查閱資料后發(fā)現(xiàn)是通過在</receiver>中添加permission標(biāo)簽,我可以發(fā)送一些敏感的廣播窿撬,只有添加了該permission的receiver才能接收到启昧,而不讓其他的應(yīng)用收到。栗:

Intent intent = new Intent("com.android.settings.action.SWITH_AGED_MODE");
sendBroadcast(intent,"com.android.settings.permission.SWITH_SETTING");

這要就只有我們自己的接收者才能收到該廣播劈伴,但是當(dāng)我們

Intent intent = new Intent("com.android.settings.action.SWITH_AGED_MODE");
sendBroadcast(intent);

則所有有此action的接收者都能收到我們發(fā)出的廣播密末。
總結(jié)來說就是:

  1. 一些敏感的廣播并不想讓第三方的應(yīng)用收到 ;
  2. 要限制自己的Receiver接收某廣播來源跛璧,避免被惡意的同樣的ACTION的廣播所干擾严里。

--*

11.01更新:
  • 發(fā)現(xiàn)一個可以處理Activity中界面與軟鍵盤顯示的屬性:
    android:windowSoftInputMode="stateAlwaysHidden"
    共有9個屬性,可以分別為軟鍵盤設(shè)置禁止追城、顯示刹碾、大小調(diào)整等情況。具體怎么使用座柱,同學(xué)們請自行使用搜索引擎~
    --*
碼字不易迷帜,給個贊唄~
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市色洞,隨后出現(xiàn)的幾起案子瞬矩,更是在濱河造成了極大的恐慌,老刑警劉巖锋玲,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件景用,死亡現(xiàn)場離奇詭異,居然都是意外死亡惭蹂,警方通過查閱死者的電腦和手機(jī)伞插,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盾碗,“玉大人媚污,你說我怎么就攤上這事⊥⒀牛” “怎么了耗美?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵京髓,是天一觀的道長。 經(jīng)常有香客問我商架,道長堰怨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任蛇摸,我火速辦了婚禮备图,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赶袄。我一直安慰自己揽涮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布饿肺。 她就那樣靜靜地躺著蒋困,像睡著了一般。 火紅的嫁衣襯著肌膚如雪敬辣。 梳的紋絲不亂的頭發(fā)上家破,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音购岗,去河邊找鬼汰聋。 笑死,一個胖子當(dāng)著我的面吹牛喊积,可吹牛的內(nèi)容都是我干的烹困。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乾吻,長吁一口氣:“原來是場噩夢啊……” “哼髓梅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绎签,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤枯饿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诡必,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奢方,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年爸舒,在試婚紗的時候發(fā)現(xiàn)自己被綠了蟋字。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡扭勉,死狀恐怖鹊奖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涂炎,我是刑警寧澤忠聚,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布设哗,位于F島的核電站,受9級特大地震影響两蟀,放射性物質(zhì)發(fā)生泄漏网梢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一垫竞、第九天 我趴在偏房一處隱蔽的房頂上張望澎粟。 院中可真熱鬧蛀序,春花似錦欢瞪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至重贺,卻和暖如春骑祟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背气笙。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工次企, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人潜圃。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓缸棵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谭期。 傳聞我的和親對象是個殘疾皇子堵第,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容