安卓的应用程序框架(Android’s application framework)利用一组可重复使用的组件可以让你创建极其丰富和新意的APPs。这部分解释了Android Apps 如何工作以及你如何利用组件建立他们。

一、应用基本要素(Application Fundamentals

Android 应用是用Java语言编写。安卓软件开发工具包(Android SDK tools)编译代码以及其他数据和资源文件到一个安卓安装包(Android Package)中,以.apk后缀的安装(archive)文件。一个.apk文件中的所有代码被认为是同一个应用同时.apk文件也是应用在安装设备的安装文件。

一旦在设备上安装后,每个安卓应用都位于独自的安全沙箱(security sandbox)中:

· Android操作系统是一个多用户的Linux系统,每个应用是一个不同的用户。

· 默认地,系统给每个应用分配一个唯一的Linux用户ID(应用并不知道这个ID,只有系统使用)。系统为应用中的所有文件设置权限,这样只有分配给应用的用户ID可以使用他们。

· 每个进程有各自的虚拟机(VM),因此一个应用的代码和其他应用隔离运行。

· 默认地,每个应用运行在各自Linux进程。当任何一个应用的组件需要被执行时,Android 开始进程,然后当它不需要或者系统必须为其他应用恢复内存(recover memory)时关闭进程。

这样,安卓系统实行最小权限原则(principle of least privilege POLP)。换言之,每个应用,默认地,只能访问它工作需要的组件。这样创造了一个非常安全的环境,在这里应用不能访问没有被授权的系统部分。

然后,这里有多种方式让一个应用和其他应用之间共享数据以及让应用访问系统服务:

l  两个应用共享同样的Linux用户ID,在这种情况下他们可以互相访问对方的文件。为了维护系统资源,拥有相同用户ID的应用运行在同样的Linux进程中并共享相同的虚拟机VM(同样应用必须签署相同的证书)。

l  一个应用可以请求访问设备数据的权限如用户联系人,短消息(SMS message),可安装的存储设备(SD Card),照相机,蓝牙以及更多。所有应用的权限必须在安装是获得用户同意。

这些包含有关系统中Android应用的基本要素。下面的文档将给你介绍:

l  定义应用的核心架构组件。

l  为应用声明组件并要求设备特征的功能性清单文件(manifest)。

l  和应用代码分离的资源允许应用就多种配置的设备优化它的行为。

二、应用组件

应用组件是Android App的基本构造模块。每个组件是系统开始应用的不同点。对用户来说并不是所有的组件都是实际的入口点,有些组件相互依赖,但是每个实际存在的组件都扮演一个特定的角色——每个组件是唯一的帮你规定应用的全部行为的构造模块。

这里有四种不同的应用组件。每种类型组件提供一个清楚的功能并有一个清楚的定义组件如何创立和销毁的(Create and Destroy)生命周期。

这里是四种应用组件的介绍:

活动(Activity

    Activity表示一个带有用户界面(UI)的简单屏幕。例如,一个Email App可能有一个显示新邮件列表的activity,撰写邮件的activity,以及阅读邮件的activity。尽管这些Email App中的activity合作形成了一个完整的用户体验,但是每个activity都是相互独立的。同样如此,其他的应用也可以启动这些activity(只要Email App允许这样)。例如,为了用户共享照片,照相应用可以启动Email App 中的Activity来撰写新邮件。

activity利用Activity的子类实现,你可以在Activity开发指导中学习更多。

服务(Service

Service是一个在后台运行的组件执行长期运行的操作(long-running operation)或者完成远程进程。Service不提供UI。例如,当用户处理其他应用时,service可以在后台播放音乐,或者在网络上获取数据而无需用一个activity来限制UI。其他组件,如activity,可以启动service并让它运行或者为了与之交互而绑定它。

service利用Service的子类实现,你可以在Service开发指导中学习更多。

内容提供者(Content Provider

Content Provider管理共享的应用数据集合。你可以在系统文件,SQLite数据库,网络或者其他应用可以访问的永久存储位置中存储数据。通过Content Provider,其他应用能够查询甚至修改数据(只要content provider允许这样)。例如,Android系统提供一个content provider来管理用户联系人信息。如此,拥有适当权限的应用可以访问content provider(如ContactsContract.Data)来编辑联系人信息。

在读写应用的私有或非共享数据时,content provider同样非常有用。例如,Note Pad应用使用一个content provider保存便签(note)。

content provider利用ContentProvider的子类实现,必须实现一套标准的APIs集合保证其他应用能够完成处理。更多信息请参见Content Providers开发文档。

广播接收者(Broadcast Receiver

Broadcast Receiver是响应系统级广播公告的组件。许多广播——例如,通告屏幕关闭,电量低,或者抓获照片的广播由系统发起。应用也可以发起广播——例如,让其他应用知道数据已经下载到设备并可以使用。尽管broadcast receiver不在UI上显示,当广播事件发生时,他们可能创建一个状态栏通知(create a status bar notification)来提醒(alert)用户。更一般的说,broadcast receiver仅是一个给其他应用的网关gateway 通道)并做少量的工作。举例说明,它可能发起一个基于事件完成动作的服务。

Broadcast Receiver利用BroadcastReceiver的子类实现,每个广播是用Intent对象传递。更多的信息,参见BroadcastReceiver类。

     Android系统设计的一个独特方面是任何应用可以启动其他应用的组件。例如,如果你想要用户获取一张照片,可能是有其他应用做这事,同时你的应用也能使用它,而不是自己开发一个照相activity。你不需要合并甚至不需要从照相应用获取代码。反而,你可以简单的启动照相应用中的获取照片的Activity。完成时,照片返回给你的应用然后你可以使用它。对于用户来说,照相机看起来像你应用的一部分。

当系统启动一个组件时,它启动应用的进程(如果它没有在运行)同时实例化组件需要的类。例如,如果你的应用启动照相应用中的获取照片的activity时,activity运行在照相应用的进程中,而不是在你的应用的进程中。因此,不同于其他系统的应用,Android应用没有一个单一的入口点(这里没有main()方法)。

    因为系统在各自的进程中运行应用,它(进程)能限制其他应用访问文件,你的应用不能直接激活其他应用的组件。然后,Android系统可以。因此,为了激活其他应用中的组件,你必须指定你的意图(Intent)传递一个消息给系统来启动特定的组件。然后系统为你激活组件。

三、激活组件

三个组件——activityservicebroadcast receiver用一个称为Intent的异步消息激活。Intent(意图)在运行时刻绑定个别组件到其他的组件(可以想象为送信者(messengers)需要从其他组件获取一个动作(action)),不论这个组件属于你的应用还是其他的。

Intent利用Intent对象创建,这个对象定义了一个激活特定组件或者某种类型的组件——intent可以是明晰的或者暗含的(explicit or implicit)。

对于activityserviceintent定义需完成的动作(例如,为了显示或发送某些东西)同时可能指定作用于数据的URI(组件启动可能需要的其他东西)。例如,intent可能给activity传达一个请求显示图像或者打开网页。某些情况下,你可以启动activity来接收结果,这时,activity也在Intent中返回结果(例如,你可以发起Intent让用户选择一个联系人并返回给你——返回的Intent包含一个指向已选联系人的URI)。

对于broadcast receiverintent仅仅定义广播通告(例如,表明设备电量低的broadcast只包含一个已知字符串动作“battery is low”)。

其他组件类型,content provider,不是通过Intent激活。当然,把一个ContentResolver的请求作为目标时激活。内容解析者(content resolver)处理所有直接与ContentProvider交易,因此组件不需要与provider完成交易只要在ContentResolver对象中调用方法即可。这在Content Provider和请求信息的组件之间留下一个抽象层(为了安全性)。

这里是激活各自组件的方法:

l  你可以通过Intent传递startActivity()startActivityForResult()(当你需要activity返回一个结果)来启动activity(或者让他做一些新的事物)。

l  你可以通过Intent传递startService()来启动service(或者给正在运行的service新的指令)。或者可以通过Intent传递bindService()来绑定service

l  你可以通过Intent传递类似sendBroadcast(), sendOrderedBroadcast(), sendStickyBroadcast()方法来发送broadcast

l  你可以通过在ContentResolver.调用query()来完成对content provider的查询。