Android官方开发指南翻译(2)-应用程序基本原理

 

应用程序基本原理

Android应用程序是由java编写的。Android SDK工具将代码连同所有数据和资源文件编译到个Android包中,一个.apk后缀名的档案文件。在一个.apk文件中的所有代码被认为是一个应用程序和用来安装应用程序的Android功能设备文件。

每个应用程序一旦安装到一个设备中,它将处于自己的安全机制中:

·Android操作系统是一个多用户的Linux系统,运行在其中的每个应用程序都是一个不同的用户。

·系统会默认给每个应用程序分配一个唯一的Linux用户ID(这个ID只被系统使用而且应用程序并不知道)。系统给所有的文件设置了权限,所以只有被分配了权限的应用程序才能访问他们。

·每个进程都有自己的虚拟机,所以一个应用程序是独立于其他应用程序运行的。

·每个应用程序都默认运行在自己的Linux进程中。Android会启动进程当任一应用程序的组件需要被执行时,然后关闭进程在当它不再需要时或者当系统必须为其他应用程序恢复内存时。

Android系统实现了最小特权原则。因此每个应用程序默认只能访问自己需要工作的组件。这样就创建了安全的环境,一个应用程序不能访问没有被授权的系统部分。

尽管如此,一个应用程序还是可以通过多种方法和其他程序共享数据以及访问系统设备的:

·可以安排两个应用程序共享相同的Linux用户ID,这样它们就可以访问彼此的文件。

·一个应用程序可以申请访问设备数据的权限,例如用户的练习簿,SMS信息、可安装的存储设备(SD卡)、摄像头、蓝牙等等。所有的应用程序务必在安装时被授权。

以上包含关于一个Android应用程序如何存在于系统中的基本要素。其余的文件将介绍如下内容:

·定义应用程序的核心框架组件

·用来声明应用程序的组件和所需的设备特性的清单文件。

·与应用程序代码分离的、允许应用程序通过配置文件优化自己行为的资源

应用程序组件

应用程序组件是Android应用程序的基本组成部分。系统可以通过每个作为不同入口的组件进入应用程序。不是所有组件都是真实的入口,有的需要彼此关联。但是每个都以自己的实体而存在并且扮演着特别的角色-每个都是定义应用程序全部行为的唯一组成部分。

有四个不同类型的应用程序组件。每种类型都有独特的用途和一个独特的生命周期,它定义了组件是如何被创建和销毁的。

以下就是这四种类型的组件:

活动

一个activity代表一个用户界面中的屏幕。例如,一个邮件应用程序可能有一个activity显示新邮件列表,一个activity来写邮件,另一个activity读邮件.尽管这些Activity在邮件应用程序中组合成了一个紧密的用户体验,但是它们彼此都是独立的个体。同样的,一个不同的应用程序能启动其他任意一个activity(如果邮件应用程序允许的话)。例如,一个摄像头应用程序可以在邮件应用程序中启动activity用来写给用户共享图片的新邮件。

一个activity可以被activity的子类实现,你可以在活动开发指南中学到更多相关内容。

服务

服务是一个运行在后台的组件,它用来执行一些长时间运行的操作或者一些服务于远端进程的操作。服务不提供用户界面。例如,当用户在另一个不同的应用程序时,服务可以在后台运行音乐程序,或者它可以从网络中获取数据但又不妨碍用户与一个activity的交互。另一个组件,例如一个activity,可以启动服务并且让它运行或者将它绑定并与之交互。

服务可以被服务的子类实现,你可以再服务开发指南中学到更多的相关内容。

内容提供者

内容提供者管理着一组共享的应用程序数据集合。你能将数据存储到文件系统,SQLite数据库,网络或者其它你的应用程序能够访问的持久存储装置。通过内容提供者,其它的应用程序可以查询或者修改数据(如果允许)。例如,Android系统提供了一个内容提供者管理用户的联系簿信息。同样的,任何有一定权限的应用程序都可以查询某个人在内容提供者的组成部分(例如contactsContract.Data)中的读写信息。

内容提供者也可以用来读写你的应用程序私有的非公开的数据。例如,Note Pad例子程序使用内容提供者保存笔记。

内容提供者可以被其子类实现,而且必须实现一个标准的APIs集合以便其他应用程序执行事务。通过内容提供者开发指南可以了解更过的信息。

广播接收者

广播接收者是一个响应系统级广播公告的组件。很多源于系统的广播-例如,一个广播声明显示器已经被关闭,电池电量低了,或者一个图片已经被截取。应用程序也可以创建广播-例如,为了让其它应用程序知道一些数据已经下载并且可以被它们使用了。尽管广播接收者不能提供一个用户界面,当一个广播事件发生时它们可以创建一个状态提示条提醒用户。通常,广播接收者只是一个通往其他组件的网关并且只能做一些非常小的工作。例如,它可以开启一个执行基于事件工作的服务。

广播接收者可以被其子类实现而且每个广播都是以Intent对象发送的。可以通过查看BroadcastReceiver类了解详细的信息。

Android操作系统设计的独特一面是任何应用程序都可以开启另一个应用程序的组件。例如,如果你想要用户通过摄像头去捕获图片,你完全可以使用另外的应用程序的这个功能,以此来替代开发一个这样的功能。你不需要结合或者连接摄像头应用程序的代码。相反,你可以轻松的开启摄像头应用程序去获取图片。当照相结束时,图片甚至可以返回到你的应用程序中供你使用。对于用户而言,这个照相功能实际上就是你的应用程序的一部分。

当系统开启一个组件,它会为应用程序(如果它不是已经运行的)和组件需要的实例化类开启进程。例如,如果你的应用程序开启了摄像头程序中的活动去照相,那个活动所在的进程是属于摄像头应用程序,不是属于你的应用程序进程。因此,不像应用程序在其他大部分系统中一样,Android应用程序没有一个单一的入口(例如没有main函数)

因为系统在单独的进程中运行运行每个应用程序,并且赋予了文件权限限制访问其他应用程序。你的应用程序不能直接激活另一个应用程序的组件。但是Android系统可以,所以为了激活另一个应用程序的组件,你必须发送一个消息给系统用来指定你的去开启一个特殊组件的意图。然后系统可以帮你激活组件。

激活组件

四个组件类型中的三个-活动,服务和广播接收者-都是被一个叫意图的异步消息激活的。意图在运行时中将独立的组件彼此绑定(你可以把它们当成从其他应用程序请求响应的信使),只是不知道这个组件是属于你的应用程序还是其它的。

一个意图由一个意图对象创建,它定义了一个消息去激活一个特殊的组件或者一个特殊类型的组件-一个意图可以分别是显示的或隐式的。

对于活动和服务,一个意图可以定义行为去执行(例如,显示或者发送一些东西)和可以按照指定的数据URI去执行(除了已知的开启组件之外)。例如,一个意图可能给一个活动传达要显示图片或者打开一个网页的请求。在某些情况下,你能开启一个活动去接受结果,某些时候,活动也可以返回结果到一个意图中(例如,你可以发布一个意图,让用户选择一个私人的联系方式并且将结果返回给你-这个返回意图包括指向适当联系方式的URI).

对于广播接收者,意图简单定义了将被广播的公告(例如,一个指示设备电量低的广播仅包括一个已知的响应字符串电池电量低”)

其他的组件类型,内容提供者不是又意图激活的。相反,它是当一个分析器的请求被指定时激活的。这个解析器处理所有直接和内容提供者相关的事务,所以执行事务的组件并不需要做,而是从内容解析器对象中请求方法。这样就在内容提供者和组件中间存在一个请求信息的虚拟层(出于安全的考虑)

有一些用于激活每种组件类型的方法:

·你可以绕开意图使用startActivity() 或者 startActivityForResult()方法(当你想要这个活动返回一个结果时)去开启一个活动(或者给它一些新的东西去做)

·你可以绕开意图使用startService()开启一个服务或者你可以通过bindservice()绑定服务。

·你可以绕开意图使用诸如sendBroadcast(), sendOrderedBroadcast()或者 sendStickyBroadcast()这样的方法去发起一个广播。

·你可以在内容解析器中调用query()方法为内容提供者执行一次查询。

想要了解更多关于如何使用意图的信息,可以查看意图和意图过滤器文档。关于激活特殊组件的更多信息可以在以下文档中获取:活动,服务,广播接收者和内容提供者。

清单文件

Android系统开启一个应用程序的组件之前,系统必须通过读取应用程序AndroidManifest.xml文件(清单文件)知道这个组件是否存在。你的应用程序必须在清单文件中定义它的所有组件,这个文件必须在应用程序的根目录下。

这个清单文件除了声明应用程序组件外,还有很多其他的作用,例如:

·识别用户的权限,例如网络访问权限或者用户联系薄的访问权限。

·声明应用程序所需的最低API版本,基于哪个版本的APIs.

·声明应用程序使用或者需要的软硬件特征,例如一个摄像头,蓝牙设备或者一个多点触控的屏幕。

·应用程序需要去联系的API程序库(除了Android框架APIs),例如google地图程序库。

·还有很多其他的

声明组件

清单文件的最主要的作用就是通知系统应用程序有哪些组件,例如,一个清单文件能定义一个如下的活动:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
   
<application android:icon="@drawable/app_icon.png" ... >
       
<activity android:name="com.example.project.ExampleActivity"
                 
android:label="@string/example_label" ... >
       
</activity>
        ...
   
</application>
</manifest>

<application>元素中,android:icon属性执行一个应用程序识别的图标资源。

<activity>元素中,android:name属性指定了标准activity子类的名称,androidlabel属性为activity指定了一个用户可视化标签使用的字符串。

你必须这样定义所有的应用程序组件:

·<activity>活动的元素

·<service>服务的元素

·<receiver>广播接收者的元素

·<provider>内容提供者的元素

包含在你的源码中的活动,服务,内容提供者,如果不在清单中声明,系统永远不会识别和运行它们。但是广播接收者却可以既在清单中声明也可以在代码中动态创建(一个BroadcastReceiver对象),并且调用registerReceiver()方法在系统中注册。

想了解更多关于怎样去结构化应用程序的清单文件,可以看AndroidManifest.xml文档。

声明组件的功能

正如我们上面讨论的关于激活组件,你可以使用一个意图去开启活动,服务和广播接收者。你可以这么着通过显示的在意图中命名目标组件(使用组件类名)。但是意图真正作用于意图行为的概念。对于意图行为,你可以简单的描述你要执行的行为类型(任意的,在你想要执行的行为上的数据),你也可以允许系统去寻找一个可以执行行为的组件并且开启它。如果有多重组件可以执行意图描述的行为,然后用户可以选择一个。

系统识别可以响应一个意图的组件的方法,这个意图是通过比较其他应用组件的清单文件提供的意图过滤器接受到的。

当你在你的应用程序清单中声明一个组件时,你可以选择性的加入可以定义组件功能的意图过滤器,以致它可以对从其它组件的意图进行响应。你可以为组件声明一个意图过滤器通过增加一个<intent-filter>元素作为组件声明元素的子元素。

例如,一个携带组合新邮件活动的邮件应用程序可以在它的清单中声明一个意图过滤器。从而去响应”send”意图(为了去发送邮件)。在你应用程序的一个活动可以为“send”行为创建一个意图(ACTION_SEND),这个意图可以与邮件应用程序的”send”活动并且发送它当你通过startActivity()方法触发意图时。

想了解更多关于创建意图过滤器的内容,可以查看意图和意图过滤器文件。

声明应用程序的需求

支持Android系统的设备有很多种,但并不是所有的都提供相同的特性和功能。为了防止你的应用程序要安装在的设备缺少必要的特性,清楚地定义一个关于你的应用程序相关支持的概括就变得很重要了,通过在你的清单文件中声明设备和软件的需求。大多数这些声明都只是信息性的,系统并不会读取它们,但是外部的服务(例如Android市场)会读取它们,为用户在搜索应用程序时提供过滤条件。

例如,如果你的应用程序需要一个摄像头和使用Android2.1API版本7)的APIs,你应该在你的清单文件中定义这些需求。这样,那些没有摄像头和Android版本低于2.1的设备就不能安装你Android市场上的应用程序。

尽管如此,你也可以定义你的应用程序可以使用摄像头,但是不是必须的。这样,你的应用程序就必须在运行时执行检查,从而判断设备是否装有摄像头,并且在没有摄像头的情况下无效相关的功能特性。

在你设计和开发应用程序时,你应该考虑一些重要的设备特性:

屏幕的大小和密度

为了通过屏幕的类型来对设备分类,Android为每个设备定义了两个特性:屏幕大小(屏幕的实际尺寸)和屏幕的密度(屏幕的物理像素密度,或者dpi-每英寸点数)。为了简化所有不同类型屏幕的配置,Android系统将它们概括成了可供选择的组从而更方便指定。

屏幕的大小事:小,中,大和特大

屏幕的密度是:低密度,中等密度,高密度和特高密度

一般情况下你的应用程序是可以适应所有屏幕的大小和密度的,因为Android系统为你的UI布局和图片资源做了适当的调整。尽管如此,你还是应该为确定的屏幕大小创建合理的布局,还要为确定的密度提供合理的图片,使用可以有可替换的布局资源和在你的清单文件中使用<supports-screens>元素明确定义你的应用程序所支持的屏幕大小。

想了解更多的信息,请查看支持多种屏幕文档。

输入配置

许多设备提供了不同类型的用户输入机制,例如一个硬件键盘,一个轨迹球或者一个5道导航台。如果你的应用程序需要一个特殊的输入硬件,那么你应该在你的清单文件中使用<uses-configuration>元素定义它。但是很少有一个应用程序需要一个特定输入配置的情况。

设备特性

有很多硬件和软件特性可能或者不可能存在一个给定的Android设备中,例如一个摄像头,一个光感器,蓝牙,一个特定的OpenGL版本或者高保真的触摸屏。你应该从未假设可以在所有的Android设备中获得某一个特性(除了标准Android程序库之外),所以你应该使用<uses-feature>元素定义你的应用程序所需的任一特性。

平台版本

不同的Android设备常常运行在不同版本的Android平台上,例如Android1.6或者Android2.3.每个后续的版本常常包含以下以前版本并不支持的额外的APIs.为了指示可以得到哪些APIs,每个平台版本都指定了一个API级别(例如Android1.0API级别1Android2.3API级别9)。如果你使用的任一APIs都已经加入到了1.0版本之后的平台中,你应该使用<uses-sdk>元素定义那些APIs所在的最低API级别。

你为应用程序定义所有的需求是很重要的,因为当你把应用程序发布到Android市场时,市场会使用这些定义去过滤哪个应用程序可以被每个设备使用。同样的,你的应用程序只能在符合你的应用程序所有需求的设备上使用。

想了解更多关于Android市场是如何基于这些(其他)需求去过滤应用程序的信息,请查看市场过滤器文档。

应用程序资源

一个Android应用程序不仅仅只是由代码组成-它还需要独立于源代码的资源。例如图片,音频文件和任何应用程序的可视化相关的东西。例如你应该定义动画,菜单,样式,颜色和活动用户界面XML文件的布局。使用应用程序资源使它能简单的在不修改代码的情况下更新你应用程序各种各样的特性-通过提供可替换的资源集合-使你能够通过各种设备配置来最优化你的应用程序(例如不同的语言和屏幕的大小)

在你的应用程序中包含的每个资源,SDK编译工具都会定义一个唯一的整形ID,你可以在应用程序中通过这个引用来使用资源或者从其他定义在XML中的资源。例如,如果你的应用程序包括一个叫logo.png的图片(保存在res/drawable目录下)SDK工具形成了一个叫R.drawable.logo的资源ID,你可以通过它来引用这个图片并且将它插入到你的用户界面中。

提供独立于源代码的资源的最重要方面是你能拥有能为不同设备配置提供可替换资源的能力。例如,通过在XML中定义UI字符串,你可以将字符串转换成其他语言并且保存在一个独立的文件中。然后基于你添加到资源目录名的语言限定符(例如法语字符串值res/values-fr/)和用户的语言设定,Android系统将在你的UI中应用适当的语言字符串。

Android支持多种不同的限定符供你的可替换资源使用。限定符是一个短字符串,它包含在你的资源目录名里,为了定义那些应该被使用到的设备配置。又如另一个理智,你应该常常创建不同活动布局,依赖于设备的屏幕定位和大小。例如,当设备的屏幕是在竖向方向(),你可能想要一个垂直的按钮布局,但是当屏幕是在横向方向(宽),按钮就应该水平对齐。为了使布局随着定位而改变,你可以定义两个不同的布局并且将适当的限定符应用到每个布,局目录名中。这样,系统就会自动根据现有的设备定位来应用适当的布局。

想了解更多包含在应用程序中的不同资源类型和怎样为各种设备配置创建可替换的资源。请查看应用程序资源开发指南。

 

原文地址:http://developer.android.com/guide/topics/fundamentals.html

posted @ 2012-02-19 00:48  到最后  阅读(1069)  评论(1编辑  收藏  举报