本文翻译自文档:App Manifest,如果有什么不正确的地方还请指正。
简要:
每一个应用程序的根目录下必须有一个 AndroidManifest.xml 文件,这个清单文件用于将重要的信息呈递给 Android 系统,并且在运行应用程序的任何代码之前告诉系统这些信息是必须拥有的。除了其它以外,该清单文件内容如下:
1.为应用程序命名了 Java 包名,而且包名作为应用程序的唯一标识符。
2.它描述了应用程序的组件组成部分 activities,services,broadcast receivers, 和 content providers,还为实现每一个组件和说明它们的功能的类命了名。这些声明让安卓系统知道这些组件是什么,在什么条件下可以启动它。
3.它决定了哪个进程将持有应用程序组件。
4.它声明了应用程序必须具有访问某些受保护 API 的权限,并与其他应用程序进行交互的权限。
5.它还声明了其它应用程序要访问自己的应用程序需要的权限。
6.它列出了应用程序在运行时提供分析和其它信息的 Instrumentation 类,这些声明仅在应用程序正在开发和测试时才出现在清单文件中,在应用程序发布前被删除。
7.它声明了应用程序需要的最低级别的 Android API。
8.它列出了应用程序必须链接到的库。
清单文件结构:
下图显示了清单文件的总体结构和它拥有的每一个元素。每一个元素,连同其所有的属性,都被记录在一个单独的文件中。要查看任何元素的详细信息,请单击图表中的元素名称,或下图中的元素的字母表,或在任何其他的被提及的元素名称。
<?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>
在清单文件中出现的所有元素按字母顺序排列如下,这些是仅有的符合规定的元素,你不能添加你自己的属性和元素。
<action>
<activity>
<activity-alias>
<application>
<category>
<data>
<grant-uri-permission>
<instrumentation>
<intent-filter>
<manifest>
<meta-data>
<permission>
<permission-group>
<permission-tree>
<provider>
<receiver>
<service>
<supports-screens>
<uses-configuration>
<uses-feature>
<uses-library>
<uses-permission>
<uses-sdk>
文件规范
一些规范和规则适用于在清单中的所有元素和属性:
元素:
只有元素<manifest>和<application>是必须的,它们都必须存在且只能出现一次。大多数其它的元素可以出现多次或者根本不存在(但是为了达到任何元素都有意义的目的,有些元素至少必须出现在清单文件中)。
如果一个元素包含任何内容或者其它元素,所有的值都是通过属性设置,而不是在元素内的字符数据。
同一级别的元素是无序的,例如:<activity>,<service>和<provider>是可以混合在任何序列中的(<activity-alias>元素除外,它必须跟随<activity>)。
属性:
在正式意义上,所有的元素都是可选的。然而,有些为了完成它的目的是必须被指定的。对于真正的可选属性,它涉及一个默认值或者阐述在缺少规范下会发生什么。
除了根元素<manifest>的一些属性,所有的属性命名以android:前缀开始,例如:android:alwaysRetainTaskState。由于前缀是通用的,当通过名称引用属性时,文档通常会省略它。
声明类名:
许多元素对应着 Java 对象,包括 application (<application>)它自己,以及 application 的主要组件 activities(<activity>) , services(<service>) , broadcast receivers(<receiver>)和 content providers(<provider>)。
如果你定义了一个子类,而且当你把它定义为组件(activity ,service ,content provider , broadcast receiver )类时,这个子类可以通过属性名称来声明。例如,一个 Service 的可能被声明如下:
<manifest . . . > <application . . . > <service android:name="com.example.project.SecretService" . . . > . . . </service> . . . </application> </manifest>
<manifest package="com.example.project" . . . > <application . . . > <service android:name=".SecretService" . . . > . . . </service> . . . </application> </manifest>
当启动一个组件时,Android 会创建一个名为子类的实例,如果子类未被指定,那么会创建一个基类的实例。
多值:
如果指定的值超过了一个,则该元素几乎总是重复的,而不是在一个单独的元素中列出多个值,例如:一个 intent filter 可列出几个 action :
<intent-filter . . . > <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.INSERT" /> <action android:name="android.intent.action.DELETE" /> . . . </intent-filter>
一些属性拥有可能被呈现在用户面前的值,例如:一个 activity 的 icon 和 label 。这些属性的值应该是局部的,因此可从主题或者资源中设置,资源值以下例的格式表示:
@[package:]type:name
如果资源在相同的包中,其中和应用程序一样 package 是可以省略的。type 是资源的类型,像 "string" 或者 "drawable",name 是标识指定资源的名字,例如:
<activity android:icon="@drawable/smallPic" . . . >
主题的值也以类似的方式表示,只不过初始是 "?" 而不是 "@":
?[package:]type:name
字符串值:
其中属性值是一个字符串,双反斜杠("\\")必须使用转义字符,例如:"\\n"是换行,"\\uxxxx"是Unicode字符。
文件功能:
下面的部分描述了反映在清单文件中的一些 Android 功能是怎样的。
Intent Filters
一个应用程序的核心组件(activities, services, broadcast receivers 和 content providers)是通过 intents 来启动的,一个 Intent 是一批信息(an Intent object)来描述所需的行为,其中包括被执行的 data ,应执行的组件的 action ,以及其他相关的指令。Android 会找到一个合适的组件来响应这个 Intent,如果需要的话,就启动一个组件的新实例,并通过它这个 Intent 对象。
组件提供它的能力,通过 intent filters 得知哪种类型的 intents 它可以响应。因为 Android 系统必须学会在它启动组件之前哪个组件能够处理这些 intents 。intent filters 在清单文件中被指定为 <intent-filter> 元素,一个组件可以有任意数量的 filters,每一个描述一个不同的能力。
一个 intent 明确地指明了目标组件的名称时,就将启动该组件,这时 filters 将没有任何作用。但是一个 intent 没有通过名称来指定一个目标时,也可能启动一个组件,条件是某个组件的 filters 可以符合它。
Icons and Labels
为了在用户面前展示一个小图标和文本标签,很多元素都拥有 icon 和 label 属性。有一些还具有可以显示在屏幕上的一个较长的解释性文本描述属性,例如:元素<permission>有三个属性,为了当用户被询问是否授予权限给请求它的应用程序时,该权限需要的图标,名称以及描述都可以向用户呈现。
在每一个案例中,如果 icon 和 label 设置在父元素中,那么它将是所有子元素的默认 icon 和 label 设置。因此,设置在<application>元素中的 icon 和 label 将是每一个应用程序组件的默认 icon 和 label。相似地,icon 和 label 设置在一个组件中也一样。例如:在一个<activity>元素中,它就是<intent-filter>元素的默认设置。如果一个<application>元素设置了一个 label,但是<activity>和它的 <intent-filter> 并没有设置,那么<application>的 label 就会被视为<activity>和它的<intent-filter>的 label。
如果设置在intent filter中的 icon 和 label 被用于表示一个组件,那么无论何时这个组件呈现在用户面前,都要通过这个filter来以满足通知功能。例如:一个附带有"android.intent.action.MAIN"和"android.intent.category.LAUNCHER"设置的 filter 是通知一个作为启动应用程序的activity,也是应用程序被启动所展示的那个activity。因此,设置在 filter中的 icon 和 label 将被展示在启动界面。
Permissions
permission是限制访问设备上部分代码和数据的约束条件,这个限制是强制保护那些可能被滥用导致曲解和损害用户体验的关键代码和数据。
每一个权限被一个独特的标签标识。通常标签表示的动作是受限制的。例如,这里有一些由安卓定义的权限:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
一个功能至多被一个权限所保护。
如果一个应用程序需要访问某个被权限保护的功能,那么它必须在清单中通过<uses-permission>元素来声明它需要的权限。然后,当应用程序安装在设备上时,安装程序通过检查权威机构签发的应用程序证书,或者在某些情况下,询问用户,来决定是否授予它请求的权限。如果权限被授予,则该应用程序就能够使用这些受保护的功能。如果没有,它试图访问这些功能时将简单地失败,且没有任何信息通知用户。
一个应用程序还可以通过权限来保护它自己的组件(activities,services,broadcast receivers,content providers),它可以使用任何Android定义的权限或者其它应用程序声明的权限,或者它自己定义的权限。一个新的权限通过<permission>元素来定义,例如,一个activity可以被保护如下:
<manifest . . . > <permission android:name="com.example.project.DEBIT_ACCT" . . . /> <uses-permission android:name="com.example.project.DEBIT_ACCT" /> . . . <application . . .> <activity android:name="com.example.project.FreneticActivity" android:permission="com.example.project.DEBIT_ACCT" . . . > . . . </activity> </application> </manifest>注意,在这个例子中,DEBIT_ACCT权限不仅通过<permission>元素声明,而且还要通过<uses-permission>元素声明。为了其它应用程序的组件启动这个受保护的activity,权限的使用必须被要求,尽管这个保护是被应用程序它自己强制加的。
如果,permission属性设置的权限允许其它地方声明,它就没有必要再一次通过<permission>元素来声明。然而,它仍然有必要要求通过<uses-permission>元素声明。
<permission-tree>元素为一组将在代码中被定义的权限声明了一个命名空间。<permission-group>定义了一组权限标签(包括那些在清单中声明的<permission>元素和其它地方声明的)。它只会影响到当呈现给用户的时候这些权限是怎么被分组的。<permission-group>元素没有指定那个权限属于哪个组,它只给了组的名称。被放置在组中的权限通过分配组名给<permission>元素的permissionGroup元素。
Libraries
每一个应用程序链接到默认的Android库,包括用于构建应用程序的基本包(普通类,如Activity, Service, Intent, Button, View, Application, ContentProvider等等)。
然而,有些包驻留在他们自己的库中。如果你的应用程序使用任何这些包中的代码,它必须明确地要求与它们联系起来。另外,清单必须包含一个单独的<uses-library>元素来命名每一个库(在文件中可找到该包的库名)。