Android 2高级编程(第2版)


移动与嵌入式开发技术 Android 2 高级编程 (第 2 版) (英) Reto Meier 著 王 超 译 II 北 京 Reto Meier Professional Android 2 Application Development EISBN:978-0-470-56552-0 Copyright © 2010 by Wiley Publishing, Inc. All Rights Reserved. This translation published under license. 本书中文简体字版由 Wiley Publishing, Inc. 授权清华大学出版社出版。未经出版者书面许可,不得以任何方式 复制或抄袭本书内容。 北京市版权局著作权合同登记号 图字:01-2010-5687 本书封面贴有 Wiley 公司防伪标签,无标签者不得销售。 版权所有,侵权必究。侵权举报电话:010-62782989 13701121933 图书在版编目(CIP)数据 Android 2 高级编程(第 2 版)/ (英) 梅尔(Meier,R.) 著;王超 译. —北京:清华大学出版社,2010.12 书名原文:Professional Android 2 Application Development (移动与嵌入式开发技术) ISBN 978-7-302-24102-7 Ⅰ. A… Ⅱ. ①梅… ②王… Ⅲ. 移动通信-携带电话机-应用程序-程序设计 Ⅳ. TN929.53 中国版本图书馆 CIP 数据核字(2010)第 221240 号 责任编辑:王 军 韩宏志 装帧设计:康 博 责任校对:胡雁翎 责任印制: 出版发行:清华大学出版社 地 址:北京清华大学学研大厦 A 座 http://www.tup.com.cn 邮 编:100084 社 总 机:010-62770175 邮 购:010-62786544 投稿与读者服务:010-62776969, c-service@tup.tsinghua.edu.cn 质 量 反 馈:010-62772015, zhiliang@tup.tsinghua.edu.cn 印 刷 者: 装 订 者: 经 销:全国新华书店 开 本:185×260 印 张:33 字 数:803 千字 版 次:20 年 月第 版 印 次: 年 月第 次印刷 印 数:1~4000 定 价:68.00 元 —————————————————————————————————————————————— 产品编号: 目 录 第 1 章 Android 简介 ............................ 1 1.1 一些背景信息 ............................... 2 1.1.1 不远的过去 ................................ 2 1.1.2 未来的前景 ................................ 3 1.2 对 Android 的误解 ........................ 3 1.3 开放的移动开发平台 ................... 4 1.4 自带的 Android 应用程序 ............ 4 1.5 Android SDK 的特征 .................... 5 1.5.1 访问硬件(包括摄像头、GPS 和 加速计) ...................................... 6 1.5.2 自带的 Google 地图、地理编码 和基于位置的服务 .................... 6 1.5.3 后台服务 .................................... 6 1.5.4 SQLite 数据存储和检索 数据库 ........................................ 7 1.5.5 共享数据和应用程序间通信 .... 7 1.5.6 使用小组件、Live Folder 和 Live Wallpaper 润色主屏幕 ............... 7 1.5.7 广泛的媒体支持和 2D/3D 图形 ............................................ 8 1.5.8 优化的内存和进程管理 ............ 8 1.6 开放手机联盟简介 ....................... 8 1.7 Android 的运行环境 ..................... 8 1.8 从事移动开发的原因 ................... 9 1.9 从事 Android 开发的原因 ............ 9 1.9.1 推动 Android 普及的因素 ....... 10 1.9.2 Android 的独到之处 ................ 10 1.9.3 改变移动开发格局 .................. 11 1.10 开发框架简介 ........................... 11 1.10.1 开发包中的资源.................. 12 1.10.2 理解 Android 软件栈 .......... 12 1.10.3 Dalvik 虚拟机 ...................... 14 1.10.4 Android 应用程序架构 ....... 14 1.10.5 Android 库 ........................... 15 1.11 小结 ........................................... 15 第 2 章 开始入手 ................................ 17 2.1 Android 开发 ............................... 18 2.1.1 开始前的准备工作 .................. 18 2.1.2 创建第一个 Android 应用 程序 .......................................... 22 2.1.3 Android 应用程序的类型 ........ 27 2.2 面向移动设备的开发 ................. 29 2.2.1 硬件限制带来的设计考虑 事项 .......................................... 29 2.2.2 考虑用户环境 .......................... 32 2.2.3 Android 开发 ............................ 33 2.3 To-Do List 示例 .......................... 36 2.4 Android 开发工具 ....................... 40 2.4.1 Android 虚拟设备和 SDK 管理器 ...................................... 41 2.4.2 Android 模拟器 ........................ 42 2.4.3 Dalvik 调试监控服务 (DDMS) .................................... 43 2.4.4 Android 调试桥(ADB) ............. 43 2.5 小结 ............................................. 44 第 3 章 创建应用程序和活动 .............. 45 3.1 Android 应用程序的组成部分 .... 46 3.2 应用程序清单简介 ..................... 47 3.3 使用清单编辑器 ......................... 52 3.4 Android 应用程序生命周期 ....... 53 3.5 理解应用程序的优先级和进程 状态 ............................................. 54 3.6 分离资源 ..................................... 55 3.6.1 创建资源 .................................. 55 3.6.2 使用资源 .................................. 62 3.6.3 To-Do List 资源示例 ............... 65 Android 2 高级编程(第 2 版) X 3.6.4 为不同的语言和硬件创建 资源 .......................................... 66 3.6.5 运行时配置更改 ...................... 67 3.7 Application 类简介 ..................... 69 3.7.1 扩展和使用 Application 类 ..... 69 3.7.2 重写应用程序的生命周期 事件 .......................................... 70 3.8 深入探讨 Android 活动 .............. 71 3.8.1 创建一个活动 .......................... 71 3.8.2 活动生命周期 .......................... 73 3.8.3 Android 活动类 ....................... 78 3.9 小结 ............................................. 78 第 4 章 创建用户界面 ......................... 79 4.1 Android UI 基本设计 ................. 80 4.2 视图简介 ..................................... 80 4.2.1 使用视图创建活动的用户 界面 .......................................... 81 4.2.2 Android 小组件工具箱 ............ 82 4.3 布局简介 ..................................... 83 4.3.1 使用布局 .................................. 83 4.3.2 优化布局 .................................. 85 4.4 创建新视图 ................................. 85 4.4.1 修改现有的视图 ...................... 86 4.4.2 创建复合控件 .......................... 90 4.4.3 创建定制的视图 ...................... 93 4.4.4 使用定制的控件 ................... 103 4.5 Drawable 资源 .......................... 104 4.5.1 形状、颜色和渐变 ............... 104 4.5.2 复合 Drawable ...................... 107 4.5.3 NinePatch Drawable ............... 110 4.6 分辨率和像素密度无关性 ....... 110 4.6.1 资源框架和分辨率无关性 .... 111 4.6.2 分辨率无关性的最佳实践 .... 112 4.6.3 反复测试 ................................ 114 4.7 创建和使用菜单 ....................... 115 4.7.1 Android 菜单系统简介 .......... 115 4.7.2 定义活动的菜单 .................... 117 4.7.3 菜单项选项 ............................ 118 4.7.4 动态更新菜单项 ................... 119 4.7.5 处理菜单选择 ....................... 120 4.7.6 子菜单和上下文菜单 ........... 120 4.7.7 使用 XML 定义菜单 ............ 122 4.7.8 To-Do List 示例续 ................ 123 4.8 小结 ........................................... 128 第 5 章 意图、广播接收器、Adapter 和 Internet ............................ 131 5.1 意图简介 ................................... 132 5.1.1 使用意图来启动活动 ........... 132 5.1.2 使用意图过滤器为隐式 意图提供服务 ....................... 138 5.1.3 使用意图过滤器作为插件 和扩展 ................................... 146 5.1.4 Linkify 简介 .......................... 148 5.1.5 使用意图来广播事件 ........... 151 5.2 待处理意图简介 ....................... 155 5.3 Adapter 简介 ............................. 156 5.3.1 部分本地 Adapter 简介 ........ 156 5.3.2 定制 ArrayAdapter ................ 156 5.3.3 使用 Adapter 绑定数据 ........ 157 5.4 使用 Internet 资源 ..................... 162 5.4.1 连接到 Internet 资源 ............. 163 5.4.2 使用 Internet 资源 ................. 164 5.5 对话框简介 ............................... 164 5.5.1 Dialog 类简介 ....................... 164 5.5.2 将活动用作对话框 ............... 166 5.5.3 管理和显示对话框 ............... 167 5.6 创建一个地震查看器 ............... 168 5.7 小结 ........................................... 176 第 6 章 文件、保存状态和首选项 ..... 179 6.1 保存简单的应用程序数据 ....... 180 6.2 创建并保存首选项 ................... 180 6.3 检索共享首选项 ....................... 181 6.4 为地震查看器创建一个设置 活动 ........................................... 181 6.5 首选项活动和首选项框架 概述 ........................................... 189 目 录 XI 6.5.1 在 XML 中定义一个首选项 屏幕布局 ............................... 190 6.5.2 首选项活动简介 ................... 192 6.5.3 查找并使用首选项屏幕 共享首选项 ........................... 193 6.5.4 共享首选项变更监听程序 简介 ....................................... 193 6.6 为地震查看器创建一个标准的 首选项活动 ............................... 194 6.7 保存活动状态 ........................... 195 6.7.1 保存并还原实例状态 ........... 195 6.7.2 保存 To-Do List 活动状态 ... 196 6.8 保存和加载文件 ....................... 198 6.9 将静态文件作为资源添加 ....... 199 6.10 文件管理工具 ......................... 200 6.11 小结 ......................................... 200 第 7 章 数据库和内容提供器 ............. 201 7.1 Android 数据库简介 ................. 201 7.1.1 SQLite 数据库简介 .............. 202 7.1.2 内容提供器简介 ................... 202 7.2 SQLite 简介 .............................. 202 7.3 游标和内容值 ........................... 203 7.4 使用 SQLite 数据库 ................. 203 7.4.1 使用 SQLiteOpenHelper ....... 206 7.4.2 在不使用 SQLiteHelper 的 情况下打开和创建数据库 ... 207 7.4.3 Android 数据库设计注意 事项 ....................................... 207 7.4.4 查询数据库 ........................... 207 7.4.5 从 Cursor 中提取结果 .......... 208 7.4.6 添加、更新和删除行 ........... 209 7.4.7 保存 To-Do List .................... 210 7.5 创建一个新的内容提供器 ....... 216 7.5.1 提供对数据源的访问 ........... 217 7.5.2 注册提供器 ........................... 219 7.6 使用内容提供器 ....................... 219 7.6.1 内容解析器简介 ................... 219 7.6.2 查询内容 ............................... 219 7.6.3 添加、更新和删除内容 ....... 220 7.6.4 在内容提供器中访问文件 ... 221 7.7 创建和使用地震内容提供器 ... 222 7.7.1 创建内容提供器 ................... 222 7.7.2 使用提供器 ........................... 227 7.8 本地 Android 内容提供器 ........ 229 7.8.1 使用媒体库提供器 ............... 230 7.8.2 使用联系人提供器 ............... 231 7.9 小结 ........................................... 235 第 8 章 地图、地理编码和基于位置的 服务 ..................................... 237 8.1 使用基于位置的服务 ............... 238 8.2 配置模拟器来测试基于位置的 服务 ........................................... 238 8.3 更新模拟位置提供器中的 位置 ........................................... 238 8.4 选择一个位置提供器 ............... 239 8.4.1 查找可用的提供器 ............... 239 8.4.2 根据标准查找位置提供器 ... 240 8.5 确定自己所在的位置 ............... 241 8.5.1 “Where Am I”示例 ........... 241 8.5.2 追踪移动 ............................... 244 8.5.3 更新“Where Am I”示例 中的位置 ............................... 245 8.6 使用邻近提醒 ........................... 247 8.7 使用地理编码器 ....................... 248 8.7.1 反向地理编码 ....................... 249 8.7.2 前向地理编码 ....................... 249 8.7.3 对“Where Am I”示例进行 地理编码 ............................... 251 8.8 创建基于地图的活动 ............... 252 8.8.1 MapView 和 MapActivity 简介 ....................................... 252 8.8.2 获得地图的 API 键 ............... 253 8.8.3 创建一个基于地图的 活动 ....................................... 254 8.8.4 配置和使用 MapView .......... 255 8.8.5 使用 MapController .............. 256 Android 2 高级编程(第 2 版) XII 8.8.6 对“Where Am I”示例使用 地图 ....................................... 256 8.8.7 创建和使用覆盖 ................... 260 8.8.8 MyLocationOverlay 简介 ..... 267 8.8.9 ItemizedOverlay 和 OverlayItem 简介 .................. 267 8.8.10 将视图固定到地图和 地图的某个位置上 ............. 269 8.9 对 Earthquake 示例添加地图 功能 ........................................... 271 8.10 小结 ......................................... 276 第 9 章 后台工作 .............................. 277 9.1 服务简介 ................................... 278 9.1.1 创建和控制服务 ................... 279 9.1.2 将活动和服务绑定 ............... 289 9.1.3 后台服务的优先级 ............... 291 9.2 使用后台线程 ........................... 292 9.2.1 使用 AsyncTask 运行异步 任务 ....................................... 292 9.2.2 使用 AsyncTask 将 Earthquake Service 移动到后台线程 ...... 294 9.2.3 手动创建线程和 GUI 线程 同步 ....................................... 295 9.3 创建 Toast ................................. 297 9.3.1 定制 Toast ............................. 297 9.3.2 在工作线程中使用 Toast ..... 299 9.4 通知简介 ................................... 299 9.4.1 通知管理器简介 ................... 300 9.4.2 创建通知 ............................... 300 9.4.3 触发通知 ............................... 304 9.4.4 向地震监控器中添加通知 和 Toast ................................. 304 9.4.5 高级通知技术 ....................... 307 9.4.6 持续的和连续的通知 ........... 310 9.5 使用警报 ................................... 310 9.5.1 设置重复警报 ....................... 312 9.5.2 使用重复警报更新 Earthquake ............................. 313 9.6 小结 ........................................... 315 第 10 章 个性化手机屏幕 ................. 317 10.1 主屏幕小组件简介 ................. 318 10.2 创建 App Widgets ................... 318 10.2.1 创建小组件布局 .............. 319 10.2.2 定义小组件设置 .............. 321 10.2.3 创建小组件意图接收器 并将其添加到应用程序 清单中 .............................. 321 10.2.4 Remote Views 和 App Widget Manager 简介 ................... 322 10.2.5 刷新小组件 ...................... 327 10.2.6 创建并使用小组件配置 活动 .................................. 329 10.3 创建地震小组件 ..................... 330 10.4 Live Folder 简介 ..................... 335 10.4.1 创建 Live Folder ............... 336 10.4.2 创建 Earthquake Live Folder ................................ 338 10.5 将搜索添加到应用程序以及 快速搜索框中 ......................... 340 10.5.1 将搜索添加到应用 程序中 .............................. 341 10.5.2 在快速搜索框中显示搜索 结果 .................................. 344 10.5.3 将搜索添加到 Earthquake 示例中 .............................. 344 10.6 创建 Live Wallpaper ............... 348 10.6.1 创建 Live Wallpaper 定义 资源 .................................. 348 10.6.2 创建 Wallpaper 服务 ........ 348 10.6.3 创建 Wallpaper 服务 引擎 .................................. 349 10.7 小结 ......................................... 350 第 11 章 音频、视频以及摄像头的 使用 ................................... 351 11.1 播放音频和视频 ..................... 352 11.1.1 Media Player 简介 ............ 352 目 录 XIII 11.1.2 准备音频播放 .................. 353 11.1.3 准备视频播放 .................. 354 11.1.4 控制播放 .......................... 357 11.1.5 管理媒体播放输出 .......... 358 11.2 录制音频和视频 ..................... 358 11.2.1 使用意图录制视频 .......... 358 11.2.2 使用媒体刻录机 .............. 359 11.3 使用摄像头并拍摄照片 ......... 362 11.3.1 使用意图拍摄照片 .......... 362 11.3.2 控制摄像头并拍摄照片... 364 11.3.3 读取并写入 JPEG EXIF 图像详细信息 .................. 368 11.4 向媒体库中添加新媒体 ......... 369 11.4.1 使用媒体扫描仪 .............. 369 11.4.2 向媒体库中插入媒体 ...... 370 11.5 原始音频操作 ......................... 370 11.5.1 使用 AudioRecord 录制 声音 .................................. 370 11.5.2 使用音频轨道播放声音... 372 11.6 语音识别 ................................. 373 11.7 小结 ......................................... 374 第 12 章 电话服务和 SMS ................ 377 12.1 电话服务 ................................. 378 12.1.1 启动拨号程序以初始化 电话呼叫 .......................... 378 12.1.2 替换本机拨号程序 .......... 378 12.1.3 访问电话和网络属性以及 状态 .................................. 379 12.1.4 监视电话状态、电话活动 以及数据连接中的变化 ... 382 12.2 SMS 和 MMS 简介 ................ 386 12.2.1 在应用程序中使用 SMS 和 MMS ............................ 386 12.2.2 使用意图和本机客户端从 应用程序中发送 SMS 和 MMS ............................ 387 12.2.3 手动发送 SMS 消息 ........ 388 12.2.4 监听传入的 SMS 消息 .... 391 12.2.5 紧急响应程序 SMS 示例 .................................. 393 12.2.6 自动化紧急响应程序 ....... 402 12.3 小结 ......................................... 410 第 13 章 蓝牙、网络和 Wi-Fi............. 411 13.1 使用蓝牙 ................................. 411 13.1.1 访问本地蓝牙设备 适配器 .............................. 412 13.1.2 管理蓝牙属性和状态 ....... 413 13.1.3 可发现性和远程设备 发现 .................................. 415 13.1.4 蓝牙通信 .......................... 418 13.1.5 蓝牙数据传输示例........... 424 13.2 管理网络连接 ......................... 433 13.2.1 Connectivity Manager 简介 .................................. 433 13.2.2 读取用户首选项用于后台 数据传输 .......................... 434 13.2.3 监视网络详细信息........... 435 13.2.4 查找并配置网络首选项 以及控制硬件信号 ........... 435 13.2.5 监视网络连接 .................. 436 13.3 管理 Wi-Fi .............................. 436 13.3.1 监视 Wi-Fi 连接 ............... 437 13.3.2 监视活动连接详细 信息 .................................. 437 13.3.3 扫描热点 .......................... 438 13.3.4 管理 Wi-Fi 配置 ............... 438 13.3.5 创建 Wi-Fi 网络配置 ....... 439 13.4 小结 ......................................... 439 第 14 章 传感器 ................................ 441 14.1 使用传感器和传感器 管理器 ..................................... 442 14.2 解释传感器数值 ..................... 445 14.3 使用指南针、加速计和方向 传感器 ..................................... 445 14.3.1 加速计简介 ...................... 446 14.3.2 检测加速度变化 .............. 447 Android 2 高级编程(第 2 版) XIV 14.3.3 创建一个 G-Forceometer (重力测力计) .................... 448 14.3.4 确定设备方向 .................. 451 14.3.5 创建一个指南针和人工 地平仪 .............................. 454 14.4 控制设备振动 ......................... 458 14.5 小结 ......................................... 459 第 15 章 Android 高级开发 ............... 461 15.1 Android 的安全性 .................. 462 15.1.1 Linux 内核安全 ................ 462 15.1.2 权限简介 .......................... 462 15.1.3 声明和实施权限 .............. 463 15.1.4 为广播意图实施权限 ...... 464 15.2 使用 Wake Lock...................... 464 15.3 Android Text To Speech 简介 .... 465 15.4 使用 AIDL 来支持服务 的 IPC ...................................... 467 15.4.1 实现 AIDL 接口 ............... 467 15.4.2 将类对象作为 Parcelable 传递 .................................. 468 15.4.3 实现和提供 IPC 接口 ...... 470 15.5 使用 Internet 服务 .................. 472 15.6 构建内容丰富的用户界面 ..... 473 15.6.1 使用动画 .......................... 473 15.6.2 高级画布绘图 .................. 484 15.6.3 SurfaceView 简介 ............. 499 15.6.4 创建交互式控件 .............. 502 15.7 小结 ......................................... 508 Android 简介 本章主要内容 ● 移动应用程序开发简介 ● Android 简介 ● Android SDK 特征简介 ● 适用 Android 的设备 ● 从事移动开发和 Android 开发的原因 ● Android SDK 和开发架构简介 无论你是一名经验丰富的移动开发工程师、一个桌面或者 Web 开发人员还是一个初出 茅庐的编程新手,Android 都为编写具有创新性的移动应用程序带来了令人兴奋的新机遇。 虽然它被命名为 Android(机器人),但是它并不会帮助你打造一支势不可挡的铁血机器 人部队来修复人类在地球上造成的破坏。事实上,Android 是一个开源的软件栈,它包含 了操作系统、中间件和关键的移动应用程序,以及一组用于编写移动应用程序的 API 库。 所编写的移动应用程序将决定移动设备的样式、观感和功能。 小巧玲珑,外观时尚且功能丰富的现代移动设备已经成为了集摄像头、媒体播放器、 GPS 系统和触摸屏为一体的强大工具。随着技术的发展,手机的功能已不再仅仅是打电话 那么简单,但是相比之下,它们的软件和开发平台却有所滞后。 不久前,手机平台在很大程度上还是一个封闭的环境,主要还是以要求使用专有开发 工具的专用操作系统为基础构建的。通常这些手机自身的应用程序的优先级要比第三方开 发的应用程序的优先级高。对于那些希望在硬件性能日益强大的移动设备上进行开发的人 员来说,这就设置了人为障碍。 1 第 章 Android 2 高级编程(第 2 版) 2 在 Android 中,本地应用程序和第三方应用程序使用相同的 API 编写,并且在相同的 运行时(run time)上执行。这些 API 的功能包括硬件访问、视频录制、基于位置的服务(location- based service)、后台服务支持、基于地图的活动(activities)、关系数据库、应用程序间的通 信以及 2D 和 3D 图形。 通过本书,你可以学习到怎样使用这些 API 来开发自己的 Android 应用程序。在本章 中,你将会学习到一些移动开发的准则以及 Android 开发平台提供的一些功能。 Android 拥有功能强大的 API、出色的文档以及茁壮成长的开发人员社区,而且不需要 为开发或发布支付费用。随着移动设备的日益普及,不管具有什么样的开发背景,使用 Android 来开发新颖的手机应用程序都是一个令人为之振奋的良机。 1.1 一些背景信息 在 Twitter 和 Facebook 出现之前,当 Google 还只是一个想法的时候,手机只是足够小 的便携电话,能够放在一个公文包中,电池足够用上几个小时。虽然没有多余的功能,但 是手机确实使人们可以不通过物理通信线路就能自由通信。 现在,小巧、时尚而且功能强大的手机已经相当普及并且不可或缺。硬件的发展使手 机在拥有越来越多的外围设备的同时也变得更加小巧和高效。 继集成了摄像头和媒体播放器以后,现在的手机更是包含了 GPS 系统、加速计和触摸 屏。虽然这些硬件上的创新为软件开发提供了广泛的应用基础,但实际情况却不容乐观, 手机应用程序的开发已经落后于相应的硬件水平了。 1.1.1 不远的过去 过去,那些通常使用 C 或者 C++进行编程的开发人员必须理解在其上编写代码的特定 硬件。这些硬件通常是一个设备,但也可能是来自于同一家生产商的一系列设备。随着硬 件技术和移动互联网接入技术的发展,这种封闭的方法很难追赶硬件发展的步伐。 后来,人们开发出了像 Symbian 这样的平台,从而给开发人员提供了更广泛的目标用 户群(target audience)。在鼓励移动开发人员开发更加丰富的应用程序以便更高效地利用硬 件方面,这些系统比上述那种封闭的方法更加成功。 这些平台提供了一些访问设备硬件的接口,但是要求编写复杂的 C/C++代码,而且严 重依赖那些因难以使用而著称的专有 API。当开发那些必须运行在不同的硬件实现上的应 用程序以及使用特定的硬件功能(如 GPS)的应用程序时,这些困难就呈现在了开发人员面前。 近几年,移动开发的最大亮点在于引入了由 Java 承载(java-hosted)的 MIDlet。MIDlet 是在一个 Java 虚拟机上执行的,它把底层的硬件抽象出来,从而使开发人员可以开发出能 运行在多种硬件上的应用程序,只要这些硬件支持 Java 运行时(Java run time)就可以。遗憾 的是,这种便利是以对设备硬件的访问限制为代价的。 在移动开发中,通常第三方应用程序的硬件访问和执行权限与手机制造商编写的本机 应用程序的权限是不同的,而 MIDlet 则通常不具有这两种权限。 第 1 章 Android 简介 3 Java MIDlet 的引入扩大了开发人员的目标用户群,但是由于缺乏对低级硬件的访问权 限以及沙盒式的执行等原因,大部分移动应用程序都是运行在较小屏幕上的桌面程序或 Web 站点,而没有充分利用移动平台的固有移动性。 1.1.2 未来的前景 最近出现的一些手机操作系统设计理念的创新与突破,都是为了适应手机硬件日益强 大的计算能力,Android 也是在这样一种背景下应运而生的。现在,Windows Mobile 和 Apple 的 iPhone 为移动应用程序开发提供了一个功能更丰富、使用更简捷的开发环境。然 而,与 Android 不同,它们是构建在专有操作系统的基础上的,而专有操作系统通常使本 地应用程序具有比第三方创建的应用程序更高的优先级,并且限制了应用程序和本地手机 数据之间的通信,以及可以在其平台上发布的第三方应用程序。 Android 通过提供一个以开源的 Linux 内核为基础而构建的开放的开发环境,为移动应 用程序的开发提供了新机遇。通过一系列 API 库,所有应用程序都可以访问硬件,并且在 严格受控的条件下完全支持应用程序之间的交互。 在 Android 中,所有应用程序有相同的优先级。第三方和本地应用程序都使用相同的 API 进行编写,而且都在相同的运行时上执行。用户可以删除任何本地应用程序,并使用 相应的第三方应用程序对其进行代替,甚至连拨号程序和主屏幕都可以进行替换。 1.2 对 Android 的误解 作为对一个成熟领域破坏性的补充,不难理解为什么一些人会对 Android 具体是什么 这个问题存在很多疑惑。Android 不是: ● 一个 Java ME 实现 Android 应用程序是使用 Java 语言编写的,但是它们并不是 运行在一个 Java ME 虚拟机上的,而且已编译的 Java 类和可执行程序不能在不经 过修改的情况下就运行在 Android 上。 ● Linux 手机标准论坛(Linux Phone Stantards Forum,LiPS)或者开放移动联盟 (Open Mobile Alliance,OMA)的一部分 Android 运行在一个开源的 Linux 内核的 基础上。尽管它们的目标很相似,但是 Android 的完全软件栈方法和这些标准定义 组织的关注点是不同的。 ● 一个简单的应用层(如 UIQ 或者 S60) 尽管 Android 确实包含一个应用层,但是它 也描述了整个软件栈,这个软件栈包含了底层操作系统、API 库和应用程序本身。 ● 一个手机设备 Android 包含了一个移动设备制造商的参考设计,但是并不存在一 个“Android 手机”。相反,Android 是为了支持多种硬件设备而设计的。 ● Google 对 iPhone 的回应 iPhone 是由 Apple 公司发布的完全专有的硬件和软件 平台,而 Android 是由开放手机联盟( Open Handset Alliance,OHA )生产和支持的 一个开源的软件栈,是为了能在任何满足要求的手机上运行而设计的。现在 Google 已经生产了直接面向消费者的手机 Nexus 1,但是这只是 Android 平台下的一种硬 件实现而已。 Android 2 高级编程(第 2 版) 4 1.3 开放的移动开发平台 Google 的 Andy Rubin 把 Android 描述为: 为移动设备设计的第一个真正开放的综合平台,所有软件都能运行在手机上,从而消 除了阻碍移动创新的障碍(http://googleblog.blogspot.com/2007/11/wheres-my-gphone.html)。 概括地讲,Android 由 3 个组件构成: ● 一个针对移动设备的免费开源操作系统。 ● 一个用于创建移动应用程序的开源开发平台。 ● 运行 Android 操作系统以及为这种操作系统编写的应用程序的设备,特别是手机。 确切地讲,Android 由以下几个不可或缺且相互依赖的部分组成: ● 一个硬件参考设计,它描述了移动设备为了支持软件栈而需要具备的性能。 ● 一个 Linux 操作系统内核,它提供了与硬件之间的低级接口、内存管理和进程控制, 且全都为移动设备进行了优化。 ● 应用程序开发的开源库,包括 SQLite、WebKit、OpenGL 以及一个媒体管理器。 ● 用来运行和承载(host)Android 应用程序的运行时,包括 Dalvik 虚拟机和提供 Android 特定功能的核心库。为了在移动设备上使用,将其设计成为了小巧而高效 的运行时。 ● 一个把系统服务隐式地显示给应用层的应用程序框架,包括窗口管理器、位置管 理器、内容提供器、电话和点对点服务。 ● 一个用来承载(host)和启动应用程序的用户界面框架。 ● 作为软件栈的一部分发行的预装应用程序。 ● 用来开发应用程序的软件开发包,包括工具、插件和文档。 真正使 Android 引人注目的是它的开放哲学,这就保证了用户界面或者本地应用程序 的所有不足之处都可以通过编写一个扩展或者替代品来弥补。Android 为开发人员提供了 一个完全按照对样式、观感和功能的设想来设计手机界面和应用程序的机会。 1.4 自带的 Android 应用程序 Android 手机通常都带有一套预装的通用应用程序,包括但不限于以下几种: ● 一个电子邮件客户端。 ● 一个 SMS 管理应用程序。 ● 一个完整的个人信息管理(personal information management,PIM)套件,包括日历 和联系人列表。 ● 一个基于 WebKit 的 Web 浏览器。 ● 一个音乐播放器和图片查看器。 第 1 章 Android 简介 5 ● 一个照相机和视频录制应用程序。 ● 一个计算器。 ● 一个主屏幕。 ● 一个闹钟。 许多 Android 设备还提供了以下的 Google 移动应用程序: ● 用来下载第三方 Android 应用程序的 Android Market 客户端。 ● 一个功能丰富的移动 Google 地图应用程序,包括街道浏览(StreetView)、驾驶导航 (driving direction)、turn-by-turn 导航、卫星观察(satellite view)和交通路况(traffic conditions)。 ● Gmail 邮件客户端。 ● Google Talk 即时消息客户端。 ● YouTube 视频播放器。 自带的应用程序存储和使用的数据(如联系人详细信息)也可以被第三方应用程序使 用。与之相似,你所编写的应用程序也可以处理像来电或者新的 SMS 信息这样的事件。 新的 Android 手机上的可用应用程序可能会根据硬件制造商和(或)手机运营商或发行 商的不同而有所不同。 Android 的开源本质意味着运营商和 OEM 可以定制用户界面和与每个 Android 设备捆 绑在一起的应用程序。一些 OEM 已经这么做了,比如 HTC 的 Sense UI 、 Motorola 的 MotoBlur 和 Sony Ericsson 的自定义 UI。 需要注意,兼容设备的底层平台和 SDK 在各个 OEM 和运营商之间是一致的。用户界 面的样式和观感可能有所变化,但是应用程序在所有彼此兼容的 Android 设备中的功能是 一样的。 1.5 Android SDK 的特征 作为一个开发环境,Android 最吸引人之处在于它提供的 API。 作为一个与应用程序无关的平台,Android 允许你创建一些类似于本地应用程序的应 用程序。下面的列表选取了一些最值得注意的 Android 特征: ● 没有获得许可、发布或者开发费用以及批准发布的过程。 ● 可以访问 Wi-Fi 硬件。 ● 用于电话或者数据传输的 GSM、EDGE 和 3G 网络,允许接打电话或者收发 SMS 信息,还允许在移动设备之间发送或者检索数据。 ● 为像 GPS 这样的基于位置的服务设计了详尽的 API。 ● 完全的多媒体硬件控制,包括使用摄像头和麦克风进行回放和录制。 ● 用于使用加速计和罗盘等传感器硬件的 API。 ● 用于使用蓝牙技术进行点对点(P2P)数据传输的库。 ● IPC 消息传递。 ● 共享数据存储。 Android 2 高级编程(第 2 版) 6 ● 后台应用程序和进程。 ● 主屏幕小组件、Live Folder 和 Live Wallpaper ● 把应用程序搜索结果集成到系统搜索中的功能。 ● 一个集成的基于 WebKit 的开源 HTML5 浏览器。 ● 完全支持能够把地图控件集成到用户界面中的应用程序。 ● 专为移动设备进行优化的硬件加速图形,包括一个基于路径的 2D 图形库以及对使 用 OpenGL ES 2.0 的 3D 图形的支持。 ● 播放和录制各种音频、视频或者静态图像格式的媒体库。 ● 通过动态资源框架实现本地化。 ● 支持重用应用程序组件和取代本地应用程序的应用程序框架。 1.5.1 访问硬件(包括摄像头、GPS 和加速计) Android 包含了用来简化那些涉及到设备硬件开发的 API 库。这些 API 库可以保证不 必为不同的设备创建软件的特殊实现,因此,创建的 Android 应用程序就可以像预料中的 那样运行在所有支持 Android 软件栈的设备上。 Android SDK 包含了针对基于位置的服务(如 GPS)、摄像头、音频、网络连接、Wi-Fi、 蓝牙、加速计、触摸屏和电源管理的 API。第 11~14 章将详细讨论 Android 的一些硬件 API 的潜在用途。 1.5.2 自带的 Google 地图、地理编码和基于位置的服务 自带的地图支持使你可以开发出很多利用了 Android 设备的移动性的基于地图的应用 程序。Android 允许创建一些活动,在用户界面中包含 Google 地图,由于可以完全访问地 图,因此,可以通过程序对地图进行控制,还可以使用 Android 丰富的图形库对地图进行 注释。 Android 的基于位置的服务通过管理如 GPS 和 Google 的 GSM 基于蜂窝(cell-based)的 定位技术来确定设备当前的位置。这些服务对特定的位置检测技术进行了抽象,从而使你 可以指定最低要求(例如,精度或者花费),而不是选择特定技术。它也意味着,不管手机 设备支持什么样的技术,基于位置的应用程序都会正常运行。 为了把地图和位置联系起来,Android 包含了一个用于地理编码(geocoding)和逆地理编 码(reverse geocoding)的 API,从而可以使你找到一个地址所对应的地图坐标和一个地图位 置所对应的地址。 第 8 章将详细讨论如何使用地图、地理编码器(Geocoder)和基于位置的服务。 1.5.3 后台服务 Android 支持在后台运行不可见的应用程序和服务。 现代的手机本质上是一个多功能的设备,然而,它们有限的屏幕尺寸使得在任何时间 只能有一个交互式应用程序是可见的。不支持后台执行的平台会限制那些不需要你持续关 第 1 章 Android 简介 7 注的应用程序的生存能力。 后台服务允许你构建一些不可见的应用程序组件,它们不需要与用户进行直接交互就 能自动执行处理操作。后台执行允许应用程序被事件驱动,并且能够支持定期更新,这就 非常适用于监控游戏的得分或者市场价格,生成基于位置的警告,或者划分来电和 SMS 消息的优先级并进行预先筛选。 在第 9 章中将学习到如何高效地利用后台服务。 1.5.4 SQLite 数据存储和检索数据库 对于一个存储空间有限的小型设备而言,快速且高效的数据存储和检索功能是很必 要的。 Android 通过 SQLite 为每一个应用程序提供了一个轻量级的关系数据库。应用程序可 以利用这个托管的关系数据库引擎来安全高效地存储数据。 默认情况下,每一个应用程序的数据库都放在一个沙盒(sandbox)中,即它的内容只对 创建它的应用程序可见。但是,内容提供器提供了一种托管这些应用程序的数据库共享的 机制。 第 7 章将详细地讨论数据库和内容提供器。 1.5.5 共享数据和应用程序间通信 Android 使用三种技术来实现应用程序间的数据共享:通知(Notification)、意图(Intent) 和内容提供器(Content Provider)。 通知是以前移动设备提醒用户的标准方式。使用通知 API,可以触发音频报警,引起 震动,使设备的 LED 闪烁以及控制状态栏通知图标(这些内容将在第 9 章中讨论)。 意图提供了一种在应用程序内部和应用程序之间传递消息的机制。使用意图,可以在 系统范围内向其他应用程序广播一种期望的动作(例如,拨号或者编辑联系人),来让它们 进行处理。意图是 Android 中的一个重要的核心组件,第 5 章将进行详细阐述。 最后,内容提供器是一种将托管访问权限授予应用程序的私有数据库的方式。自带的 应用程序(如联系人管理器)的数据存储都作为内容提供器提供,这样就可以通过创建自己 的应用程序来读取或者修改这些存储的数据。第 7 章详细地讲解了内容提供器,包括自带 的提供器,并说明了如何创建和使用自己的提供器。 1.5.6 使用小组件、Live Folder 和 Live Wallpaper 润色主屏幕 通过使用小组件、Live Folder 和 Live Wallpaper,可以创建一些动态的应用程序组件, 然后可以利用它们在应用程序内提供一个窗口,或者在主屏幕上直接提供及时而有用的 信息。 如果为用户提供了一种在主屏幕上直接与应用程序交互的方法,那么他们就可以立即 访问感兴趣的信息,而不需要打开应用程序,而上述功能就需要你提供一种访问应用程序 Android 2 高级编程(第 2 版) 8 的快捷方式。 第 10 章将讨论如何为主屏幕创建应用程序组件。 1.5.7 广泛的媒体支持和 2D/3D 图形 越来越大的屏幕,越来越清晰的显示和越来越高的分辨率,让手机变成了理所当然的 多媒体设备。为了能够充分利用硬件功能,Android 为使用 2D 画布绘图和使用 OpenGL 的 3D 图形渲染提供了相应的图形库。 Android 也提供了处理静态图像、视频和音频文件的综合库,该库可处理 MPEG4、 H.264、MP3、AAC、AMR、JPG、PNG 和 GIF 格式的图像、视频和音频文件。 第 15 章将详细讲述 2D 和 3D 图形库,而第 11 章则涵盖了 Android 的媒体管理库的相 关内容。 1.5.8 优化的内存和进程管理 Android 的进程和内存管理有一点特殊。与 Java 和.NET 一样,Android 使用自己的运 行时和虚拟机来管理应用程序内存。但与 Java 和.NET 不同的是,Android 运行时还管理着 进程的生存期。Android 根据需要对进程进行暂停和结束操作来为更高优先级的应用程序 释放资源,从而保证高优先级应用程序的及时响应。 在此上下文环境中,正在与用户进行交互的应用程序将具有最高的优先级。既要保证 能对你的应用程序随时进行暂停或结束操作,又要保证应用程序能够保持实时响应与更新, 以及必要时在后台进行更新或重启——这在诸如手机平台等不允许应用程序控制其生存期 的应用环境中是非常重要的。 第 3 章将介绍更多关于 Android 应用程序生命周期的相关内容。 1.6 开放手机联盟简介 开放手机联盟(Open Handset Alliance,OHA)是由 50 多家技术公司组成的一个组织, 这些公司包括手机制造商、移动运营商和软件开发商。值得注意的是,诸如 Motorola、HTC、 T-Mobile 和 Qualcomm 等众多著名的移动技术公司也都纷纷加入了开放手机联盟。用它们 自己的话说,OHA 代表的是: 对开放原则的承诺、对未来的共同憧憬,以及把这种憧憬变为现实的具体实施计划。 它可以有力推动移动设备的创新,并且向消费者提供内容更丰富、资费更低廉且更美妙的 移动体验(http://www.openhandsetalliance.com/oha_faq.html)。 OHA 希望提供一个有利于移动开发创新的平台,该平台具有更快的速度和更高的品 第 1 章 Android 简介 9 质,而且不需要软件开发人员或者设备制造商支付费用,并希望以此向消费者提供更好的 移动软件体验。 1.7 Android 的运行环境 第一款 Android 手机——T-Mobile G1——于 2008 年 10 月在美国上市。到 2009 年年底, 已经有超过 26 个国家的 32 个运营商开始生产或宣布即将生产超过 20 种与 Android 兼容的 手机。 Android 手机操作系统并不是为某种特定的硬件实现而创建的,它的设计是面向各种 各样的硬件平台的,这些平台包括带有硬键盘的 WVGA 手机和带有电阻式触摸屏的 QVGA 设备等。 此外,由于得益于 Android 不收取许可费和其代码的完全开放性,手机制造商生产与 Android 兼容的手机产品或其他 Android 设备的成本得以大大降低。Android 平台在创建强 大的应用程序方面有很大的优势,因此,许多人期望这种优势可以鼓励手机制造商生产定 制程度越来越高的硬件。 1.8 从事移动开发的原因 现代智能手机和“超级手机”(包含手机通话功能的多功能设备,提供了功能丰富的 Web 浏览器、摄像头、多媒体播放器、Wi-Fi 和基于位置的服务)的出现从根本上改变了人 们使用移动设备以及访问 Internet 的方式。在许多国家,拥有手机的人数远远超出了拥有 计算机的人数。在 2009 年,使用手机上网的人数第一次超过了使用 PC 上网的人数。 现代智能手机日益流行,而费率统一并且价格相对较低的数据计划和 Wi-Fi 也越来越 普及,这都使得市场对高级移动应用程序的需求越来越大。 手机的普及以及我们使用手机的方式决定了它们是与 PC 完全不同的开发平台。在包 含了麦克风、摄像头、触摸屏、位置检测和环境传感器以后,手机实际上已经成为了人的 感知能力的扩展。 Android 用户平均安装和使用大约 40 个应用程序。从这一点上说,移动应用程序改变 了人们使用手机的方式。这就为应用程序开发人员提供了一个独特的机会,使他们能够创 建出动态而具有吸引力的新应用程序,并使这些应用程序变成人们的生活中不可或缺的一 部分。 1.9 从事 Android 开发的原因 如果你对移动开发有一些了解,那么你会很容易接受以下事实: ● Android 所能实现的许多功能也可以通过其他方法实现。 ● 但是使用那些方法进行实现却并不容易。 Android 是移动开发技术发展历程上的一个里程碑,是现代移动设备开发技术的基础 Android 2 高级编程(第 2 版) 10 上的一个移动应用程序框架。 使用简单而强大的 SDK,无需缴纳使用许可费,具有规范的文档和日益庞大的开发社 区,Android 的上述特点为移动开发人员提供了一个可以深刻改变人们移动应用生活的绝 佳机会。 从商业角度看,Android: ● 不要求获得 Android 开发人员认证。 ● 提供了 Android Market,可以帮助你发布应用程序并利用应用程序获利。 ● 没有针对应用程序发布的批准过程。 ● 允许你完全控制自己的品牌和对用户主屏幕进行访问。 1.9.1 推动 Android 普及的因素 Android 主要是面向开发人员的,因为 Google 和 OHA 坚信,只有先让开发人员能更 方便地开发出移动应用软件,才能使这些软件在消费者中广泛推广。 作为一个开发平台,Android 功能非常强大,而且易于使用,它使那些没有任何移动 开发经验的人员也可以方便快速地创建有用的应用程序。显而易见,富有创新性的 Android 应用程序将能够带动对可以运行这些应用程序的设备的需求,特别是当开发人员无法为 Android 以外的平台编写某些应用程序时更是如此。 对系统底层细节的开放访问通常有助于平台及基于该平台所开发的应用程序的流行。 Internet 本身固有的开放性和平台无关性让它在短短十年之内变成了拥有数十亿美元产业 的平台。在此之前,像 Linux 这样的开源操作系统和 Windows 操作系统所提供的强大的 API 接口使个人计算机迅速普及至寻常百姓家,同时也使神秘的计算机编程技术得以流行。 开放并且功能强大,这保证了任何有创意的想法都可以用最小的代价来实现。 1.9.2 Android 的独到之处 前面列出很多功能,如 3D 图形和本地数据库支持,在其他移动 SDK 上也有。下面的 这些内容是使 Android 能和其他平台区分开来的独特功能: ● Google Map 应用程序 手机上的 Google 地图已经非常流行了,Android 把 Google Map 作为一个原子的、可重用的控件提供给开发人员。MapView 小程序允许在用 户活动中显示、操作和注释 Google Map,以使用熟悉的 Google 地图接口来构建 基于地图的应用程序。 ● 后台服务和应用程序 后台服务允许创建使用事件驱动模型的应用程序,当其他 应用程序正在被使用时,或者手机处于待机状态时,这些应用程序将在后台自动 运行。它可能是一个流式引用播放器;也可能是一个关注股市动态的应用程序, 当投资出现重大波动的时候进行通知;还可能是一种服务,比如可以根据当前的 位置、时间和来电人的身份来改变铃声或者音量。 第 1 章 Android 简介 11 ● 共享数据和进程间通信 通过使用意图和内容提供器,Android 使应用程序可以交 换信息、执行处理和共享数据。也可以使用这些机制来利用本地应用程序提供的 数据和功能。为了降低这种开放策略带来的风险,每个应用程序的进程、数据存 储和文件都是私有的,除非使用一种完全基于权限的安全机制显式地和其他应用 程序进行共享,第 15 章将详细介绍这种机制。 ● 平等地创建所有应用程序 Android 并不会区别对待本地应用程序和第三方开发 的应用程序。这就给了消费者改变他们设备的样式和感观的前所未有的权力,允 许他们使用第三方应用程序完全取代每个本地应用程序,并且这些第三方应用程 序也能访问相同的底层数据和硬件。 ● 主屏幕小组件、Live Folder、Live Wallpaper 和快速搜索框 使用小组件、Live Folder 和 Live Wallpaper 可以从手机的主屏幕上创建应用程序内的窗口。快速搜索 框可以将应用程序的搜索结果直接整合到手机的搜索功能中。 1.9.3 改变移动开发格局 目前存在的移动开发平台在移动开发过程中产生了一种排外的氛围。无论是有意为 之,还是成本、复杂度或在开发本地应用程序时必须获得批准的原因,大部分手机在许多 年内都没有什么变化。 相比之下,Android 允许、甚至鼓励革命性的颠覆。作为一种消费设备,Android 手机 在销售的时候都会应客户的要求而预装一套新手机所必需具备的标准的核心应用程序,但 是它真正的强大之处在于可以让用户完全拥有改变手机外观、感觉和功能的能力。 Android 给开发者提供了一个很好的机会。所有的 Android 应用程序都是手机产品自身 的一部分,而不仅仅是运行在手机之上的沙盒中的软件。你不必开发那些运行在低功率设 备上的小屏幕版本的软件,而是可以编写那些能够改变人们使用手机的方式的移动应用 程序。 作为一个开源的开发框架,虽然 Android 仍然必须和已有的以及将来可能会出现的各 种移动开发平台竞争,但是它仍然具有自己的优势。当然,在移动开发过程中采用免费和 开放的方法,并且可以不受限制地访问手机的资源,是在正确的发展方向上向前迈出的一 大步。 1.10 开发框架简介 在做完了准备工作之后,现在开始讨论如何开发 Android 应用程序。Android 应用程序 使用 Java 作为编程语言进行编写,但不是用传统的 Java 虚拟机执行,而是用一个定制的 称为 Dalvik 的虚拟机执行。 本章的后面部分将介绍 Android 的框架,先从对 Android 软件栈技术的解释开始,然 后对 SDK 中包含的内容和 Android 库进行简单介绍,最后简单地了解一下 Dalvik 虚拟机。 每个 Android 应用程序都运行在它自己的 Dalvik 实例的一个进程中,它把内存管理和 进程管理的所有工作都交给 Android 运行时进行处理,Android 运行时在必要的时候会暂停 Android 2 高级编程(第 2 版) 12 和结束进程,从而更有效地管理资源。 Dalvik 和 Android 运行时位于一个 Linux 内核之上,由该 Linux 内核来处理低级的硬 件交互,包括驱动程序和内存管理,同时有一套 API 来提供所有对底层服务、功能和硬件 的访问。 1.10.1 开发包中的资源 Android 软件开发包(software development kit,SDK)包含了开发、测试和调试 Android 应用程序所需的所有东西。下载的 SDK 包含以下组件: ● Android API SDK 的核心是 Android API 库,它向开发人员提供了对 Android 栈 进行访问的方法。Google 也使用相同的库来开发本地应用程序。 ● 开发工具 为了让 Android 源代码变成可执行的 Android 应用程序,SDK 提供了多 个开发工具供编译和调试应用程序时使用。第 2 章将更加详细地讲述开发工具的相 关内容。 ● Android 虚拟设备管理器和模拟器 Android 模拟器是一个完全交互式的 Android 设备模拟器,并有多个皮肤可供选择。模拟器运行在模拟设备硬件配置的 Android 虚拟设备中。通过使用模拟器,可以了解应用程序在实际的 Android 设备上的外观 和运行情况。所有 Android 应用程序都运行在 Dalvik VM 中,所以软件模拟器是一 个非常好的环境。事实上,由于它的硬件无关性,它提供了比任何单一的硬件实 现都更好的独立测试环境。 ● 完整的文档 SDK 中包含了大量代码级的参考信息,详细地说明了每个包和类中 都包含什么内容以及如何使用它们。除了代码文档之外,Android 的参考文档还解 释了如何开始进行开发,并详细地解释了 Android 开发背后的基本原理。 ● 示例代码 Android SDK 包含了一些示例代码集,它们解释了使用 Android 的某些 可能性,以及一些用来强调如何使用每一个 API 功能的简单程序。 ● 在线支持 Android 迅速拥有了一个生机勃勃的开发社区。http://code.google.com/ android/groups 中的 Google Groups 是一个活跃的 Android 开发论坛,也是 Google 的 Android 开发人员经常去的论坛。网址为 http://www.stackoverflow.com/questions/ tagged/android 的 StackOverFlow 也是交流 Android 问题的一个热点区域。 Android 针对那些习惯于使用流行的 Eclipse IDE 的移动开发人员发布了一个特殊的插 件来简化工程创建,并把 Android 模拟器和调试工具紧密地集成到了 Eclipse 中。第 2 章将 详细介绍 ADT 插件的功能。 1.10.2 理解 Android 软件栈 Android 软件栈由图 1-1 中的元素组成,下面我们会更详细地对其进行解释。简单地说, 就是通过一个应用程序框架提供一个 Linux 内核和一个 C/C++库集合,而该应用程序框架 为运行时和应用程序提供服务,并对它们进行管理。 第 1 章 Android 简介 13 ● Linux 内核 核心服务(包括硬件驱动程序、进程和内存管理、安全、网络和电源 管理)都由一个 Linux 2.6 内核处理。内核还在硬件和软件栈的其他部分之间提供了 一个抽象层。 应用层 本地应用程序 (联系人、地图、浏览器等) 第三方应用程序 开发应用程序 应用程序框架 基于位置的服务 内容提供器 窗口管理器 活动管理器 包管理器 电话服务 P2P/XMPP 通知 视图 资源管理器 库 图形库 多媒体库 外观管理器 Android 运行时 Android 库 Dalvik 虚拟机 Linux 内核 硬件驱动程序 (USB、显示屏、蓝牙等) 电源管理 进程管理 内存管理 图 1-1 ● 库 运行在内核之上,Android 包含了各种 C/C++核心库(例如 libc 和 SSL),以及: • 用来回放音频和视频媒体的媒体库; • 用来管理显示的外观管理器; • 包含用于 2D 和 3D 图形的 SGL 和 OpenGL 的图形库; • 用于本地数据库支持的 SQLite; • 用于集成 Web 浏览器和 Internet 安全的 SSL 和 WebKit。 ● Android 运行时 Android 运行时可以让一个 Android 手机从本质上与一个移动 Linux 实现区分开来。由于 Android 运行时包含了核心库和 Dalvik 虚拟机,因此, 它是向应用程序提供动力的引擎,它和库一起形成了应用程序框架的基础。 • 核心库 虽然 Android 开发使用的是 Java 语言,但 Dalvik 并不是一个 Java 虚 拟机。Android 核心库提供了 Java 核心库以及 Android 特定库可用的大部分 功能。 • Dalvik 虚拟机 Dalvik 是一个基于寄存器的虚拟机,它已经被优化从而保证一 个设备可以高效地运行多个实例。它依赖 Linux 内核进行线程和底层内存管理。 Android 2 高级编程(第 2 版) 14 提示: 本书主要介绍的是如何使用 SDK 编写 Dalvik 支持的应用程序。如果你更倾 向于探索 Android 的 Linux 内核和 C/C++底层细节以及修改 Dalvik 或者底层的 其他东西,那么建议你看一下 Android Internals Google Group,网址是 http:// groups.google.com/group/android-internals。 虽然本书推荐在需要时尽量使用 NDK,但是并没有详细讨论如何使用 NDK。 ● 应用程序框架 应用程序框架提供了用来创建 Android 应用程序的类。它还对硬件 访问提供了一般抽象,并管理用户界面和应用程序资源。 ● 应用层 所有的应用程序,包括本地的和第三方的,都在应用层上使用相同的库 进行构建。应用层运行在 Android 运行时之内,并且使用了应用程序框架中可用的 类和服务。 1.10.3 Dalvik 虚拟机 Android 的一个关键元素就是 Dalvik 虚拟机。Android 使用定制的虚拟机来保证多个实 例可以高效地运行在一个设备上,而不是使用传统的 Java 虚拟机,比如 Java ME(Java Mobile Edition)。 Dalvik 虚拟机使用设备的底层 Linux 内核来处理基本的功能,包括安全、线程以及进 程和内存管理。编写直接运行在底层 Linux OS 上的 C/C++应用程序也是可以的,但大部分 情况下没有这个必要。 如果你的应用程序需要利用 C/C++的速度和效率,则可以使用 Android 提供的 Native Development Kit(NDK)。设计 NDK 的目的是允许使用 libc 和 libm 库以及对 OpenGL 的本 地访问创建 C++库。 所有 Android 硬件和系统服务访问都是使用作为中间层的 Dalvik 来加以管理的。通过 使用一个 VM 来承载应用程序的执行,开发人员就可以获得一个抽象层来保证他们永远都 不需要考虑特定的硬件实现。 Dalvik VM 执行 Dalvik 可执行文件,这种优化后的格式可以保证能最小限度地占用内 存。使用 SDK 提供的工具,可以把 Java 语言编译的类转换为.dex 可执行文件。第 2 章将 介绍如何创建 Dalvik 可执行文件的更多相关内容。 1.10.4 Android 应用程序架构 Android 架构鼓励组件重用,允许在规定的安全限制的访问管理之下向其他的应用程 序发布和共享活动、服务及数据。 使用可以替换联系人管理器或者电话拨号器的机制,同样可以公开自己的应用程序组 件,让其他开发人员创建新的 UI 前端和功能扩展,或者在它们的基础上构建应用程序。 下面的应用程序服务是所有 Android 应用程序的架构基础,它们提供了常用软件都会 第 1 章 Android 简介 15 使用到的框架: ● 活动管理器(Activity Manager) 控制活动的生命周期,包括对第 3 章中描述的活 动栈进行管理。 ● 视图(View) 用来为活动构建用户界面,第 4 章将讲述相关内容。 ● 通知管理器(Notification Manager) 如第 9 章所述,提供了一种一致的和非打断性 的机制来通知用户。 ● 内容提供器(Content Providers) 如第 7 章所述,让应用程序可以共享数据。 ● 资源管理器(Resource Manager) 如第 3 章所述,支持像字符串和图形这样的非 代码资源的具体化。 1.10.5 Android 库 Android 提供了大量的 API 供开发使用。要想了解 Android SDK 中包含的包的完整列 表,可以参考 http://developer.android.com/reference/packages.html 上提供的文档。 Android 是针对大量的移动硬件设计的,所以要注意,一些高级或可选 API 的适用性 及实现可能因 Android 设备而异。 1.11 小结 如本章所述,虽然现代手机上的硬件功能有了重大的发展,但是相应的可用软件的发 展却相对滞后了。难以使用的开发包、特定于硬件的 API 和缺乏开放性都阻碍了移动软件 的创新。 Android 向开发人员提供了为移动设备开发新颖的应用程序的机会,而且不存在与现 存的那些私有移动开发框架相关的限制。 本章展示了完整的 Android 软件栈,它不仅包括应用层和开发工具包,而且还包括 Dalvik 虚拟机、一个定制的运行时、核心库以及 Linux 内核。上述所有内容都可以作为开 源的资源而获得。 本章还介绍了: ● 具有更多硬件功能的手机带动了对可以让开发人员更好地利用这些功能的工具的 需求。 ● 在使用 Android 的过程中,开发人员可用的某些功能,包括本地地图支持、硬件访 问、后台服务、进程间的消息传递、共享数据库以及 2D 及 3D 图形。 ● 所有的 Android 应用程序具有相同的优先级,允许用户用一个应用程序完全取代另 一个应用程序,甚至可以取代核心的本地应用程序。 ● Android SDK 包含了开发人员工具、API 和完整的文档。 第 2 章将从下载和安装 Android SDK 开始,学习如何在 Eclipse 中建立 Android 开发环境。 在创建第一个 Android 应用程序之前,你将学习如何使用 Android 开发人员工具插件 来简化开发、测试和调试 Android 应用程序的过程。 在学习了 Android 应用程序的组成之后,我们将介绍可以创建的不同类型的应用程序, Android 2 高级编程(第 2 版) 16 以及在为移动设备开发应用程序时应该考虑到的一些设计问题。 第 1 章 Android 简介 17 意图、广播接收器、Adapter 和 Internet 本章主要内容 ● 意图简介 ● 使用隐式和显式意图启动新的活动和子活动 ● 意图过滤器和意图解析 ● 使用 linkify ● 意图、广播动作和广播接收器 ● 使用 Adapter 将数据绑定到视图中 ● 在 Android 中使用 Internet ● 如何创建和使用对话框 乍一看,本章的各个主题之间好像并没有什么共同点;但实际上,它们都代表了连接 应用程序及其组件的纽带。 大部分平台上的移动应用程序都运行在各自的沙盒之中。它们彼此独立,而且它们与 系统硬件以及本地组件之间的交互受到严格限制。Android 应用程序也位于沙盒之中,但 是它们可以使用意图、广播接收器、Adapter、内容提供器以及 Internet 来摆脱束缚。 在本章,将会了解意图。意图可能是 Android 开发中最独特、最重要的概念。你将学 习如何使用它们在应用程序和应用程序组件之间广播数据,以及如何使用它们显式地或通 5 第 章 Android 2 高级编程(第 2 版) 18 过运行时迟绑定启动活动或服务。 通过使用隐式的意图,将学会如何请求在一条数据上执行某个动作,让 Android 决定 哪个应用程序组件可以最好地满足该请求。 广播意图用来在系统范围内公布应用程序事件。你将学到如何传递这些广播以及如何 使用广播接收器来接收它们。 还将研究 Adapter,并学习如何使用它们将表现层和数据源绑定到一起,还会了解到对 话框机制。 在学习了传递和使用本地数据的这些机制之后,还将了解 Android的Internet连接模型, 以及一些用来分析 Internet 数据反馈的 Java 技术。 然后会使用一个地震监控示例来说明如何把所有的这些功能组合到一起。这个地震监 控示例只是一个基础,在后面的章节中将会继续对其进行改进和扩展。 5.1 意图简介 意图是一种消息传递机制,可以在应用程序内使用,也可以在应用程序间使用。意图 可以用于: ● 声明你的意图,即启动活动或服务来执行一个动作的意图,通常需要使用特定的 数据,或者对特定的数据执行动作。 ● 广播某个事件(或动作)已经发生。 ● 显式启动一个特定的服务或活动。 意图支持 Android 设备上安装的任意应用程序组件之间的交互,不管它们是哪个应用 程序的一部分都是如此。这就把设备从一个包含相互独立的组件集合的平台变成了一个互 联的系统。 意图最常见的一个用法是显式地(通过指定要加载的类)或者隐式地(通过请求对一条 数据执行某个动作)启动新的活动。在后一种情况中,动作不一定由调用应用程序中的活动 执行。 意图也可以用来在系统范围内广播消息。任何应用程序都可以注册一个广播接收器来 监听和响应这些广播的意图。这样就可以基于内部的、系统的或者第三方应用程序的事件 创建事件驱动的应用程序。 Android 通过广播意图来公布系统事件,比如网络连接状态或者电池电量的改变。本 地 Android 应用程序(如拨号程序和 SMS 管理器)简单地注册监听特定的广播意图(例如 “来 电”或者“接收 SMS 消息”)的组件,并作出相应的响应。 使用意图来传播动作(甚至在同一个应用程序内传播动作)是一条基本的 Android 设计 原则。它鼓励组件之间的分离,允许无缝地替换应用程序元素。它还提供了一个简单的用 于扩展应用程序功能的模型的基础。 5.1.1 使用意图来启动活动 意图最常见的用途是绑定应用程序组件。意图可以用来启动活动并在应用程序内的活 第 1 章 Android 简介 19 提示: 这一部分给出的说明是关于启动新的活动的,但是这些相同的规则通常也 适用于服务。第 9 章将会讲述关于启动(和创建)服务的详细信息。 动之间进行转换。 要打开一个活动,可以调用 startActivity,并传递给它一个意图,如下面的代码所示: startActivity(my Intent); 意图可以显式地指定要打开的活动类,或者包含一个活动必须执行的动作。在后面一 种情况中,运行时将会使用一个称为“意图解析(intent resolution)”的过程来动态选择要打 开的活动。 startActivity 方法会查找并启动一个与意图最匹配的活动。 如果使用 startActivity,则在新启动的活动完成之后,应用程序不会接收到任何通知。 要想跟踪来自打开的窗口的反馈,可以使用下面详述的 startActivityForResult 方法。 1. 显式启动新活动 在第 2 章中已经知道了应用程序是由多个相互关联的屏幕(活动)组成的,它们必须包 含在应用程序的清单中。要连接它们,可能需要显式地指定要打开哪个活动。 要显式地选择要启动的活动类,可以创建一个新的意图来指定当前的应用程序上下文 以及要启动的活动类。然后把这个意图传递给 startActivity,如程序清单 5-1 所示。 程序清单 5-1 显式启动一个活动 Intent intent = new Intent(MyActivity.this, MyOtherActivity.class); startActivity(intent); 在调用 startActivity 之后,新的活动(本例中是 MyOtherActivity)将会被创建,并变为可 见的和活动的状态,同时移动到活动栈的顶部。 调用新活动的 finish 或按下设备的返回按钮将关闭该活动,并把它从栈中移除。或者, 开发人员可以通过调用 startActivity 导航到前一个活动,或另一个活动。 2. 隐式的意图和运行时迟绑定 隐式的意图提供了一种机制,可以让匿名的应用程序组件响应动作请求。这意味着可 以要求系统启动一个可执行给定动作的活动,而不必知道哪个应用程序或活动将执行该 动作。 当构建一个新的隐式的意图供 startActivity 使用的时候,需要指定一个要执行的动作, 另外,也可以提供执行那个动作需要的数据的 URI。还可以通过向意图添加附近信息来向 目标活动发送额外的数据。 Android 2 高级编程(第 2 版) 20 当使用这个意图来启动一个活动时,Android 将在运行时把它解析为最适合在指定的 数据类型上执行所需动作的类。这就意味着可以创建使用其他应用程序功能的项目,而不 必提前确切知道是哪个应用程序提供了这种功能。 例如,如果希望让用户从应用程序中打电话,那么可以实现一个新的拨号程序,也可 以使用一个隐式的意图来请求一个在电话号码(表示为一个 URI)上执行动作(拨号),如程序 清单 5-2 所示。 程序清单 5-2 隐式启动一个活动 if (somethingWeird && itDontLookGood) { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-2368")); startActivity(intent); } Android 会解析这个意图,并启动一个新的活动,该活动会提供对这个电话号码进行 拨号的动作——在这个例子中,就是拨号活动。 如果多个活动都能够执行指定的动作,则会向用户呈现各种选项。本章后面将详细讨 论意图解析的完整过程。 许多本地应用程序都提供了处理对特定的数据执行动作的组件。第三方应用程序(包括 你自己的应用程序)也可以通过注册来支持新的动作,或者提供本地动作的可替换组件。本 章后面的部分将会介绍一些本地活动,以及如何注册自己的活动来支持它们。 3. 从活动返回结果 通过 startActivity 启动的活动独立于其父活动,并且在关闭时不会提供任何反馈。 除此以外,还可以把活动作为与其父活动相连接的子活动启动。当关闭子活动时,它 会触发其父活动内的一个事件处理程序。对于一个活动为另一个活动提供数据输入(比如用 户从一个列表中选择某一项)的情况,子活动特别适用。 子活动只是以一种不同的方式启动的活动。因此,必须在应用程序清单中注册它们—— 事实上,在清单中注册的任何活动都可以作为子活动打开,包括系统活动或第三方应用程 序的活动。 启动子活动 startActivityForResult 的工作方式和 startActivity 相似,但是有一个重要的区别。除了 使用显式或隐式意图来决定启动哪个活动以外,还需要传入一个请求码。这个值将在后面 用于唯一标识返回了结果的子活动。 程序清单 5-3 显示了启动一个子活动的代码。 程序清单 5-3 启动一个子活动以返回结果 private static final int SHOW_SUBACTIVITY = 1; Intent intent = new Intent(this, MyOtherActivity.class); startActivityForResult(intent, SHOW_SUBACTIVITY); 第 1 章 Android 简介 21 类似于常规活动,也可以隐式或显式地启动子活动。程序清单 5-4 通过使用隐式意图 启动一个新的子活动来选取联系人。 程序清单 5-4 隐式启动一个活动以返回结果 private static final int PICK_CONTACT_SUBACTIVITY = 2; Uri uri = Uri.parse("content://contacts/people"); Intent intent = new Intent(Intent.ACTION_PICK, uri); startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY); 返回结果 当准备好返回子活动时,可以在调用 finish 以前调用 setResult,以便向调用活动返回 一个结果。 setResult 方法有两个参数:结果码和表示为意图的结果本身。 结果码是运行子活动的结果——通常是 Activity.RESULT_OK 或者 Activity.RESULT_ CANCELED。在某些环境下,可能希望使用自己的响应码(response code)来处理应用程序 特定的选择;setResult 支持任意的整数值。 作为结果返回的意图通常包含某段内容(比如选择的联系人、电话号码或媒体文件)的 URI 和用于返回附加信息的额外信息。 程序清单 5-5 来自于一个子活动的 onCreate 方法,展示了一个 OK 按钮和一个 Cancel 按钮如何向调用它的活动返回不同的结果。 程序清单 5-5 创建新的共享参数 Button okButton = (Button) findViewById(R.id.ok_button); okButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Uri data = Uri.parse("content://horses/" + selected_horse_id); Intent result = new Intent(null, data); result.putExtra(IS_INPUT_CORRECT, inputCorrect); result.putExtra(SELECTED_PISTOL, selectedPistol); setResult(RESULT_OK, result); finish(); } }); Button cancelButton = (Button) findViewById(R.id.cancel_button); cancelButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { setResult(RESULT_CANCELED, null); finish(); } Android 2 高级编程(第 2 版) 22 提示: 如果子活动非正常地关闭或者在关闭之前没有指定结果码,那么结果码就 是 Activity.RESULT_CANCELED。 }); 如果用户通过按下设备的返回键关闭活动,或者在调用 finish 以前没有调用 setResult, 那么结果码将被设为 RESULT_CANCELED,结果意图将被设为 null。 处理子活动结果 当一个子活动关闭的时候,它会触发其调用活动的 onActivityResult 事件处理程序。可 以通过重写这个方法来处理从子活动返回的结果。 onActivityResult 接受多个参数: ● 请求码 请求码用来启动返回子活动。 ● 结果码 子活动生成的结果码用来说明结果。它可以是任何整数值,但是一般情 况下都是 Activity.RESULT_OK 或者 Activity.RESULT_CANCELED。 ● 数据 意图用来包装所有返回的数据。根据子活动目标的不同,它可能会包含代 表选定内容的 URI。另外,子活动可以使用 extras 机制,作为基本值返回额外的 信息。 程序清单 5-6 实现了一个活动的 onActivityResult 事件处理程序。 程序清单 5-6 实现一个 onActivityResult 事件处理程序 private static final int SHOW_SUB_ACTIVITY_ONE = 1; private static final int SHOW_SUB_ACTIVITY_TWO = 2; @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode) { case (SHOW_SUB_ACTIVITY_ONE) : { if (resultCode == Activity.RESULT_OK) { Uri horse = data.getData(); boolean inputCorrect = data.getBooleanExtra(IS_INPUT_CORRECT, false); String selectedPistol = data.getStringExtra(SELECTED_PISTOL); } break; } case (SHOW_SUB_ACTIVITY_TWO) : { if (resultCode == Activity.RESULT_OK) { // TODO:处理 OK 单击 第 1 章 Android 简介 23 提示: 在下面的部分中,我们将会介绍意图过滤器,到时候将学习如何把自己的 活动注册为这些动作的处理程序。 } break; } } } 4. 本地 Android 动作 本地 Android 应用程序也可以使用意图来启动活动和子活动。 下面的不完整列表列出了某些本地动作,它们都是 Intent 类中的静态字符串常量。在 创建隐式的意图来启动应用程序内的活动或者子活动的时候,可以使用这些动作(称为活 动意图)。 ● ACTION_ANSWER 打开一个处理来电的活动,目前这个动作是由本地电话拨号 程序进行处理的。 ● ACTION_CALL 打开一个电话拨号程序,并立即使用意图 URI 所提供的号码拨 打一个电话。通常,如果可能的话,使用 ACTION_DIAL 是一种更好的方式。 ● ACTION_DELETE 启动一个活动,允许删除意图的数据 URI 中指定的数据。 ● ACTION_DIAL 打开一个拨号程序,拨打意图 URI 所提供的号码。默认情况下, 这是由本地 Android 电话拨号程序进行处理的。拨号程序可以规范化大部分号码样 式,例如,tel:555-1234 和 tel:(212)555 1212 都是有效的号码。 ● ACTION_EDIT 请求可以编辑指定的意图 URI 中的数据的活动。 ● ACTION_INSERT 打开一个能够在意图 URI 指定的光标处插入新的条目的活动。 当作为子活动调用的时候,它应该返回一个指向新插入条目的 URI。 ● ACTION_PICK 启动一个子活动,它可以让你从意图 URI 指定的内容提供器中选 择一个条目。当关闭的时候,它应该返回所选择的条目的 URI。启动的活动跟选 择的数据有关,例如,传递 content://contacts/people 将会调用本地联系人列表。 ● ACTION_SEARCH 启动用于执行搜索的活动。可以使用 SearchManager.QUERY 键把搜索词作为一个意图的附加数据中的字符串来提供。 ● ACTION_SENDTO 启动一个活动来向意图 URI 所指定的联系人发送一条消息。 ● ACTION_SEND 启动一个活动,该活动会发送意图中指定的数据。接收人需要由 解析的活动来选择。使用 setType 可以设置要传输的数据的 MIME 类型。 数据本身应该根据它的类型,使用 EXTRA_TEXT 或者 EXTRA_STREAM 存储为 附加数据。在 E-mail 的情况下,本地 Android 应用程序也可以使用 EXTRA_EMAIL、 EXTRA_CC、EXTRA_BCC 和 EXTRA_SUBJECT 键来接收附加数据。应该只使用 ACTION_SEND 动作向远程接收人(而不是设备上的另外一个应用程序)发送数据。 Android 2 高级编程(第 2 版) 24 提示: 除了这些活动动作之外,Android 还包含了很多广播动作,它们用来创建广 播意图以公布系统事件。本章后面将对这些广播动作进行详细讲述。 ● ACTION_VIEW 这是最常见的通用动作。视图要求以最合理的方式查看意图 URI 中提供的数据。不同的应用程序将会根据所提供的数据的 URI 模式来处理视图请 求。一般情况下,http:地址将会打开浏览器,tel:地址将会打开拨号程序以拨打该 号码,geo:地址会在 Google 地图应用程序中显示出来,而联系人信息将会在联系 人管理器中显示出来。 ● ACTION_WEB_SEARCH 打开一个活动,根据意图 URI(通常是浏览器)中提供的 文本执行 Web 搜索。 5.1.2 使用意图过滤器为隐式意图提供服务 如果一个意图是对在某个数据集上执行的动作的请求,那么 Android 是如何知道使用 哪个应用程序(和组件)来响应这个请求的呢? 意图过滤器用来将活动、服务和广播接收器注册为可以对一类特定的数据执行操作。 意图过滤器还可以用于将广播接收器注册为对广播给定的动作或事件感兴趣。 应用程序组件通过使用意图过滤器声明,它们可以响应设备上安装的任意应用程序的 动作请求。 要把一个应用程序组件注册为意图处理程序,可以使用意图过滤器节点中的以下标签 (以及相关的属性)向组件的清单节点中添加一个 intent-filter 标签: ● action 使用 android:name 属性来指定要为之服务的动作的名称。每个意图过滤 器都必须有且仅有一个 action 标签。动作必须是自描述的唯一字符串,所以最好的 做法是使用基于 Java 的包命名约定的命名系统。 ● category 使用 android:category 属性来指定应该在哪种环境下为动作提供服务。 每一个意图过滤器标签都可以包含多个 category 标签。既可以指定自己的 category, 也可以使用 Android 提供的标准值,如下所示: • ALTERNATIVE ALTERNATIVE 可以把这个动作指定为在特定数据类型上 执行的默认动作的可选项。例如,一个联系人的默认动作是查看其信息,而可 选的动作则是对其进行编辑。 • SELECTED_ALTERNATIVE 与 ALTERNATIVE 相似,但是 ALTERNATIVE 总 是使用后面将描述的意图解析解析为一个动作,而当要求有很多种可能性的时 候,则可以使用 SELECTED_ALTERNATIVE。在本章后面可以看到,意图过 滤器的一种用法就是使用动作帮助动态填充上下文菜单。 • BROWSABLE 指定一个在浏览器内部可用的动作。当一个意图从浏览器内部 触发的时候,它总是会包含 BROWSABLE。如果想让应用程序响应浏览器内触 发的动作(例如,截获指向特定网站的链接),那么必须包含 BROWSABLE。 第 1 章 Android 简介 25 • DEFAULT 通过设置这个类型可以使一个组件成为意图过滤器内指定的数据 类型的默认动作。对于那些使用一个显式的意图启动的活动,这个类型也是很 有必要的。 • GADGET 通过设置 GADGET,可以指定这个活动可以嵌入到另一个活动中 执行。 • HOME 通过将一个意图过滤器的类型设置为 HOME,而不指定一个动作,就 可以把它作为本地主屏幕的可选项。 • LAUNCHER 使用这个类型会让一个活动出现在应用程序的启动器中。 ● data data 标签允许指定组件可以执行的数据类型;根据情况,也可以包含多个数 据标签。可以使用以下属性的任意组合来指定你的组件所支持的数据: • android:host 指定一个有效的主机名(如 google.com)。 • android:mimetype 允许指定组件可以处理的数据类型。例如,将匹配所有的 Android 游标。 • android:path 指定 URI 的有效路径(如/transport/boats)。 • android:port 指定主机的有效端口。 • android:scheme 要求一种特定的模式(如 content 或者 http)。 程序清单 5-7 展示了一个活动的意图过滤器,它将执行 SHOW_DAMAGE 动作,这个 动作既可以是主要的,也可以是可选的(在第 6 章中将会创建有关地震的内容)。 程序清单 5-7 将活动注册为一个意图接收器 1. Android 如何解析意图过滤器 当使用 startActivity 的时候,传入的隐式意图会被解析为一个单一的活动。如果有多 个活动可以对指定的数据执行给定的动作,那么将向用户呈现一个可选项列表。 决定启动哪一个活动的过程称为意图解析。意图解析的目标是使用以下步骤来找出最 匹配的意图过滤器: (1) Android 把所有来自已安装的包中的可用的意图过滤器放到一个列表中。 (2) 那些与解析意图时相关联的动作或类型不匹配的意图过滤器将会从列表中移除。 a. 如果意图过滤器包含了指定的动作,或者没有指定动作,那么就认为动作匹配了。 只有在意图过滤器包含了一个或者多个动作,其中却没有任何一个动作和意图指定的动作 Android 2 高级编程(第 2 版) 26 相匹配时,才认为动作匹配不成立。 b. category 匹配更加严格。意图过滤器必须包含待解析的意图中的所有 category。一 个没有指定 category 的意图过滤器只能和没有任何 category 的意图相匹配。 (3) 最后,意图的数据 URI 的每一个部分都和意图过滤器的 data 标签进行比较。如果 意图过滤器定义了模式、host/authority、path 或者 MIME 类型,那么这些值就要和意图的 URI 比较。任何不匹配都会把意图过滤器从列表中移除。没有指定数据值的意图过滤器将 会和所有的意图数据值匹配。 a. MIME 类型是指要匹配的数据的类型。当匹配数据类型时,可以使用通配符来匹配 子类型(例如,earthquake/*)。如果意图过滤器指定了一种数据类型,那么它必须匹配该意 图;如果不指定数据类型,则它会和所有的意图匹配。 b. 模式是 URI 的“协议”部分——例如,http:、mailto:或者 tel:。 c. 主机名或者“data authority”是 URI 位于模式和路径之间的部分(例如,www.google. com)。主机名要想匹配,就必须也通过意图过滤器的模式。 d. 数据路径(data path)是 authority 之后的内容(例如,/ig)。只有在数据标签的模式和主 机名标签部分也匹配的时候,路径才能匹配。 (4) 当隐式启动一个活动的时候,如果这个过程解析出多个组件,那么所有可能匹配 的组件都会呈现给用户。 本地 Android 应用程序组件被解析的方式与第三方应用程序组件被解析的方式是完全 相同的。它们并没有更高的优先级,并且可以完全被新的活动取代,而这些新的活动声明 了可以为相同的动作请求提供服务的意图过滤器。 2. 在活动内找到和使用启动意图 当通过隐式意图启动应用程序组件时,它需要找出要执行的动作和对哪些数据执行动作。 可以通过调用 getIntent 方法(通常位于 onCreate 方法中)来提取用于启动组件的意图, 如程序清单 5-8 所示。 程序清单 5-8 在子活动中找到启动意图 @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); Intent intent = getIntent(); } 可以使用 getData 和 getAction 方法来找到与意图相关联的数据和动作。可以使用类型 安全的 getExtra 方法来提取存储在其 extras bundle 中的额外信息。 String action = intent.getAction(); Uri data = intent.getData(); 第 1 章 Android 简介 27 提示: 这个例子的实用价值有待考虑。因为 Android 已经提供了一个用来从一个 列表中选择一个联系人的意图过滤器,它可以在一个隐式的意图中使用 content://contacts/people/URI 来进行调用。因此,这个练习的目的只是为了说 明这种形式,即使这个特定的实现没有任何用处。 3. 传递责任 可以使用 startNextMatchingActivity 方法将处理动作的责任传递给次最佳匹配的应用 程序组件,如程序清单 5-9 所示。 程序清单 5-9 传递意图接收器处理 Intent intent = getIntent(); if (isDuringBreak) startNextMatchingActivity(intent); 这允许为应用程序添加额外的条件,用来限制它们在基于意图过滤器的意图解析过程 之外的使用。 在某些情况下,当组件把意图传递给下一个本地处理程序之前,它可能希望执行某些 处理,或者给用户提供一个选择。 4. 选择一个联系人的示例 在这个例子中,将创建一个新的活动来为联系人数据的 ACTION_PICK 动作提供服务。 它显示了联系人数据库中的每一个联系人,而且在关闭并且将其 URI 返回给调用它的活动 之前,用户可以选择其中的一个联系人。 (1) 创建一个新的 ContactPicker 项目,其中包含一个 ContactPicker 活动。 package com.paad.contactpicker; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.Contacts.People; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.AdapterView.OnItemClickListener; public class ContactPicker extends Activity { @Override public void onCreate(Bundle icicle) { Android 2 高级编程(第 2 版) 28 super.onCreate(icicle); setContentView(R.layout.main); } } (2) 通过修改 main.xml 布局资源来包含一个单一的 ListView 控件。后面将使用这个控 件来显示联系人。 (3) 创建一个新的包含一个单独的 TextView 的 listitemlayout.xml 资源。它将用来在列 表视图中显示每个联系人。 (4) 返回到 ContactPicker 活动中。重写 onCreate 方法,并从调用意图中提取出数据路径。 @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); Intent intent = getIntent(); String dataPath = intent.getData().toString(); a. 为存储在联系人列表中的人创建一个新的数据 URI,并使用 SimpleCursorArrayAdapter 把它绑定到列表视图上。 第 1 章 Android 简介 29 提示: SimpleCursorArrayAdapter 允许向视图分配内容提供器所使用的游标数 据。这里并没有关于它的更多注释,但是本章后面的部分会更详细地解释它。 final Uri data = Uri.parse(dataPath + "people/"); final Cursor c = managedQuery(data, null, null, null); String[] from = new String[] {People.NAME}; int[] to = new int[] { R.id.itemTextView }; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.listitemlayout, c, from, to); ListView lv = (ListView)findViewById(R.id.contactListView); lv.setAdapter(adapter); b. 向列表视图中添加一个 onItemClickListener。当从列表中选择一个联系人时应该将 该条目的路径返回给调用活动。 lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int pos, long id) { // 把游标移动到选定的项。 c.moveToPosition(pos); // 提取行 id。 int rowId = c.getInt(c.getColumnIndexOrThrow("_id")); // 构建结果 URI。 Uri outURI = Uri.parse(data.toString() + rowId); Intent outData = new Intent(); outData.setData(outURI); setResult(Activity.RESULT_OK, outData); finish(); } }); c. 关闭 onCreate 方法: } (5) 修改应用程序的清单,并替换活动的 intent-filter 标签以添加对在联系人数据上进 行的选择动作的支持。 Android 2 高级编程(第 2 版) 30 (6) 至此就完成了子活动。要对其进行测试,可以创建一个新的测试工具 ContentPickerTester 活动。创建一个新的布局资源——contentpickertester.xml,它包含了一个用来显示选中的联 系人的 TextView 和一个用来启动子活动的 Button。
还剩106页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

i_google

贡献于2013-05-12

下载需要 5 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf