第8章 AndroidManifest.xml文件

每个Android应用程序在根目录下必定有一个AndroidManifest.xml文件(文件名必须是这个)。这个manifest文件向android系统列出了应用程序的必要信息,有了这些信息,系统才能运行应用程序(linux你懂的)。除此之外,manifest还有以下作用:

◆列举了应用程序的java包。包名是识别应用程序的唯一标志。

◆描述了应用程序的组件——Activity、Service、Broadcast receivers,Content providers。列举了实现每个组件的类,并给出可能的值(例如,类能处理的intent信息)。这些声明使Android系统了解了应用程序包含的组件及其运行条件。

◆确定了宿主应用程序组件的进程。

◆声明了应用程序拥有的权限,使其可以使用API保护的内容,与其他应用程序进行交互。

◆同时,也声明了其他应用程序与该应用程序组件交互所需要的权限。

◆列举了为应用程序运行时提供性能和其他信息的Instrumentation类的声明。这些声明只有在开发和测试的时候才会在manifest中使用,发布的时候需要将这些声明删除。

◆声明了应用程序支持的Android API的最低等级。

◆列举了应用程序必须链接的库。

8.1 Manifest文件结构

下面代码清单8-1中显示了manifest文件的整体结构以及可以使用的所有元素结构。每一个元素都所有属性都在另一个单独的文件中显示。它们按元素的字母顺序排序。其实这种xml格式相信很多人应该非常熟悉了。(请参考http://developer.android.com/intl/zh-CN/guide/topics/manifest/manifest-intro.html

<?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 />
        </provider>

        <uses-library />

    </application>

</manifest>

 

代码清单 8-1

下面按字母顺序列出了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>

8.2文件惯例

一些惯例和规则一般适用于manifest文件中的所有元素和属性:
1. Elements(元素,节点)
只有<manifest>和<application>元素是必须的,而且只能出现一次。大多数其他元素都可以出现多次或者不出现,并且要实现有意义的功能时,有些元素是必不可少的。同等级的元素通常没有固定顺序。例如:<activity>, <provider>, 和<service>可以按任何顺序混合出现。(<activity-alias>通常要要按顺序出现:必须在<activity>之后出现。)
2. Attributes(属性)
正常情况下来说,所有的属性都是可选的。然而,为了实现功能,元素的某些属性是必须要指明的。你可以将这份文档作为指南。对于真正可选的属性,意味着在未指明的时候会有一个默认值或默认状态。 除了<manifest>根元素的某些属性,其他所有的属性都以 android:为前缀——例如,android:alwaysRetainTaskState。因为前缀是通用的,所以当引用属性的名字的时候本文件会自动将其忽略。
3. 声明类名
很多元素都对应着java对象,包括应用程序元素本身(<application>及其主要的组件——<activity>,<service>, <receiver>和<provider)。如果定义一个子类,比如用户通常会定义的组件子类(Activity,Service,BroadcastReceiver,ContentProvider),通常由name属性声明。这个名字必须包括完整的包名。例如,Service的子类必须按如下方法定义:如代码清单8-2所示:

<manifest . . . >
    <application . . . >
        <service android:name="com.example.project.SecretService" . . . >
            . . .
        </service>
        . . .
    </application>
</manifest>

 

代码清单 8-2

但是,作为简写,如果字符串的第一个字符为一个点,那么字符串将会被添加到应用程序的包名(由manifest的package属性指定)之后,下面的赋值跟上面是一样的效果,如代码清单8-3所示:

<manifest package="com.example.project" . . . >
    <application . . . >
        <service android:name=".SecretService" . . . >
            . . .
        </service>
        . . .
    </application>
</manifest>

 

代码清单 8-3

当使用组件时,android会实例化命名的子类。如果子类没有指定,将会实例化父类。
4. 多个值
如果元素可以赋多个值,通常会重复进行。例如,一个intent filter可以列举多个action,如代码清单8-4所示:

<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>

 

代码清单 8-4

5. 资源值
某些属性的值可以显示给用户看——例如,Activity的label和icon。这些属性的值应该本地化,因此可以从一个资源或主题中获取。资源值通常按以下格式表示:@[package:]type:name
其中,如果资源跟应用程序在同一个包中,那么包名可以省略。type是资源的类型——例如“string”或者“drawable”——name是识别具体资源的标识。具体示例如代码清单8=5所示:

<activity android:icon="@drawable/smallPic" . . . >

 

代码清单 8-5

从主题中获取的值可以用类似的方法表示,只不过首字符使用?而不是@:?[package:]type:name
6. 字符串值
当属性值是一个字符串的时候,需要使用双反斜杠('\\')来转义字符——例如'\\n'代表换行,或者'\\uxxxx'代表Unicode字符。

8.3 文件特性

以下内容描述了manifest文件中表现出来的Android特性:

1. Intent Filters

应用程序的核心组件(activities,services,broadcast receivers)由intent激活。intent是一组描述要做的动作的信息(一个intent对象)——包括依赖的数据、执行动作的组件种类和其他相关的说明。Android选用对应的组件来响应intent,需要的时候实例化组件,并将其传给intent对象。
组件通过intent filters表明了自身的能力——能响应的intent的种类。由于android系统在运行之前必须明确组件能够处理哪些intent,因此可以在manifest文件中声明intent过滤器。一个组件可以有多个不同的过滤器,代表不同的能力。显式地指定目标组件的intent将激活该组件;filters并不起作用。但是,如果一个intent没有通过名字指定目标,那么只有在通过组件的某一filters时才会激活组件。

2. Icons和labels

很多元素都有icon和label属性,用于给用户显示一个小图标或者一个文本。有些元素还有一个description属性,用于在屏幕上显示更长的扩展信息。例如,<permission>元素以上三个属性都有,所以当用户要求为应用程序授予权限的时候,将会看到代表权限的图标、权限的名称,以及描述权限作用的信息。在application元素中设定的图标和标签,将会是应用程序中每个组件的默认设置。类似的,组件的图标和标签——例如,activity元素——将会是该组件的每一个intent-filter元素的默认设置。如果application元素设置了一个标签,但是activity和intent filters没有设置,那么应用程序标签将同时适用于activity和intent filters。不管组件何时展现给用户,intent filters设置的图标和标签都代表实现该过滤器(filters)功能的组件。 例如,设置了“android.intent.action.MAIN”和“android.intent.category.LAUNCHER”的过滤器代表了由这个activity来启动应用程序——也就是说,应用程序启动的时候,这个activity最先显示。因此,启动画面显示的图标和标签就是过滤器中设置的图标和标签。 

3. 权限(Permissions)

权限是限制访问设备上的代码或数据。这个限制用于保护关键代码和数据,以免被滥用导致出现错误或影响用户体验。每个权限都有一个唯一的标记。通常这个标记表示被限制的行为。例如,以下是android中定义的一些权限:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
一个特性最多由一个权限控制。如果应用程序需要访问有权限保护的特性,必须在manifest中用<uses-permission>元素声明该应用程序需要使用该权限。然后,安装应用程序的时候,安装程序将检查用户签署的应用程序证书的权限,或者,在某些情况下,询问用户,从而决定是否需要给应用程序授予要求的权限。如果授权成功了,那么应用程序就可以使用被保护的特性了。如果授权失败,那么应用程序尝试访问被保护的特性的时候,将会直接失败,而不通知用户。
应用程序也可以使用权限保护自己的组件(activities,services,broadcast receivers,content providers)。android定义的所有权限(请参考)

http://developer.android.com/intl/zh-CN/reference/android/Manifest.permission.html

或者其他应用程序声明的权限,都可以使用。或者应用程序也可以定义自己的权限。新的权限通过<permission>元素声明。例如,可以按照以下方法保护activity,如代码清单8-6所示:

<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>

 

代码清单 8-6

注意,在这个例子中,DEBIT_ACCT权限不仅使用<permission>元素声明,同时也需要使用<uses-permission>声明。应用程序的其他组件想要运行被保护的activity的时候,就需要使用该权限,即使该activity是被应用程序本身保护的。还是这个例子,如果permission属性已经在其他地方声明过了(比如android.permission.CALL_EMERGENCY_NUMBERS中),那么就无需再用<permission>元素声明了,但是<uses-permission>元素的声明还是需要的。

<permission-tree>元素为代码中需要使用的权限组定义了一个命名空间。<permission-group>元素为权限组定义了一个标签(无论权限是在manifest中使用<permission>元素声明的,还是在其他地方声明的)。区别只是展现给用户的时候,权限是如何组合的。<permission-group>元素不会指明权限属于哪一个组,只给出了组的名字。把组名添加到<permission>元素的<permission-group>属性就可以把该权限分配到该组了。

4.

每一个应用程序都会连接到android的默认库,这个库中包含了编译应用程序需要的基础包(包中含有常用的类,如Activity, Service, Intent, View, Button, Application, ContentProvider等)。

但是,有些包有自己的库。如果应用程序要使用这些包中的代码,就必须显式地链接这些包的库。在manifest文件中必须包含独立的<uses-library>元素,将需要的库全部列举出来。