原文在这里:http://developer.android.com/guide/topics/manifest/manifest-intro.html
*Manifest译作“清单”,这里沿用英文便于理解,其它术语同理。
**文中链接都会跳转到android开发者网站。
App Manifest
每一个应用都必须在它的根目录有一份AndroidManifest.xml文件(必须使用这个名字)。Android系统必须在运行应用的任何代码之前了解一些重要信息,这些信息就来自于这份manifest文件。Manifest做的事情包括但不限于以下内容:
- 它提供了应用中的Java包的命名。包名是用于区别当前应用与其他应用的标识符。
- 它描述了应用中的所有组件 -组成应用的activity,service,broadcast receiver和content provider。同时它给实现这些组件的类命名,并公布了它们的作用范围(比如它们可以处理什么样的intent)。这些声明让Android系统可以了解应用有哪些组件以及在什么情况下可以启动它们。
- 它决定了应用的组件是运行在哪一个进程中的。
- 它声明了应用需要哪些权限。权限是用来访问一些受保护的系统API,以及跟其他应用安全交互。
- 它也声明了应用自己创建的权限。其他应用如果要跟当前应用的组件交互,就需要在自己的manifest中声明这些权限。
- 它列出了应用的instrumentation类。这个类可以提供应用在运行时的profiling和其他信息。只有在开发和测试阶段才会需要列在manifest中,应用发布前记得移除。
- 它声明了应用需要的最低Android API等级。
- 它列出了应用必须要链接到的一些库。
*关于profiling和instrumentation我力不能及,果断沿用英文,解释看这里:http://dbanotes.net/database/instrumentation_profiling.html
Manifest文件的结构
下图显示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中的元素都列在下方了。只有它们是合法的元素,你不能添加你自己的元素或者属性。
<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中所有元素和属性都应用到的一些惯例和规则。
元素
只有<manifest>和<application>元素是必须的,它们必须要呈现在manifest中且只能出现一次。其他大多数元素都可以出现很多次或者不出现——尽管为了让你的manifest有意义,还是要有一些元素要写进去的。
如果一个元素可以完全包含所有东西,那么它会包含一些别的元素。所有的数据都是通过属性设定的,而不是通过元素的character data (此处可能是xml的术语)。
同一级的元素一般是不排序的。举例,<activity>, <provider>,和<service> 元素可以按任何顺序混在一起。(activity-alias>元素是一个例外,它必须紧跟它想要化名的<activity>。)
属性
正常来说,所有属性都是随意可选的。但是有一些属性只能针对特定元素来使用以完成它的功能。请参考文档作为指导。对于那些真的是随意可选的,如果留空,那么系统会分配一个默认值。
除了根节点的<manifest>元素中用到的某些属性,所有的属性都以android:当作前缀 - 举例,android:alwaysRetainTaskState. 因为这个前缀是普遍通用的,所以文档中提到属性名称的时候一般会省略它。
声明类名
许多元素都对应着Java对象,包括代表应用本身的元素(<application>元素),和它的基本组件——<activity>, <service>, <receiver>, <provider>。
如果你定义了一个子类,当然大部分情况下你都会用到组件类的子类,这个子类需要通过name属性来声明。它的名称必须包括了所属包的包名。举例,一个Service的子类应可以被定义成下面这样:
<manifest . . . > <application . . . > <service android:name="com.example.project.SecretService" . . . > . . . </service> . . . </application> </manifest>
然而,更简便的方法是,如果字符串的第一个字符是一个句号(注:英文句号,就是个点 -> "."),这个字符会自动用应用的包名扩展(定义在<manifest>元素的package属性中)。下面的方式跟上面能达到一样的赋值效果:
<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的标签和图标。这些属性的值要从资源或者主题中分配并设置。资源的值请用以下的格式表述:
@[package:]type:name
当资源是跟应用在同一个包中,上句中的包名可以省略。type是指资源的类型,比如“string”或者“drawable” - name是可以标识指定资源的名称,举例:
<activity android:icon="@drawable/smallPic" . . . >
?[package:]type:name
字符串类型的值
当一个属性的值是字串,必须使用双反斜线(“\\”)来起始转义字符。比如"\\n"用来换行,"\\uxxxx"表示一个Unicode字符。
特色功能
下面这个章节描述了一些Android特色功能是如何体现在manifest中的。
Intent过滤器
应用的核心组件(activity, service, broadcast receiver )都是通过intent呼叫起来的。intent是一个携带了“要做的动作”相关信息的bundle (束?)- 包括将要处理的数据,将要执行这个动作的组件的分类,以及其他相关的指令。Android将分配一个合适的组件来响应这个intent,如果需要的话会启动一个这个组件的实例,并将这个intent对象发送给它。
组件通过intent filter来广播它的作用范围,即它会响应哪些intent。由于Android系统必须要在一个组件被启动之前知道它能处理哪些intent,就需要应用在manifest的<intent-filters>元素指定好intent filter。一个组件可以有任意数目的intent filter,每一个都描述一个不同的作用范围。
一个明确指定组件类名的intent可以启动对应的组件;过滤器在这里面没有发挥作用。但是一个没有执行目标类名的intent,只能通过intent filter来启动一个组件。
如果想了解intent filter如何筛选intent对象,请访问单独的文档, Intents and Intent Filters。
图标和标签
相当数量的元素拥有icon和label属性,即可以显示一个小图标和一个文字标签给用户。一些元素还拥有description属性,即长篇的解释性文字,也可以在屏幕上显示出来。举例,<permission>元素拥有这三种属性,所以当用户被问到是否允许某个应用申请权限,用户会看到表示权限的图标,权限的名称和权限的详细描述。
任何情况下,元素拥有的图标和标签都会成为它的子元素的默认图标和标签。这样的话,<application>元素中的图标和标签就是它的所有组件的默认图标和标签。同样的,一个组件的图标和标签也会成为它所有<intent-filter>的默认图标和标签,比如一个activity。如果<application>元素中设定了标签,但是activity和它的intent filter没有,那么应用的标签就会当作activity和intent filter的标签。
intent filter的图标和标签是用在系统展示给用户哪些组件可以用来完成某项功能(应用就是intent filter来向系统表明自己可以完成某项功能)的时候。举例,一个带着"android.intent.action.MAIN"和"android.intent.category.LAUNCHER"的filter可以向系统表明这个activity是应用的启动activity,也就是应该显示在launcher中的activity。这样,这个filter的图标和标签就显示在launcher中了。
权限
Permission权限是限制访问设备上的部分代码或数据的约束条件。这个限制是为了保护重要的代码和数据以防被误用而破坏用户体验。
每个权限都是用一个独一无二的标签来标识。一般标签就会表明它要限制的行为。举例,这里有一些Android定义的权限:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
一个特定功能至多会被一个权限保护。
如果应用需要访问被权限保护的功能,它必须在manifest中用<uses-permission>元素来申请权限。然后,当应用安装到设备上时,安装器会通过检查应用签名的发布者,或者在一些情况下直接询问用户,来决定是否允许申请的权限。让权限被允许时,应用可以使用受保护的功能。反之,它访问受保护功能的动作会直接失败并且不会通知用户。
应用也可以用权限来保护自己的组件。它可以采用任何Android定义的权限,或其它应用定义的。甚至它可以定义自己的权限。声明一个新的权限需要用到<permissions>元素。举例,下面的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属性中的要填的是一个其他地方声明过的权限,比如android.permissionCALL_EMERGENCY_NUMBERS,就不需要再用<permission>元素声明了,不过还是要是用<uses-permission>申请才行。
<permission-tree>元素声明了一个权限组定义在代码中的的命名空间。<permission-group>为一个权限的集合(包括在manifest中用<permission>声明的权限,以及定义在其它地方的权限)定义了一个统一的标签。它只会影响权限按组呈现给用户的结果。<permission-group>元素没有指定哪一个权限属于这个组;它只是给了权限组一个标签。通过给<permission>元素的permission-group属性赋值可以将权限归类到特定的组。
库
每个应用都链接到默认的Android库,这里面包括了基本的用于构建应用的包(比如一些常见的类 Activity, Service, View, Button, Application, ContentProvider等等)。
但是有些包依赖于它们自己的库。当你的应用使用了这种包,它必须明确地请求链接到依赖的库。Manifest中必须包含一个单独的<uses-library>元素来指名每一个库。(库名可以在包的文档中找到。)