Android帮助文档翻译——开发指南(一)应用程序基本原理

来源:互联网 发布:梦里花落知多少诗 编辑:程序博客网 时间:2024/06/05 00:15
转自:http://blog.csdn.net/sam_zhang1984

交流可加新浪微博:Android开发人

 

Android应用程序是由JAVA编写的。AndroidSDK工具把编写好的应用程序代码连同一些数据和资源编译成一个.apk后缀的Android应用程序包。包含在同一个apk文件里面的所有代码就当成是一个应用程序安装包,并可以在Android设备上进行安装。

安装在Android设备上的每一个应用程序都运行于自己的安全砂箱中:

Android操作系统是一个多用户Linux系统,每一个应用程序就相当于一个不同的用户;

默认情况下,系统会为每一个应用程序分配一个只对系统可见而对程序不可见的Linux用户ID。系统为每一个应用程序包含的所有文件设置权限,以便通过分配给某应用程序的系统用户ID来访问该程序的这些文件;

每一个进程运行在自己的虚拟机上,这样使每一个应用程序都是独立运行;

默认情况下,每一个应用程序运行在自己的Linux进程中。当应用程序的组件需要被执行时,Android系统会开启一个进程,当进程不再需要运行或系统必须为其它应用程序提供内存空间时,Android会关闭这个线程;

这样的话,Android系统实现了最小特权原则。就是说每一个应用程序在默认情况下只能访问用来完成其工作的自身组件。这就创建了一个应用程序在没有得到授权时无法访问系统其它部分的安全环境。

虽然如此,但应用程序还是有一些途径与其它程序共享数据,或访问系统的服务。

可以让两个应用程序共用一个Linux用户ID,在这种情况下,他们就可以相互访问彼此的文件。为了节省系统资源,两个有共同用户ID的应用程序同样能运行在同一个Linux进程中,并共用一个虚拟机,当然这两个应用程序必须用同一个证书注册

每一个应用程序能够请求访问设备数据的权限,如用户联系人、短信息、可安装存储(如SD卡)、摄像头、蓝牙等等。所有的这些应用程序权限必须由用户在初始化时进行授权。

这里覆盖了关于一个应用怎么存在于系统中的一些基础知识,接下来在这个文档各个章节中将为你介绍以下内容:

1、     在你的应用程序中使用的核心框架组件;

2、     你用来定义组件和应用程序所需设备环境的manifest文件;

3、     资源与代码分离,并允许完全优化针对各种不同配置设备的行为属性(如:针对不同屏幕分辨率@Sam注)。

 

应用程序组件

应用程序组件是一个Android应用程序必不可少的一部分。每一个组件都是系统能与你的应用程序进行交互的不同点。并不是所有组件都是对直接面向用户的实体,有一些组件依赖于其它组件而存在,但对于每一个组件来说,它都是以作为一个独自的存在实体,并扮演着特定的角色,也就是说,每一个组件都是来定义你的应用程序外部行为的特定组成部分。

Android里有四大应用程序组件,每一种类型的组件有不同的作用,并拥有不同的生命周期(生命周期即组件从创建到销毁的整个过程)

下面就是这四种应用程序组件的介绍:

 

Activity

Activity就是一个带有用户接口的界面。比如,一个Email应用程序应该包括一个用来显示邮件列表的Activity、一个用来写邮件的Activity和一个用来读邮件的Activity。虽然这些Activity共同组成了一个Emailt程序的用户体验,但他们彼此之间却是互相独立地存在。因此,只要Email应用程序授权的情况下,其它应用程序可以启动这些Activity的任何一个。比如一个照相程序可以通过启动一个Email程序中新建邮件的Activity来分享照片。

每一个activity界面都是继承了Activity类,你可以在开发指南中学习更多关于Activity的知识。

 

Services(服务)

服务是一个运行在后台的组件,它不提供一些用户接口界面,一般是用于执行相对费时的操作或运行一些远程进程。比如当用户在使用其它应用时,用一个服务在后台播放音乐或在后台获取网络数据而阻塞影响用户的其它操作。其它一些组件(如activity)可以启动一个服务运行在后台或绑定一个服务来与之进行交互。

每一个服务是继承了Service类,你可以在开发指南中学习更多关于服务的知识。

 

Contentproviders(内容提供器)

内容提供器是用来处理应用程序的一些共享数据。你可以利用系统文件、SQLite数据库、web或一些永久存储设备(如SD卡,@Sam注)来存储数据,以便你的应用程序可以访问使用。其它应用程序可以通过你的应用程序提供的内容提供器(Content provider)查询或甚至修改这些数据(前提是你允许其它程序修改)。比如,Android系统提供了一个管理用户联系人信息的内容提供器(Content provider),因此,其它应用程序只要取得了相应的权限就可以取得诸如de>ContactsContract.Datade>de>这样的内容提供器内容(de>Contentproviderde>),这样就可以查看或编辑联系人信息了。de>

de>在读取或修改你的应用程序中不共享的私有数据时,内容提供器(de>Content providerde>)也是非常有用的,例如记事本程序就是提供一个内容提供器来实现存储内容的。de>

de>内容提供器(de>Contentproviderde>)必须继承ContentProviderde>,并实现一些执行数据交互的应用程序接口。

 

Broadcastreceivers(广播接收器)

广播接收器是一个用来响应系统全局广播事件的组件。大部分的广播都是由系统产生的,比如屏幕关闭、电量低、选中了一张图片。应用程序也可以自己初定义一个广播,比如通知其它应用程序数据已经下载到了设备上,它们可以使用这些数据了。虽然广播接收器不能显示一个用户接口界面,但它可以在接收到广播时,创建一个状态栏通知信息通知用户。尽管如此,更普通的情况下,广播接收器只是一个与其它应用程序对接的出口,并仅仅是做一些很轻量级的操作(广播接收器不能进行费时的重量级操作 @Sam注)。比如,一个广播接收器在接收到某一个广播后启动一个服务去执行其它一些操作(一般是一些相对重量级的费时操作@Sam注)。

一个广播接收器需要继承de>BroadcastReceiverde>de>de>而且每一个广播都是以Intent对象的形式来进行传递。

 

Android系统的一个独特设计就是任何应用程序可以启动其它程序的组件,比如,当你想通过设备的摄像头获取一张照片,通常情况下利用其它有照相功能的应用程序去获取,然后你直接使用得到的这张照片数据就行,而不需要自己去开发一个具有照相功能的程序。要实现这样的功能,你也不需要去包含进照相程序的代码或去连接这个照相程序,你只需在代码中简单地打开一个照相程序的activity界面,然后直接使用现有照相程序进行照相,最后把照片返回供你的应用程序使用。在用户看来,这个照相程序就好像你的应用程序的一部分,实际他们是相互独立的两个程序。

当系统启动一个组件时,如果应用程序还没运行,系统会启动一个包含应用程序和组件所需要的类实例进程。比如,当你的应用程序要启动一个照相程序来获取相片,那么系统将启动一个属于照相程序的线程,而不是你的应用程序进程中打开照相程序。因此,Android应用程序并不像其它大多数系统应用程序一样,它没有一个单独的程序入口(比如并不像其它系统应用程序一样有main()函数这样一个入口)。

因为Android系统中每一个应用程序都是独立运行在自己的进程中,并且有访问其它应用程序的文件权限约束,所以你的应用程序不能直接激活另一个应用程序的组件,只有Android系统可以激活。因此,如果需要激活其它程序的组件,你必须向系统发送一个包含你要打开的这个组件信息的意图(Intent),并由系统为你打开这个组件。

 

激活组件

activities、服务(services)、广播接收器(broadcast receivers)这三大组件都可以通过一个叫意图(Intent)的异步信息来激活。意图(Intent)在运行时为某一个特定的组件绑定了一个其它组件(你可以理解成一个用来请求其它组件动作的消息),这个组件可是属于你的应用程序,也可以不属于你的应用程序(比如上面例子中的照相程序就不属于你的应用程序 @Sam注)。

一个意图(Intent)就是一个Intent对象,它定义了一个需要激活某个组件或某种类型的组件的消息,这个意图(Intent)可以是显式匹配、隐式匹配或respectively

对于activitiesservices,一个意图(Intent)定义了需要执行的动作(如“"view" "send"),也可能指定了启动组件需要的数据URI。比如,可以通过一个意图(Intent)去请求一个activity显示一张图片或打开一个网页。在某些情况下,你可以通过一个意图(Intent)去启动一个activity,并接收这个activity返回的包含了结果数据的Intent。比如,你可以发送一个意图(Intent)打开一个联系人列表界面,让用户选择联系人,并接收一个包含了指向用户选中的联系人URI的意图(Intent)。

对于广播接收器,意图(Intent)就只是简单地定义了当前广播的内容,比如,一个表示设备电量低的广播,只需要包括一个已经定义过的可知字符串去表示电量低这个事件就行了。

四大组件的另一个组件——内容提供器(content provider)是不能通过意图来激活的。更确切地说,当有一个来自de>ContentResolverde>的请求指向它时,它才会被激活。由于内容分解器(contentresolver)通过内容提供器(contentprovider)直接处理事务,所以组件不需要直接调用内容提供器(content provider)来处理事务,而只需要调用de>ContentResolverde>对象的方法就可以了。这就为内容提供器(content provider)和组件请求数据之间加入了一个抽离层,这样子做使得程序更为安全(即组件不直接与内容提供器打交道,而是通过de>ContentResolverde>对象来进行操作 @Sam注)。

下面是激活每一种组件的方法:

1、     激活activity:通过传递一个意图(Intent)给de>startActivity()de> de>startActivityForResult()de>方法,后者是当需要activity有数据返回时调用;

2、     激活服务(service)或向一个运行中的服务(service)传递指令:通过传递一个意图(Intent)给de>startService()de>,也可以通过传递一个意图(Intent)给de>bindService()de>de>de>绑定一个服务;

3、     可以通过传递一个意图(Intent)给de>sendBroadcast()de> de>sendOrderedBroadcast()de>de>sendStickyBroadcast()de>来初始化一个广播;

你可以通过调用de>ContentResolverde>类的de>query()de>方法来执行一个内容提供器的查询动作。

 

Manifest文件

Android系统启动应用程序组件前,系统必须通过读取应用程序的AndroidManifest.xml文件(即manifest文件)来明确有哪些组件存在应用程序中。应用程序必须在其工程根目录下创建这样一个包含了所有组件定义的manifest文件。

这个manifest文件定义了各种关于应用程序组件定义的数据,比如:

1、       定义应用程序需要的用户权限,比如访问网络、访问用户联系人;

2、       定义应用程序至少需要的API级别(Level,这个取决于你的应用程序使用的API版本(在Eclipse实际操作中,在创建工程时选择的API版本后面就有这个参数,是一个数字  @Sam注);

3、       定义应用程序需要的软硬件环境,如需要摄像头、蓝牙或多点触控;

4、       应用程序需要连接除了Android框架APIs外的API库,比如GoogleMaps library(这个库虽然也是Google的,但并没有在标准APIs中,所以当使用时,则需要显式连接这个库进来 @Sam注);

5、       还有更多……

 

定义组件

Manifest的首要任务就是让系统知道当前应用程序的组件信息。例如,可以像下面一样在manifest文件中定义一个activity

 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest ... >  
  3.     <application android:icon="@drawable/app_icon.png" ... >  
  4.         <activity android:name="com.example.project.ExampleActivity"  
  5.                   android:label="@string/example_label" ... >  
  6.         </activity>  
  7.         ...  
  8.     </application>  
  9. </manifest>  
 

<application>标签中的android:icon属性是用来为应用程序指定图标资源(即应用程序的图标 @Sam注)。

<activity>标签中的android:name属性指定了一个完整修饰的类名,这个类是Activity的子类;android:label属性则是指定一个字符串作为对于用户可见activity标签。

你必须按照以下方法来定义应用程序的组件:

1、       <activity>标签来定义activities

2、       <service>标签来定义服务(services

3、       <receiver>标签来定义广播接收器(broadcast receivers

4、       <provider>标签来定义内容提供器(content providers

如果有一些activities、服务(services)和内容提供器(content providers)包含在你的应用程序源文件中的,但没有在manifest文件中定义,那么这些组件对于系统来说将是不可见,当然它们也永远不会运行。不同的是,广播接收器(broadcast receivers)即可以在manifest文件中定义,也可以代码中作为一个BroadcastReceiver对象动态创建,并通过调用registerReceiver()方法在系统中注册这个广播接收器。

更多关于如何组织manifest文件的介绍,可以参考TheAndroidManifest.xml File文档。

 

定义组件的性能

正如在“激活组件”一节中所说的,你可以通过传递一个意图(Intent)去启动activities、服务(services)和广播接收器(broadcast receivers)。你可以在意图(Intent)中通过组件的类名显式地指定目标组件。然而,意图(Intent)的真正强大之处是在于意图中有动作(action)的概念。利用意图(Intent)的这个动作(action),你只需简单地描述你需要进行操作的动作(action)类型(如果有需要时也可以给这个动作带上必要的数据),然后让系统去匹配一个具有执行这个动作能力的组件并运行这个组件。如果匹配到多个组件具备执行这个动作的能力,那么就通过弹出选择框的方式让用户自己去选择用哪一个组件去执行(如在在手机上有多个浏览器,在打开网址前,系统会打开一个选择界面,让你选择用哪一个浏览器去打开 @Sam注)。

系统确定哪一个组件能够对某一个意图(Intent)进行响应的方法是:系统通过比对收到的意图(Intent)和设备上其它应用程序在manifest文件中提供意图过滤器(ntent filters),如果相匹配则调用这个应用程序对收到的意图(Intent)进行响应。

当你在应用程序的manifest中定义一个组件时,在有需要的情况下,你可以选择为你的组件定义一个描述意图能力的意图过滤器,这样它就能够响应其它应用程序的意图(Intent)。定义意图过滤的方法是:在控件标签下增加一个<intent-filter>子标签进行定义。

比如,一个包含了可以编辑新邮件activityEmail程序,可以在它的manifest入口中定义一个意图过滤器来响应“send”意图(它的意思是发送电子邮件)。这样的话,你就可以在你的应用程序中创建一个包含“send”动作的意图(即ACTION_SEND),然后当通过调用startActivity()方法传递出这个意图时,系统就会去匹配并运行之前的那个Email程序。

 

定义应用程序对配置的要求

目前支持Android的设备有很多,但这些设备千差万别,并没有统一的性能。为了防止你的应用程序装到了一台无法提供程序所需性能,所以在manifest文件中明确定义你的程序运行所需的软硬件环境是非常有必要的。通常这些定义只仅仅是一些信息性的描述,而且系统是不会去读取它们的。然而当用户在搜索一些针对他们设备的应用程序时,像Android市场这些外部服务会利用这些信息性描述生成一个过滤器去确定程序与用户设备是否匹配。

例如,你在manifest文件中定义了你的应用程序需要摄像头并且使用了Android2.1APIAPI Level 7),那些没有摄像头或系统版本低于Android2.1的设备将无法从Android市场上下载安装你的应用程序。

尽管如此,你也可以定义你的应用程序使用了摄像头,但不是必需的。在这种情况下,你就必须在你程序运行时去判断设备是否有摄像头,并在摄像头不可以情况下屏蔽一些使用了摄像头的属性

以下是一些在设计开发程序时需要考虑的设备重要属性:

1、     屏幕尺寸和密度

为了通过屏幕来区分设备,Android为每一个设备定义了两个属性:一个是屏幕尺寸,即屏幕的物理尺寸(也即我们平常说的3.5寸、4.3寸等等,@Sam注);另一个是屏幕密度,即屏幕像素的物理密度,或称为dpi(每英寸上的像素点数)。为了简化不同屏幕配置类型的区分,Android系统把他们归纳成不同的选择组,这样就可以地去确定屏幕配置类型。

屏幕尺寸分为小、正常、大和超大四种。

屏幕密度分成低密度、中密度、高密度和超高密度四种。

默认情况下,由于Android系统为你的UI布局和图片资源提供了一个合适的校准,因此你的应用程序可以兼容所有的屏幕尺寸和密度。当然你可以用可选布局资源并在你的manifest中用<supports-screens>标签明确指定你的应用程序所支持的屏幕尺寸,来创建针对某些屏幕的专门布局和提供针对某些密度的专门图片。

2、     输入配置

大部分机器提供了不同的用户输入设备,比如键盘、轨迹球和五维按键。如果你的应用程序需要特定的输入设备,那你就需要在manifest中用<uses-configuration>标签指定你所需的输入设备,然而很少有这种需要某种特定输入设备的应用程序。

3、     设备属性

在一个Android驱动的设备中,可能存在很多的软硬件属性,比如摄像头、光感、蓝牙、专门版本的OpenGL或触摸屏的精确度等等。你永远不要假设在Android驱动设备中的某一个属性是有效的(除了Android标准库外),所以你需要在manifest中用de><uses-feature>de>标签显式指定你的应用程序所需的设备属性。

4、     平台版本

不同的Android设备经常使用不同版本Android平台,如有些使用Android 1.6,有些使用Android 2.3。对于每一个后续版本经常是新增了一些前期版本没有的API,因此,为了更明确API的可用性,每一个平台版本都指定了API的级别(Level),如Android 1.0 API Level 1,而Android 2.3API Level 9。如果你使用了1.0版本后API,你就必须利用<uses-sdk>标签定义你所用API的至少API级别。

因为你在Android市场发布应用程序后,电子市场需要利用程序里定义的硬件件环境需求去匹配想使用该程序的设备,所以在程序中定义你的应用程序所需的所有配置环境就显得尤为重要。同样的,你的应用程序也只能在符合其配置需求的设备上运行。

 

应用程序资源

一个Android应用程序远远不只是由代码组成那么简单,它还包括了一些抽离于源代码的必要资源,如图片、声音文件或其它一些与应用程序相关的可视化界面。例如,你可以用XML文件定义一些动画、菜单、样式、颜色和用户交互界面的布局等。使用应用程序资源,你可以通过提供一些替代资源alternative resources)就可以简便地更新应用程序的各种属性,使得你可以针对不同配置的设备进行相应的优化,如针对不同语言、不同屏幕尺寸的设备。

对于你的Android程序中每一个资源,SDK开发工具会自动为它定义一个唯一的ID,通过这个ID你可以在程序代码中或用XML定义的其它资源文件中关联该ID对应的资源。例如,你的应用程序中包含了一张叫logo.png的图片(它会被保存到res/drawable/路径下),那么SDK开发工具就会自动生成一个名为R.drawable.logoID,这样你就可以用这个ID来关联包含进来的图片,然后插入到你的用户交互界面中(UI)。

可用资源文件最重要的作用之一,就是把资源和代码抽离,这样你就可以方便地为不同设备配置提供不同的替代资源。例如,在XML文件中定义用户交互界面(UI)中用到的字符串,你就可以把这些字符串翻译成其它语言,并保存在一个抽离的文件中。系统将会根据你在资源路径中插入的语言修饰符(如保存成res/values-fr/即表示这个文件中的字符串表示法文)和用户机器中语言的设置为程序选择一个合适的用户界面变语言。

Android系统支持很多不同的替代资源修饰符,这个修饰符其实就是一些包含在资源路径中的字符串。通过这个修饰符可以让设备根据不同配置使用不同的资源。另一个例子就是你的程序可能需要根据设备屏幕方向和尺寸的不同使用不同的布局,比如当设备是纵向的你可能需要一个按钮是纵向的布局,当屏幕是横屏时按钮需要是水平对齐,这时你就可以定义两个不同的布局文件,并为它们分别添加合适的修饰,这样系统就会自动根据设备当前的方向选择合适的布局。

阅读全文
0 0
原创粉丝点击