[置顶] Android API Guides – Application Fundamentals

应用基础

 

声明:

本文由Gordon翻译

发布于www.dlvoice.com

欢迎转载,但请保留此声明

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

         Android应用是用Java语言来开发的。Android的SDK工具将会把你的代码和数据以及资源文件编译到APK中,所谓的APK就是一个Android包,它是以.apk结尾的压缩包文件。APK文件包含了Android应用的所有部分,一个真正的Android设备也是使用这个文件进行安装应用的。

一旦Android应用安装到设备中,它就会运行于它自己的安全区域:

  • Android系统是一个多用户的Linux系统,每一个应用都是一个不同的使用者。
  • 系统将默认给每一个应用一个独一无二的用户ID(这个ID仅仅由系统和应用之间使用),系统将会设置应用的所有文件的权限,这样就只有这个应用可以访问这些文件。
  • 每个进程都有它自己的虚拟机(VM),所以应用的代码和别的应用是互不相干的。
  • 每个应用默认都是运行在它自己的Linux进程中,当应用的任何一个部分需要执行时,Android就启动这个进程,当这个部分不再运行或者别的应用需要系统恢复内存的时候就会停止这个进程。

这样一来,其实Android系统遵循的是“最小权限”原则。也就是说,默认来说一个应用只能够访问它需求部分,别的部分都不允许访问。这样应用就会运行在一个非常安全的环境,它不能访问系统未给予其访问权限的部分。

当然,也有一些方式让应用来和别的应用分享数据以及访问一些系统的服务:

  • 可以让两个应用共享使用一个Linux用户ID,这样它们就可以互相访问对方的文件。为了保护系统资源,具有同样用户ID的应用也能够在同一个Linux进程上运行并使用同样的VM(这两个应用需要使用同样的证书进行签名)。
  • 应用可以请求访问一些设备数据的权限,比如用户的联系人,SMS信息,挂载的存储器(SD卡),相机,蓝牙等等。所有的这些应用权限都必须是在用户安装的时候授权。

上面所讲的基本上就是应用如何在系统中存在的,本文接下来的部分将会向你介绍下面几个部分:

  • 定义你应用的核心组件。
  • 应用用来声明组件和设备性能需求的Manifest文件。
  • 用来适配不同设备配置的资源文件。

 

应用组件

应用组件是Android应用的基本组成部分,每一个组件都是系统进入你应用的不同途径。虽然不是所有的组件都是用户的真实的入口点,但是每一个存在的实体都有它自己的特殊作用——在应用中有其不可取代的作用。

有四种不同类型的应用组件,每一种类型的组件都有其独特的作用以及生命周期。

组件的四种类型详细介绍如下:

Activities

Activity描述了用户看到的一个单独的屏幕。比如,一个email的应用使用一个activity来显示新邮件的列表,另外一个activity来创建邮件以及一个activity来读取邮件。尽管email应用使用了这些activity来实现不同的功能,但是他们之间是独立的。因此,别的应用是可以单独启动他们中的任何一个activity(前提是email应用允许它这样做)。比如,一个拍照相关的应用可以启动email应用中的新邮件来分享照片。

Activity是由Activity子类来实现的,更多的资讯可以参考Activity开发手册。

Services

Service组件用来在后台执行长时间运行的操作或者执行远端进程的工作,service不提供用户接口。比如,一个service可能会在用户使用一个应用的时候在后台播放音乐,或者在后台获取网络数据。别的组件,比如activity可以启动service或者绑定service。

Service是由Service子类来实现的,更多的资讯可以参考Service开发手册。

Content providers

Content provider管理应用数据的分享。你可以把数据保存在文件系统,SQLite数据库,网络或者别的你的应用可以访问的存储区域。通过Content provider,别的应用可以查询甚至修改这些数据(前提是content provider运行这样做)。例如,Android系统提供了一个content provider管理用户的联系人信息。这样,任何具有一定权限的应用都可以查询这个content provider(比如ContactsContract.Data)并进行某个特定用户的信息的读写。

Content provider在对应用的私有数据的读写也是有用的。例如,Note Pad应用中用content provider进行notes的保存。

Content provider是由ContentProvider子类来实现,并且需要实现一系列标准的API来让别的应用来实施传递。更多的资讯可以参考Content Provider开发手册。

Broadcast receivers

Broadcast receiver组件是用来对系统广播进行响应的。许多广播起源于系统——比如,一个广播表示屏幕已经关闭,电池电量低或者一个图片被捕获。当然应用也能够初始化广播——比如让别的应用知道一些数据已经下载到设备并且能够被用户使用。尽管broadcast receiver并不显示给用户,他有可能创建一个状态栏的通知,这样用户就知道一个广播事件发生了。更多的时候broadcast receiver只是一个到别的组件的“通道”,并且只做很少的工作。比如,它可能初始化一个service去做一些基于这个事件的事情。

Broadcast receiver是由BroadcastReceiver子类来实现并且每一个broadcast都是由Intent来进行传递的。更多的资讯可以参考BroadcastReceiver类。

一个应用可以启动另外一个应用的组件是Android系统独有的部分。比如,你想让用户通过设备的相机来拍照,假如这时有另外一个应用做了同样的事情,你就可以直接拿过来用而不用自己去开发一个activity来实现。你不需要合并或者链接相机应用的代码,只需要简单启动相机应用来拍照即可。当拍照结束之后,这个照片会返回到你的应用,这样你就可以使用它了。对用户来说,看起来拍照也是你应用的一部分。

当系统启动一个组件的时候,它会启动这个应用的进程(假如它还没有运行)并且初始化这个组件需要的类。举例来说,假如你的应用启动了相机应用的拍照activity,这个activity将会在相机应用的进程中运行而不是你的应用进程。因此,和别的大多数系统不同的是,Android的应用并没有一个单独的入口点(比如说函数没有main())。

因为系统在独立的进程中运行每一个应用,所以你的应用不能够直接激活另外一个应用的组件。但是,Android系统是可以的。所以,假如你的应用想要激活另外一个应用的组件,你需要先发送一个信息到系统,然后系统来利用你的intent启动特定的组件。

激活组件

四大组件中的三个——activities,services和broadcast receivers——都是通过调用一个称之为intent的异步信息来启动的。Intent可以把独立的组件在运行时相互绑定,不过这些组件是否属于你的应用还是属于别的应用。

Intent是由Intent对象来创建,它定义了一个信息来启动一个特殊的组件或者一个特殊的组件类型——intent可以是明确的或者不明确的。

对activities和services来说,intent定义了执行和指定数据URI的操作。例如,一个intent可能传输给一个activity显示一个图片或者打开网页的请求。有时,你可以启动一个activity去接收结果,这种情况下,这个activity也将会通过Intent来返回结果。(例如,你可以产生一个intent让用户选择一个联系人信息并且把这个信息返回给你——这个返回的Intent就会包括指向用户选择的联系人信息的URI)。

对broadcast receiver,intent简单定义了将会广播的通告(例如,一个广播显示设备电量低就仅仅包含了一个“电池电量低”的操作字符串)。

另外一个组件类型,content provider不是由intent来激活的。它是在ContentResolver有需求的时候才会被激活。Content resolver处理所有的content provider之间的直接交互,因此没有必要定义一个专门用于处理content provider之间交换的组件,只需要一个称之为ContentResolver的对象就可以了。在请求信息的组件和content provider之间存在一个抽象层(主要是为了安全进行考虑的)。

有以下几种方式可以用来激活组件:

  • 你可以通过发送Intent给startActivity()或者startActivityForResult()(希望得到启动的activity返回一个结果)来启动一个activity。
  • 你可以通过发送Intent给startService()来启动service,或者通过发送Intent给bindService()来绑定service。
  • 你可以通过发送Intent给sendBroadcast(),sendOrderedBroadcast()或者sendStickyBroadcast()来初始化一个广播。
  • 你可以通过调用ContentResolver的query()来查询一个content provider。

更多的关于intent使用的资讯请参考Intents和Intent Filters这个章节。特定组件的激活也可以参考一下文档:“Activities”,“Services”,“BroadcastReceiver”以及“Content Providers”。

 

Manifest文件

在Android系统启动应用组件之前,它是通过读取应用的AndroidManifest.xml文件(简称Manifest文件)来确定应用包含了哪些组件的。因此,你的应用必须把所有的组件都在这个文件中声明,并且把这个文件放在你的应用的根目录下面。

  • Manifest文件除了声明组件以外还做了以下这些事情:
  • 确定应用需要的用户权限,比如网络访问或者联系人的读取。
  • 声明应用中使用的API需要的最小API Level。
  • 声明应用所要求的硬件和软件特性,比如相机,蓝牙服务或者多点触控屏等。
  • 应用所需要连接的API库(除了Android框架层API),比如谷歌地图库。
  • ……

 

声明组件

Manifest文件的最基本功能就是向系统声明应用所包含的组件。例如,下面这个manifest文件就声明了一个activity组件:

<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子类的完整类名,android:label属性指定了activity的用户可见的标签字符串。

你必须用下面这些元素来定义应用组件:

  • <activity>:定义activities
  • <service>:定义services
  • <receiver>:定义broadcast receivers
  • <provider>:定义了content providers

在你的应用代码中包含的activities,services和content providers,若是没有在manifest文件中声明,将不可见,也就是说永远不会被运行。但是broadcast receiver可以在manifest中定义,也就可以在代码中动态申请(用BroadcastReceiver对象来做),只要调用registerReceiver()函数向系统注册即可。

关于如何实现manifest文件的更多资讯请参考“AndroidManifest.xml文件”这一章节。

声明组件功能

上文在“激活组件”章节中介绍过,可以通过Intent来启动activities,services和broadcast receivers。具体可以把目标组件的名字(组件类名字)明确写到intent中来实现。然而,intent真正的魅力在于隐式的intent。一个隐式的intent只是简单定义了操作的类型(有时会包括你所做操作的数据)并允许系统去搜寻到可以实现这个操作的组件并启动它。假如有多个组件可以实现这个操作,用户可以自己去选择使用哪一个组件。

系统通过查看接收到的intent在manifest文件中的intent filters中是否存在来决定这个组件是否可以响应该intent的。

当你在应用的manifest文件中定义activity的时候,可以包含一个intent filter,它主要用来声明activity的功能,这样你的应用就可以响应对应的intent了。包含intent filter的方法就是在组件声明元素里面加一个子元素<intent-filter>即可。

例如,你的email应用里面包含了一个发送新邮件的组件,你就可以声明一个对“send” intent(用来发送新的邮件)响应的intent filter:


<manifest ... >
 
...
 
<application ... >
 
<activity android:name="com.example.project.ComposeEmailActivity">
 
<intent-filter>
 
<action android:name="android.intent.action.SEND" />
 
<data android:type="*/*" />
 
<category android:name="android.intent.category.DEFAULT" />
 
</intent-filter>
 
</activity>
 
</application>
 
</manifest>


这样,当另外一个应用创建了一个ACTION_SEND的intent,并且通过startActivity()进行发送,系统就会启动你的activity,这样用户就可以撰写并发送一个邮件。

更多关于创建intent filter的资讯,请参考“Intents和Intent Filters”文档。

 

声明应用的需求

Android系统有各种各样的设备,他们的功能和特性各不相同。为了防止你的应用被安装到缺少相应功能的设备上,你需要在manifest文件中声明你的应用所需要的设备和软件特性。这些声明绝大数来说都只是一些信息,系统并不读取他们,不过一些外部服务回使用这些信息。比如Google商店将会利用他们来过滤搜索应用的设备。

例如,你的应用请求一个相机并且使用Android2.1的API(API Level 7),你就需要在manifest文件中做如下声明:

<manifest ... >
 
<uses-feature android:name="android.hardware.camera.any"
 
android:required="true" />
 
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
 
...
 
</manifest>

这样一来,不包含相机或者Android版本低于2.1的设备就不能安装你的应用。

当然,你也可以声明你的应用使用相机,但是并不是必须的。在这种情况下,你应当设置requeired属性为”false”,并且在运行的时候检查是否设备是否支持相机,假如不支持,需要禁止相关的功能。

更多的关于如何管理应用在不同设备上的兼容性请参考“设备兼容性”文档。

 

应用资源

应用除了有代码之外还需要资源,比如图片,音乐文件以及任何和你的应用视觉显示相关的东西。举例来说,你应当使用XML文件来定义动画,按钮,风格,颜色以及布局等用户可见的接口。使用应用资源可以使得应用不需要修改代码就能更新相关的特性,只要使用一系列可选的资源,就可以使得你的应用能够根据不同的设备配置来适配显示。(比如不同的语言和屏幕大小)

你的Android项目中所包含的每一个资源都被定义为一个唯一的整型ID,这样你就可以在代码或者别的资源的XML文件中使用这个ID来访问相应的资源。比如,你的应用中包含了一个图片资源名字为logo.png(保存在res/drawable目录下),SDK工具就会产生一个名为R.drawable.logo的资源ID,你可以就可以使用这个ID来访问这个图片资源。

Android支持对可选的资源进行不同的修饰。这个修饰就是包含在你的资源目录名字中的一个很短的字符串,它定义了这些资源使用的设备配置。比如,为了适应不同的屏幕方向以及大小,你需要为activity创建不同的布局。举例来说,当你的设备屏幕是竖着的,你可能希望按钮的布局是垂直的,而当你的屏幕是横向的时候,按钮就应当水平对齐。为了根据不同的屏幕方向改变布局,你可以定义两个不同的布局,他们的目录名字不同即可。这样,系统就能自动地根据当前设备的方向来访问不同的布局。

更多的关于应用中不同的资源以及如何创建不同设备配置的不同资源请参考“Providing Resources”章节。

 

本文阅读结束后推荐阅读下面章节

Intents和Intents Filters

它是介绍关于如何使用Intent API来启动应用组件的,比如启动activities,services以及如何让别的应用使用你的应用组件。

Activities

它是关于如何创建Activity类的实例的。

Providing Resources

它是关于Android应用如何把不同的应用资源和应用代码结合起来以及如何为不同的设备配置提供不同的资源。

下面两个章节也是可以阅读的

Device Compatibility

它是关于运行在不同设备上的Android信息以及介绍如何让你的应用能够很好的运行在不同设备上的。

System Permissions

它是关于应用当应用需要特定系统权限的API时,如何让用户允许应用访问这些API.

你可能感兴趣的:(android,api)