`

【API Guides视频系列】第1篇Application Fundamentals(应用程序基础)

阅读更多
Application Fundamentals中文版:http://www.eyeandroid.com/AndroidDeveloper/JellyBean/guide/components/fundamentals.html
主要内容

  • 引入--Android工程目录介绍
  • 概述(Android应用程序如何在系统中存在)
  • 应用程序四大组件(Application Components)
  • 配置文件(The Manifest File)
  • 应用程序资源(Application Resources)
  • Q&A

视频讲解:http://www.eyeandroid.com/thread-6789-1-1.html
--------------------------------------------------------------------------
第1章 概述
快速浏览:
 Android应用程序由一个或者多个应用程序组件 (activities, services, content providers, and broadcast receivers)构成
 在整个应用程序的行为中,每个组件都扮演着自己的角色,并且它们都能被单独地激活 (甚至能被其他应用程序的组件激活)
 在应用程序的配置(Manifest)文件中,必须声明该应用程序使用的所有组件,还应该声明这个应用程序所需要信息,比如:能运行该应用程序的最小Android版本号、最低的硬件配置
 非代码的应用程序资源(如图像,字符串,布局文件等),应该为不同的设备配置不同的资源(如为不同屏幕尺寸设置不同的布局文件,为不同语言设置不同的字符串)
Android应用程序使用Java做为开发语言。aapt工具把编译后的Java代码连同其它应用程序需要的数据和资源文件一起打包到一个Android包文件中,这个文件使用.apk做为扩展名,它是分发应用程序并安装到移动设备的媒介,用户只需下载并安装此文件到他们的设备。单一.apk文件中的所有代码被认为是一个应用程序.
每一个Android应用程序,一旦被安装在一个设备上,它就存在于它自己的安全沙箱中:
 Android操作系统是一个多用户的Linux操作系统,在这个系统中每一个应用程序对系统而言都是一个不同的用户.
 默认情况下,每个应用程序均被赋予一个唯一的Linux用户ID,并加以权限设置,使得应用程序的文件仅对这个用户、这个应用程序可见。当然,也有其它的方法使得这些文件同样能为别的应用程序所访问.
 每个进程都运行于自己的Java虚拟机(VM)中。所以应用程序代码实际上与其它应用程序的代码是隔绝的.
 默认情况下,每个应用程序均运行于它自己的Linux进程中。当应用程序中的任意代码开始执行时,Android启动一个进程,而当不再需要此进程而其它应用程序又需要系统资源时,则关闭这个进程.
通过这种方式,Android系统实现了最小特权原则。也就是说,在默认情况下每个应用程序只能访问它需要工作的组件,并不能访问更多的组件。这将创建一个非常安全的环境,在这个环境中一个应用程序不能访问该应用程序没有访问权限的组件.
不过,也有应用程序与其他应用程序共享数据的方式,应用程序也能通过一定的方式访问系统提供的服务:
 让两个应用程序共享相同的Linux用户ID是可能的。在这种情况下,他们能够访问对方的文件。为了节省系统资源,具有相同用户ID的应用程序也可以安排运行在同一个Linux进程中和共享同一个VM(这两个应用程序也必须使用同的权限).
 应用程序可以请求访问设备的数据,比如用户联系人、短信、可卸载的存储设备(SDCard)、摄像头、蓝牙等等。所有应用程序的设备访问权限必须在其被安装时赋予.
上面的部分简单说明了一个Android应用程序如何在系统中存在的,该文档剩下的部分将会向你介绍:
 声明应用程序的核心框架组件.
 声明组件和声明应用程序所需要的设备的配置(Manifest)文件.
 与应用程序代码相分离的资源,让您的应用程序以优雅的方式优化其行为来符合各种不同的设备配置.

第2章 应用程序组件
应用程序组件是Android应用程序的重要基石。每个组件都是系统进入你的应用程序的不同的入口。并非所有的组件都是用户实际的进入点,有些是相互关联的.但是每一个组件都是作为一个实体的存在并且扮演了一个特殊的角色—在定义整个应用程序的行为时,每个组件都扮演了一个特殊的角色.
有四种不同类型的应用程序组件。每一种组件都起着不同的作用,还拥有不同的生命周期(生命周期始于创建终于销毁).
下面是四种不同类型的应用程序组件:
Activities
一个 Activity 代表用户界面的一个单屏.例如,在Email应用程序中,可能有一个Activity用于显示新收到的电子邮件列表,另一个Activity用于撰写电子邮件,还有一个Activity用于阅读电子邮件. 在Email应用程序中,尽管它们一起组成了一个内聚的用户界面,但其中每个activity都与其它的保持独立. 正因为如此,不同的应用程序可以启动这些Activities中的任何一个(假设Email应用程序允许其它程序这样做). 例如,当用户通过Camera应用程序拍下照片后,可以从Camera应用程序启动Email应用程序中的撰写新邮件的Activity来分享图片.
每个Activity都是以 Activity类为基类的子类,关于Activities更多的信息,请访问: Activities.
Services
Service没有可视化的用户界面,它是在后台运行的一个组件,主要用于执行一些耗时的操作或者为远程进程执行操作. 比如说,一个Service可以在用户做其它事情的时候在后台播放背景音乐、从网络上获取一些数据的时候而不用阻塞正在跟用户交互的Activity. 其它组件(如Activity)能为了运行Service而startService或者为了与Service交互而bindService .
每个Service都是以 Service 类为基类的子类,关于Services更多的信息,请访问 Services.
Content providers
一个 content provider 管理着一组共享的应用程序数据集. 你可以将数据存储到文件系统,SQLite数据库,网络或者其它你的应用程序能够访问的持久存储装置中. 通过 content provider, 其他应用程序能查询甚至修改你应用程序的数据(如果你的content provider允许其他应用程序这样做). 例如, Android系统提供了一个 content provider 管理用户的联系簿信息. 同样的, 任何有一定权限的应用程序都可以查询读取在 content provider 中的部分数据(例如 ContactsContract.Data) ,并且向其写入某个人的信息.
Content providers 用来读写你的应用程序私有的非公开的数据也是非常有用的. 例如, Note Pad 例子程序使用 content provider 保存笔记.
每个 content provider 都是以 ContentProvider 类为基类的子类,而且必须实现一个标准的APIs集合以便其他应用程序执行事务. 更多的信息请访问: Content Providers
Broadcast receivers
broadcast receiver 是一个响应系统级广播公告的组件. 许多广播都来源于系统—例如, 锁屏的广播, 电量低的广播, 一个图片已经被截取的广播. 应用程序也可以创建广播—例如,发送广播通知其它应用程序一些数据已经下载到设备上了并且可以被它们使用了. 尽管 broadcast receivers 不能提供一个用户界面, 但当一个广播事件发生时它们可以 创建一个状态提示条 提醒用户. 通常, broadcast receiver 只是一个通往其他组件的"网关" 并且只做一些非常小的工作. 例如, 例如,它可以开启一个执行基于事件工作的 service .
每个 broadcast receiver 都是以 BroadcastReceiver 类为基类的子类,并且每个广播都是以 Intent 对象发送的. 更多的信息请访问: BroadcastReceiver
Android操作系统设计的独特一面是任何应用程序都可以开启另一个应用程序的组件. 例如 , 如果你想要用户通过摄像头去捕获图片,你完全可以使用另外的应用程序的这个功能,以此来替代开发一个这样的功能. 你不需要结合或者连接摄像头应用程序的代码. 相反,你可以轻松的开启摄像头应用程序的Activity去获取图片. 当照相结束时,图片甚至可以返回到你的应用程序中供你使用. 对于用户而言,这个照相功能实际上就是你的应用程序的一部分.
当系统启动一个组件时, 它会为这个应用程序开启一个进程 (如果应用程序不是已经运行的) 并实例化这个组件需要的类. 例如,如果你的应用程序开启了摄像头程序中的Activity去照相, 那个Activity所在的进程是属于摄像头应用程序,不是属于你的应用程序进程. 因此,不像应用程序在其他大部分系统中一样,Android应用程序没有一个单一的入口 (例如没有 main() 函数).
因为系统在单独的进程中运行每个应用程序,并且赋予了文件权限限制访问其他应用程序, 因此,你的应用程序不能直接激活另一个应用程序的组件. 但是Android系统可以. 所以为了激活另一个应用程序的组件,你必须发送一个消息给系统用来指定你的去开启一个特殊组件的 intent. 然后系统可以帮你激活这个组件.
2.1激活组件
四个组件类型中的三个—activities, services, 和 broadcast receivers—都是被一个叫 intent的异步消息激活的. Intents 在运行时只绑定独立的组件 (你可以把Intents当成从其他组件请求某个响应的信使), 不管这个组件是否属于你的应用程序还是其他应用程序.
一个 intent 是由一个 Intent 对象创建的, 它定义了一个消息去激活一个特殊的组件或者一个特殊类型的组件—一个intent可以分别是显示的或者隐式的.
对于 activities 和 services, 一个 intent可以定义行为(Action)去执行 (例如, "view" 或者 "send" 一些东西) 和可以按照指定的URI数据去执行 (among other things that the component being started might need to know). 例如, 一个 intent 可能给一个 activity 传达要显示图片或者打开一个网页的请求. 在某些情况下, 你能开启一个 activity 接受结果, 某些时候, Activity 也可以返回结果到一个 Intent 中(例如, 你可以发布一个 intent 让用户选择一个私人的联系方式并且将结果返回给你—这个返回的 intent 包括指向适当联系方式的URI).
对于 broadcast receivers, Intent 简单定义了将被广播的公告 (例如, 一个指示设备电量低的广播仅包括一个已知的响应字符串 "battery is low").
其他的组件类型, content provider, 不是由 intents 激活的. 相反, 它是由来自 ContentResolver的请求被指定时激活的. 这个 content resolver 处理所有直接与 content provider 相关的事务 所以用Content Provider执行事务的组件并不需要做,而是调用 ContentResolver 对象中的方法. 这样就在 content provider 和组件中间存在一个请求信息的抽象层 (出于安全的考虑).
有一些用于激活每种组件类型的独立方法:
 你能够启动一个Activity (或者给这个Activity一些新的东西去做) 通过传递一个 Intent 对象给 startActivity() 或者 startActivityForResult() (当你想要这个Activity返回一个结果时).
 你能够启动一个 service (或者给正在执行是Service一些新的指令) 通过传递一个 Intent 对象给 startService(). 或者你想绑定一个 service 通过传递一个 Intent 对象给 bindService().
 你能够初始化一个broadcast通过传递一个 Intent 对象给类似这些方法: sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast().
 在content provider中, 你可以执行一次查询通过调用ContentResolver的query()方法.
想要了解更多关于如何使用intents,请参看: Intents and Intent Filters document. 关于激活特殊组件的更多信息可以在以下文档中获取: Activities, Services, BroadcastReceiver 和 Content Providers.
第3章 Manifest 文件
在Android系统开启一个应用程序的组件之前, 系统必须通过读取应用程序的 AndroidManifest.xml 文件("manifest"文件)知道这个组件是否存在. 你的应用程序必须在清单文件中定义应用程序所使用的的所有组件, 并且这个文件必须在应用程序的根目录下.
这个配置文件除了声明应用程序组件外,还有很多其他的作用,例如:
 识别应用程序需要的用户的权限,例如网络访问权限或者用户联系薄的读写权限.
 声明应用程序所需的最低 API Level版本, 应用程序使用的是基于哪种版本的 APIs.
 声明应用程序使用或者需要的软硬件特征, 例如一个摄像头,蓝牙设备或者一个多点触控的屏幕.
 应用程序需要去连接的API程序库 (除了Android框架APIs), 例如 Google Maps 程序库.
 还有很多其他的

3.1声明组件
配置文件的最主要的作用就是通知系统应用程序有哪些组件. 例如, 一个配置文件能定义一个Activity如下:
<?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 子类的名称, android:label 属性为 activity指定了一个用户可视化标签使用的字符串.
你必须这样定义所有的应用程序组件:
 <activity> 元素定义 activities
 <service> 元素定义 services
 <receiver> 元素定义 broadcast receivers
 <provider> 元素定义 content providers
源码中使用了 Activities, services, and content providers, 如果不在配置文件中声明他们, 那么系统永远不会识别和运行它们 . 但是, broadcast receivers 却可以既在配置文件中声明也可以在代码中动态创建 (作为 BroadcastReceiver 对象) ,并且调用 registerReceiver() 方法在系统中注册.
想了解更多关于怎样去结构化应用程序的配置文件,请查看 The AndroidManifest.xml File.
3.2声明组件的功能
正如我们上面讨论的, 在 Activating Components(激活组件中), 你可以使用一个 Intent对象 去启动 activities, services, 和 broadcast receivers. 你可以这么着通过显示的在intent中命名目标组件 (通过使用组件的类名) . 但是, intents的真正作用在于intent的行为(Action)概念. 对于intent的acions, 你可以简单的描述你要执行的Action类型 (在你想要执行的Action上的数据是可选的)并且允许系统去寻找一个可以执行这个Action的组件并启动它 . 如果有多个组件可以执行intent描述的Action,让用户选择其中的一个.
系统识别可以响应一个intent的组件的方法是: 通过比较接收到的intent与其他应用组件在配置文件中定义的 intent filters.
你在你的应用程序的配置文件中声明一个组件时, 你可以选择性地加入可以定义组件功能的 intent filters 以致它可以对从其它组件的 intents 进行响应. 你可以为组件声明一个 intent filter 通过增加一个<intent-filter>元素作为组件声明元素的子元素.
例如, 一个携带编写新邮件Activity的邮件应用程序可以在它的配置文件的元素中声明一个intent filter, 从而去响应"send" intents (为了去发送邮件). 在你应用程序的一个 activity 以为“send”Action创建一个intent (ACTION_SEND), 当你通过 startActivity()方法触发这个Intent时,系统会与邮件应用程序的”send”Activity进行匹配成功并启动这个Activity.
想了解更多关于创建 intent filters, 请参考 Intents and Intent Filters.
3.3声明应用程序需求
支持Android系统的设备有很多种,但并不是所有的设备都提供相同的特性和功能. 为了防止你的应用程序要安装在的设备上缺少必要的特性, 通过在你的配置文件中声明设备和软件的需求,从而清楚地定义一个关于你的应用程序相关支持的概括就变得很重要了. 多数这些声明都只是信息性的,系统并不会读取它们, 但是外部的服务(例如Android市场)会读取它们,为用户在搜索应用程序时提供过滤条件.
例如, 如果你的应用程序需要一个摄像头和使用Android2.1 (API Level 7)的APIs, 应该在你的配置文件中定义这些需求. 这样,那些没有摄像头和Android版本低于2.1的设备就不能安装你Android市场上的应用程序.
尽管如此,你不是一定要定义你的应用程序使用摄像头. 这样,你的应用程序就必须在运行时执行检查,从而判断设备是否装有摄像头,并且处理在没有摄像头的情况下无效相关的功能特性.
在你设计和开发应用程序时,你应该考虑一些重要的设备特性:
Screen size and density(屏幕的大小和密度)
为了通过屏幕的类型来对设备分类,Android为每个设备定义了两个特性 :屏幕大小 (屏幕的实际尺寸) 和屏幕的密度 (屏幕的物理像素密度, 或者dpi—每英寸点数). 为了简化所有不同类型屏幕的配置,Android系统将它们概括成了可供选择的组从而更方便指定.
屏幕的大小是: 小,中,大和特大.
屏幕的密度是:低密度,中等密度,高密度和特高密度.
默认情况下你的应用程序是可以适应所有屏幕的大小和密度的,因为Android系统为你的UI布局和图片资源做了适当的调整. 尽管如此,你还是应该为特定的屏幕大小创建合理的布局,还要为特定的密度提供合理的图片, 应该使用可以有可替换的布局资源和在你的清单文件中使用 <supports-screens> 元素明确定义你的应用程序所支持的屏幕大小.
了解更多的信息,请查看: Supporting Multiple Screens.
Input configurations(输入配置)
许多设备提供了不同类型的用户输入机制,例如一个硬件键盘,一个轨迹球或者一个5道导航台. 如果你的应用程序需要一个特殊的输入硬件,那么你应该在你的清单文件中使用 <uses-configuration> 元素定义它. 但是很少有一个应用程序需要一个特定输入配置的情况.
Device features(设备特性)
有很多硬件和软件特性可能或者不可能存在一个给定的Android设备中,例如一个摄像头,一个光感器,蓝牙,一个特定的OpenGL版本或者高保真的触摸屏. 你不应该假定可以在所有的Android设备中获得某一个特性 (除了标准Android程序库之外), 所以你应该使用 <uses-feature> 元素定义你的应用程序所需的任一特性.
Platform Version(平台版本)
不同的Android设备常常运行在不同版本的Android平台上,例如Android1.6或者Android2.3. 每个后续的版本常常包含以前版本并不支持的额外的APIs. 了指示可以得到哪些APIs,每个平台版本都指定了一个 API Level级别 (如Android1.0是API级别1,Android2.3是API级别9). 如果你使用的任一APIs都已经加入到了1.0版本之后的平台中,你应该使用 <uses-sdk> 元素定义那些APIs所在的最低API级别.
你为应用程序定义所有的需求是很重要的,因为当你把应用程序发布到Android市场时,市场会使用这些定义去过滤哪个应用程序可以被每个设备使用. 同样的,你的应用程序只能在符合你的应用程序所有需求的设备上使用.
想了解更多关于Android市场是如何基于这些(其他)需求去过滤应用程序的信息,请查看: Market Filters.
第4章 应用程序资源
一个Android应用程序不仅仅只是由代码组成—它还需要独立于源代码的资源。例如图片,音频文件和任何应用程序的可视化相关的东西. 例如你应该定义动画,菜单,样式,颜色和Activity用户界面的XML布局文件. 使用应用程序资源使它能简单的在不修改代码的情况下更新你应用程序各种各样的特性—通过提供可替换的资源集合—使你能够通过各种设备配置来最优化你的应用程序 (例如不同的语言和屏幕的大小).
在你的应用程序中包含的每个资源,SDK编译工具都会定义一个唯一的整型ID, 你可以在应用程序中通过这个引用来使用资源或者使用其他定义在XML中的资源. 例如,如果你的应用程序包括一个叫 logo.png 的图片(保存在 res/drawable/ 目录下), SDK工具生成了一个叫 R.drawable.logo的资源ID, 你可以通过这个ID来引用这个图片并且将它插入到你的用户界面中.
提供独立于源代码的资源的最重要方面是你能拥有能为不同设备配置提供可替换资源. 例如,通过在XML中定义UI字符串,你可以将字符串转换成其他语言并且保存在一个不同的独立的文件中. 然后基于你添加到资源目录名的语言限定符 (例如法语字符串值 res/values-fr/) 和用户的语言设定,Android系统将在你的UI中应用适当的语言字符串.
Android支持多种不同的限定符供你的可替换资源使用. 限定符是一个短字符串,它包含在你的资源目录名里,为了定义那些应该被使用到的设备配置. 又如另一个例子,你应该常常创建不同Activity布局, 依赖于设备的屏幕定位和大小. 例如,当设备的屏幕是在竖向方向 (高), 你可能想要一个垂直的按钮布局, 但是当屏幕是在横向方向(宽), 按钮就应该水平对齐.为了使布局随着定位而改变,你可以定义两个不同的布局并且将适当的限定符应用到每个布局目录名中. 这样,系统就会自动根据现有的设备定位来应用适当的布局.
想了解更多包含在应用程序中的不同资源类型和怎样为各种设备配置创建可替换的资源, 请查看: Application Resources.

1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics