Android应用程序基础(Application Fundamentals)之一

点点圈 提交于 2019-12-06 02:56:36

正在尝试分析SDK中的示例程序NotePad,发现仍然还欠缺很多知识。今天看到 API Guides 下有一部分应用程序基础 Application Fundamentals,感觉需要进一步学习。于是准备采用之前的策略,边翻译,边学习。虽然这样做,学起来很慢,但是,好在可以慢慢理解,转化为自己的语言的同时也是一种加深记忆的过程。反正,我也只是业余学习,不赶时间,呵呵。

整个API指南有很多个章节,下面先把章节的名字列一下,这样知道还有多长的路要走。

API Guides (developer.android.com/guide/components/index.html)

  • [App Components]
  • [User Interface]
  • [App Resources]
  • [Animation and Graphics]
  • [Computation]
  • [Media and Camera]
  • [Location and Sensors]
  • [Connectivity]
  • [Text and Input]
  • [Data Storage]
  • [Administration]
  • [Web Apps]
  • [Best Practices]

其中第一章 应用程序组件(App Components)就有多个子章节。各章节的名字如下:

App Components

  • [App Fundamentals]
  • [Activities]
  • [Services]
  • [Content Providers]
  • [Intents and Intent Filters]
  • [Processes and Threads]
  • [Permissions]
  • [App Widgets]
  • [Android Manifest]

下面正式进入第一小节 App Fundamentals 的学习。

Android应用程序基础(Application Fundamentals)

Android应用程序使用JAVA语言编程。Android SDK工具编译源代码,并连同所有的数据文件和资源文件,打成一个Android包(以.apk为后缀的存档文件)。在一个.apk文件里的所有代码被认为是一个应用程序。基于Android系统的设备(手机或者平板)通过这个文件来安装应用程序。

Android应用程序一旦被安装到设备(手机或平板电脑)上,那么它就只存活在属于它自己的安全沙盒中。

译者注:现实中的沙盒,是一种儿童玩具,类如KFC中一个装满小球的容器,儿童可以在随意玩耍,起到保护儿童的作用。(也可以理解为一种安全环境)。同样在网络技术中也是一种按照安全策略限制程序行为的执行环境。

  • Android操作系统是一个多用户Linux系统,每一个应用程序在其中都是一个不同的用户。
  • 默认情况下,系统为每一个应用程序分配一个唯一的Linux用户ID(这个ID仅供系统使用,对应用程序不可见)。系统为应用程序中的所有文件设置权限,这样只有分配给该应用程序的用户ID可以访问它们。
  • 每一个处理进程都有它自己的虚拟机(VM),这样一个应用程序的代码是与其他应用程序隔离运行的。
  • 默认情况下,每个应用程序运行在它自己的Linux进程中。当应用程序的任何组件需要执行的时候,Android启动其处理进程。当不再需要它,或当系统需要为其他应用程序恢复内存时,关闭该处理进程。

在这种方式中,Android系统实现了最小特权原则。也就是,默认情况下,每个应用程序只能访问的它需要为其工作的组件,而没有更多权限。这创造了一个非常安全的环境,应用程序不能访问它没有获得权限的系统的一部分。

不过,也有一些方法可以使应用程序之间共享数据,或者让应用程序访问系统服务: 

  • 当两个应用程序需要互相访问对方的文件时,就可能为这两个应用程序分配同一个Linux用户ID。为了节省系统资源,具有相同用户ID的程序可以运行在同一个Linux进程中,并共享同一个虚拟机(应用程序也必须使用相同的签名证书)。
  • 应用程序可以请求访问设备(手机或平板)数据,如联系人信息,短信,可插拔的存储设备(SD卡),相机,蓝牙,和更多。应用程序的所有权限必须在安装的时候由用户授予。

本文介绍关于Android应用程序如何在系统运行的基础知识。本文档的其余部分将向你介绍:

  • 用来定义应用程序的核心框架组件。
  • 用来为应用程序声明组件和所需设备功能的清单文件(manifest file)。
  • 将资源从应用程序代码中分离,让应用程序可以在各种设备上都能完美运行。

应用程序组件(Application Components)

应用程序组件是应用程序的基本构建块。每个组件都是不同的切入点。通过它们,系统可以进入你的应用程序。并非所有的组件都是用户的实际切入点,它们其中的某一些是相互依赖的。但每一个组件都作为自己实体存在并扮演一个特定的角色,都是用来帮助定义你的应用程序整体行为的一个独特的建筑块。

有四种不同类型的应用程序组件。每种类型服务于不同的目的,有不同的生命周期(定义了如何创建和销毁)。

下面列举了这四种不同类型的应用程序组件:

Activities

一个activity就是一个用户界面。例如,一个电子邮件应用程序可能有一个activity,用于展示新电子邮件的列表,另一个activity用于编写电子邮件,还有一个用于读取邮件的activity。虽然在电子邮件这个应用中,多个activity共同作用形成了一个整体的用户体验。但是,每一个activity都是独立的。因此,另外一个应用程序可以启动这些activity中的任何一个(如果邮件应用程序允许的话)。例如,一个摄像头的应用可以通过启动邮件应用程序中的activity来新建一封电子邮件,从而实现照片分享功能。

一个activity要作为Activity的子类来实现,更多的信息可以参考Activity的开发指南。

Services

服务是一个在后台运行的组件,用来执行长时间操作或执行远程操作。服务不提供用户界面。例如,一个服务可以在后台播放音乐,而此时用户在另外一个不同的应用程序中。也可以用来从网络获取数据,而同时不阻塞用户与一个activity的交互。别的组件,如activity,可以启动一个服务,并让它运行,或者与它绑定,并进行交互。

一个服务要作为Service的子类来实现,更多的信息可以参考Services的开发指南。

Content providers

内容提供者管理应用程序用来共享的数据集合。你可以将数据存储在文件系统,SQLite数据库,互联网,或者其它任何你的应用程序可以访问的持久化存储位置。通过内容提供商,其他应用程序可以查询甚至修改数据(如果内容提供者允许的话)。例如,Android系统提供一个内容提供者用于管理用户的联系人信息。因此,任何拥有合适权限的应用程序可以查询内容提供者的某一部分(如ContactsContract.Data)来读取和写入一个特定联系人的信息。

内容提供者也可以用于读写那些应用程序私有的没有共享的数据。例如,记事本示例程序就使用内容提供者来保存记录信息。

内容提供商作为ContentProvider的一个子类来实现并且必须实现了一套标准的API接口,方便其他应用程序来调用执行欲了解更多信息,请参阅Content Providers开发人员指南

Broadcast receivers

广播接收器是一个用于响应系统范围内广播公告的组件。许多广播都是由系统所产生的。例如,一个广播可以报告屏幕已关闭,电量低,或者捕获到了一个图片。应用程序也可以发起广播——比如,让其他应用程序知道,有一些数据已经被下载到设备上,可以被他们使用了。虽然广播接收器不会有用户UI界面的显示,但是它们可能会创建一个状态栏通知,来告知用户有广播事件发生。通常来说,广播接收机只是一个到其它组件的“网关”,它要做的事情非常少。例如,它可能会启动一个服务来执行一些基于这一事件的工作。

一个广播接收机作为BroadcastReceiver的一个子类来实现,每个广播是作为一个Intent对象来交付的。更多的信息,请参见BroadcastReceiver类。

Android系统有一个不同寻常的特性,任何应用程序都可以启动另外一个应用程序的组件。例如,如果你希望用户使用设备(手机或者平板电脑)的摄像头去拍一张照片,这很有可能是另外一个应用程序所实现的功能,而你的应用程序可以直接去使用它。而不需要你自己开发一个activity去实现拍照的功能。你不需要合并或者链接相机应用程序的代码。相反地,你只需要简单地启动相机应用程序中的一个activity来实现拍照的功能。当拍照完成之后,所拍的照片甚至会返回到你的应用程序,这样你可以直接使用它。对于用户而言,照相机功能就好像是你的应用程序的一部分。

当系统启动一个组件时,应用程序就开始运行了(如果这之前并没有运行),并且实例化这个组件所需要的类。例如,如果你的应用程序启动了相机应用程序中的activity来捕捉一张照片,那么这个activity实际上是运行在相机应用程序的处理进程中,而不是在你的应用程序的处理进程中。因此,与大多数其他系统上的应用程序不同,Android应用程序没有一个单一的入口点(例如,没有main()函数)。

因为每个应用程序运行在一个单独的进程里,其文件权限限制了其他应用程序的访问。所以,你的应用程序不能直接激活另外一个应用程序中的组件。然而,Android系统可以。所以,要想激活另外一个应用程序中的组件,你必须给系统发一个消息,指定一个启动特定组件的intent。然后,系统就帮你去激活该组件。

Activating Components

四个组件类型的三个:活动、服务、广播接收器都是被一个称为intent的异步消息所激活的。Intent可以在运行时,将组件与组件之间结合起来(你可以把它们想象成信使,用于请求其他组件的动作),而不论这个组件是否是属于你的应用程序还是别的应用程序。

通过创建一个Intent对象来创建intent。它定义一个消息,用来激活一个特定组件或者特定类型的组件。一个intent可以是显式的,也可以是隐式的。

对于活动和服务,intent需要定义将要执行的操作(例如,“查看”或“发送”某些东西),同时也可能会给出操作时需要的数据的URI(或者组件开始工作时需要的其他什么东西)。例如,一个intent可能会请求一个活动来显示一个图像或打开一个网页。在某些情况下,你可以开始一个活动来获得结果,在这种情况下,该活动也会将结果放在Intent中返回(例如,可以发出一个intent,让用户选择一个联系人并返回给你,返回的intent包含一个指向所选定联系人的URI)。

对于广播接收器,intent只是简单地定义了要广播的公告(例如,一个指示设备电量不足的广播就只包含一个已知动作的字符串,以表示“电量不足”)。

其他组件类型,内容提供商,则不是被intent激活的。相反,它是被ContentResolver的一个请求所激活的。内容解析器(ContentResolver)处理所有与内容供应商(Content Provider)的直接交易,这样,执行事务的组件就不需要了,而是调用ContentResolver对象上的方法。这使得内容提供者和请求信息的组件之间有一个抽象层(为了安全)。

每个类型的组件都有单独的激活方法:

通过传递一个Intent给startActivity()或者startActivityForResult()(当需要返回结果时),你可以启动一个活动(或者给它一些新的东西去做)。

通过传递一个Intent给startService(),你可以启动一个服务(或者将新的指令发给正在运行的服务)。或者通过传递一个Intent给bindService()来实现服务的绑定。

通过传递一个Intent给sendBroadcast(),sendStickyBroadcast()或者sendOrderedBroadcast(),你可以发起一个广播。

通过调用ContentResolver的query()方法,你可以给内容提供者发起查询请求。

对于如何使用intent的更多信息,请参见Intents and Intent Filters文件。更多有关于激活特定的组件的信息,也在下列文件中提供:Activities,Services,BroadcastReceiver,Content Providers。

未完待续……

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!