以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-sdkandroid: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"//由SystemServer启动而来.很多的服务都是在系统进程里启动的.
    将当前应用进程设置为系统级进程(不推介随意这么做,会产生很多隐患)。拥有此属性后,我们的应用就可以无视用户,无法无天地处理很多事情,比如擅自修改手机system分区的内容、静默安装等。之前开发过一个类似切换多套开关机动画和音效的模块,添加此属性后,就可以明目张胆地将我们的数据节点存在system分区,可以让用户恢复出厂设置都清空不了我们的数据。
    但是添加此属性后,我们需要在当前模块的MakeFile中添加LOCAL_CERTIFICATE := platform,然后在安卓源码环境下使用原生make命令编译才能生效(原生编译虽然比使用ide工具麻烦很多,但是却能使用很多ide工具无权限使用的api)。
    如果非要在ide工具中使用则必须通过系统密钥重签名生成的apk才行(未亲自验证)。

  • 4.uses-permission
    为我们的应用添加必须的权限。同时我们也可以该层声明自定义的权限。

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

--*

<application/>标签层:

应用层标签,用来配置我们的apk的整体属性,也可以统一指定所有界面的主题。栗子如下:

    <applicationandroid: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声明:

        <activityandroid: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的组件启动。

热身结束,我们就来重点分析<intent-filter>的匹配规则(显式调用只需正确使用包名类名即可,隐式调用才需要考虑匹配的问题)。

        <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" /><dataandroid: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>

当我们通过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 == 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 objectfinal 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问题:

    <receiverandroid: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中处理一些操作需要使用到此权限,后来查阅资料后发现是通过在</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的接收者都能收到我们发出的广播。
总结来说就是:

  1. 一些敏感的广播并不想让第三方的应用收到 ;
  2. 要限制自己的Receiver接收某广播来源,避免被恶意的同样的ACTION的广播所干扰

--*

11.01更新:

  • 发现一个可以处理Activity中界面与软键盘显示的属性:
    android:windowSoftInputMode="stateAlwaysHidden"
    共有9个属性,可以分别为软键盘设置禁止、显示、大小调整等情况。具体怎么使用,同学们请自行使用搜索引擎~    

自己更新: 分析一个工程,习惯从manifest.xml入手。

 coreApp="true"

打开manifest.xml,发现配置了这个属性,这个属性有什么作用?

有三个差不多的属性,分别是coreApp="true";android:sharedUserId="android.uid.system";android:process="system"

coreApp="true";android:sharedUserId="android.uid.system";配置在manifest头部,android:process="system"配置在application处。

这有篇文章分析这三个作用http://blog.csdn.net/gu821361889/article/details/50429002

 coreApp="true"表示该应用是系统核心应用.可以优先被分配内存.不是代表该APP具有系统权限

 android:sharedUserId="android.uid.system"增加这个标签,app必须要有系统的签名,不然无法安装。配置了这个属性基本上,想干什么就干什么了。

android:process="system"申明进程的级别,这个标签平时没有使用过。平时一般是这样使用的android:process=":test"申明一个组件运行在一个独立的进程中。之前看到文章说微信使用webview加载网页,但是由于android的  bug,webview 存在内存泄露,所以微信把这个模块放在一个独立进程中,访问完之后直接kill。通过设置进程,可以分离一个复杂的app业务,达到降低核心业务进程的常驻内存,避免被lowmemory kill掉,达到不影响核心业务。

 <meta-data android:name="android.view.im" android:resource="@xml/method" />

         meta-data 元数据,一般用于配置一些配置数据,可以为application、activity、service、receive配置。

共有三个属性,name、resource、value。resource指向的是一个xml文件。meta-data可以被其他程序访问到,配置resource也同样可以访问到,很方便用作一些配置。

android:noHistory="true">

activity组件设置nohistory,activity 在不可见之后自动调用finish()结束。这个值默认是false,默认情况下activity A启动activity B,activity B返回,是回到activity A

如果给activity A 设置noHistory=“true” 则从activity B回不到activity A

清理任务栈

android:clearTaskOnLaunch="true"  到后台之后,除这个activity之外其余activity清除

android:finishOnTaskLaunch="true" 到后台之后,清除该activity

android:alwaysRetainTaskState="true" 到后台之后,不清除activity栈的activity

假如配置的属性不是根activity,会有什么情况了?验证如下

android:clearTaskOnLaunch="true",如果不是根activity,没有效果。

android:finishOnTaskLaunch="true"  作用于根activity没有效果,其余有效果。

android:alwaysRetainTaskState="true" 不好验证,没有验证。

补充activity四种启动模式:

      standard   默认模式,不管怎样都是新建一个activity

      singleTop  栈顶模式,要启动的activity在栈顶,进入OnNewIntent(),不走onCreate()..onStart()..onResume()

      singleTask 如果在activity栈中存在了该activity,会重新走到这个实例里面,调用onNewIntent(),栈里面之上的activity却会销毁。

      singleInstance 顾名思义 单例,栈中就只有一个activity的实例。它是区别其他栈的。这种可以达到复用activity。比如QQ启动了地图的activity,如果activity的模式是singleInstance,那么再打开这个activity就不会重建。只会进入到onNewIntent()里面

AndroidManifest--详细理解相关推荐

  1. Android清单AndroidManifest详细说明

    Android清单AndroidManifest详细说明 在初见Intent一章中,我们已尝试过使用「startActivity」函式,传入适当的「Intent」,来呼叫浏览器的Activity. 到 ...

  2. Maven依赖详细理解

    Maven依赖理解 1 简介 2 依赖的配置 3 依赖的范围 4 传递性依赖 4.1 传递性依赖和依赖调解 5 依赖调解 6 可选依赖 7 总结 8 下载 1 简介  在Maven项目中,有一个核心文 ...

  3. 【时序列】时序列数据如何一步步分解成趋势(trend)季节性(seasonality)和误差(residual)- 详细理解python sm.tsa.seasonal_decompose

    [时序列]时序列数据如何一步步分解成趋势(trend)季节性(seasonality)和误差(residual)- 理解python sm.tsa.seasonal_decompose 在做时序列分析 ...

  4. 模型整合之模型堆叠——详细理解Stacking model

    详细理解Stacking model 如果你得到了10个不一样的model,并且每个model都各有千秋,这个时候你该怎么选?想必你一定是很为难吧,但通过集成方法,你可以轻松的将10个model合成为 ...

  5. 关于A类地址,B类地址,C类地址的划分和详细理解

    关于A类地址,B类地址,C类地址的划分和详细理解 IP地址的指派范围 网络类别 最大可指派的网络数 第一个可指派的网络号 最后一个可指派的网络号 每一个网络中的最大主机数 占IP地址总数比例 A 2^ ...

  6. 绘制扇形的多种方式,包括border-radius、clip裁剪显示、canvas原点变换等方式的详细理解及demo

    对clip的理解: clip是对使用了该样式的元素进行裁剪显示.使用方法是rect (top, right, bottom, left) 其中参数top代表显示的区域上边界离该元素顶部border-t ...

  7. python降维可视化 自编码_deep learning 自编码算法详细理解与代码实现(超详细)...

    在有监督学习中,训练样本是有类别标签的.现在假设我们只有一个没有带类别标签的训练样本集合 ,其中 .自编码神经网络是一种无监督学习算法,它使用了反向传播算法,并让目标值等于输入值,比如 .下图是一个自 ...

  8. [转载] numpy.exp,numpy.sqrt,np.power等函数的详细理解

    参考链接: Python中的numpy.exp2 草鸡详细的np.exp(),np.sqrt(),等运算的理解过程. 一个程序猿世界的小白的自我成长之路 ^_& np.exp(x)表示自然数e ...

  9. 局部二值模式LBP的详细理解

    局部二值模式LBP的噶几详细的理解 一个电脑小白的自我成长之路,总是这么的寂寞.孤独.无聊,却充满新奇.艰难,唯有坚韧不拔,持续奋斗,才可披荆斩棘.登临云端.各位看官们:"咋的,能不能上干货 ...

  10. 一文详细理解计算机网络体系结构(考试和面试必备)

    一. 计算机网络概述 1.1 计算机网络的概念 最简洁的定义\color{#0000FF}{最简洁的定义}最简洁的定义:计算机网络就是一些互连的,自治的计算机系统的集合. 广义观点的定义\color{ ...

最新文章

  1. Learn Python the Hard Way: while循环
  2. tomcat catalina localhost 没有项目_实用shell脚本--一键配置tomcat定期日志清理功能
  3. leetcode43. 字符串相乘
  4. 数据科学 IPython 笔记本 8.3 Matplotlib 可视化
  5. JS获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
  6. 关于U盘不能新建文件夹
  7. 百度离线语音合成SDK使用
  8. AIScanner文字识别软件 OCR
  9. C语言自动计数功能,《Objective-C高级编程》温故知新之自动引用计数
  10. Ubuntu终端中字体颜色含义
  11. Linux下分卷压缩与解压
  12. Redhat rpm常用命令以及如何配置yum软件仓库使用yum install
  13. 决定RDD分区数因素、关联
  14. 网站安全漏洞--大全
  15. python six 用途_python之six用法
  16. 31-三色旗问题(荷兰国旗问题)
  17. easyx文字输出汇总
  18. 51nod1679 连通率
  19. VB6不能加载MSCOMCTL.OCX最简单的解决办法
  20. reactive() 函数

热门文章

  1. 重庆顶香味分析快手春竹笋的制作方法
  2. 12306订票候补是个坑_重磅!12306候补购票正式上线,实测你可能连排队的机会都没有!...
  3. PostgreSQL中uuid的使用,uuid_generate_v4()
  4. Python的多线程和多进程教程:大大提高效率
  5. 003.关于光流传感器(ADNS3080)调焦问题
  6. mysql中的不等于_sql中怎么表示“不等于”(数据库,SQL)
  7. 人身三流指什么_什么是三流明星
  8. 高德地图绘制点(简单实现)
  9. mysql默认存储引擎_MySQL5.5 所支持的存储引擎
  10. Caffeine教程