开始之前
本教程介绍如何在 Eclipse 环境中进行 Android 应用程序开发,包括两个示例应用程序。第一个示例是一个基本的应用程序,涉及构建和调试的所有阶段。第二个应用程序示例涉及比较复杂的 Android 特性,包括联系人搜索和 Google Maps 地址查找。要想从本教程获得最大收益,具备移动开发经验会有帮助,但不是必需的。开发 Android 应用程序需要 Java™ 编程技能,但是对于本教程不是必需的。
我们为什么要关注 Android?有两个原因使 Android 成为重要的平台。首先,Google 引入了 Android,它在很短时间内就获得了市场的关注。Google 正在进军移动市场。它在这个市场上采取的第一个行动就是发布 Android 和 Open Handset Alliance,这是一个令人印象深刻的起点。第二,Android 不仅仅是另一种包含电话、菜单和触摸屏功能的移动平台。您将在本教程中了解到,Android 提供了一种不同的应用程序开发方法。由于可以对请求的操作和代码进行运行时绑定,Android 的体系结构支持高度可定制的软件环境。无论是考虑市场因素还是 Android 的技术方面,它都是一个值得研究的平台。
本教程分为以下几节:
- Android 基础知识和必需的工具
- Android Software Developer Kit
- 构建和调试 SaySomething Android 应用程序
- 创建内容提供器和 Google Maps 应用程序
本教程需要结合使用几种技术。
-
Eclipse 平台
- Eclipse 是一个运行插件的平台。您应该安装 Eclipse Classic 的最新版本(本教程使用 V3.3.1)。
-
Android Developer Tools
- 按照 安装 Android SDK 中的说明安装 Android Developer Tools(Eclipse 插件)。
-
源代码
-
本教程中的源代码片段包括:
- AndroidManifest.xml(片段)— 这个文件是 Android 应用程序的应用程序部署描述符。
-
IntentReceiver
— 演示IntentReceiver
的实现,这个类处理 AndroidManifest.xml 文件中IntentFilter
标记所公布的 intent。 - SaySomething.java — 实现一个 Android 活动,这是本教程的示例应用程序的主要入口点。
- Main.xml — 这个文件包含 Android 活动所用的视觉元素或资源。
- R.java — 这个文件是由 Android Developer Tools 自动生成的,它把视觉资源 “连接” 到 Java 源代码。
- AndroidManifest.xml(完整)— 这是完整的 AndroidManfest.xml 文件,包含每个重要元素的描述。
- MobileServiceCallContacts.java — 这个文件包含的代码显示联系人并对用户输入做出反应,执行 Google Maps 地址查找。
Android 简介
在讨论 Eclipse 插件和开发 Android 应用程序之前,我们先看看 Android 的体系结构和一些重要的术语,这会对本教程后面的讨论和您自己构建 Android 应用程序有帮助。
在 Eclipse 环境中开发 Android 应用程序需要了解 Eclipse 环境和 Android 平台的知识。了解以下术语会有助于用 Eclipse 插件开发 Android 应用程序。
-
Open Handset Alliance
- 这是一个由 Google 公司主导的组织,它由许多公共和私人组织组成。
-
Android
- 这是 Open Handset Alliance 的主打产品。它是一种针对移动设备的开放源码操作环境。
-
模拟器
- 模拟另一个系统的软件工具 — 这常常是在个人计算机(IBM®、Mac、Linux®)上运行的一个环境,它模拟另一个环境,比如移动计算设备。
-
Linux
- 一种开放源码的操作系统内核,许多计算平台都使用这种操作系统,包括服务器、桌面计算机、网络设备和移动计算设备。Android 在 Linux 内核上运行。
-
Dalvik Virtual Machine
- Dalvik VM 是 Android 产品组合中的一种操作环境,它在运行时解释应用程序代码。Dalvik VM 与 Java VM 相似,但是两者不兼容。
Android 是一种针对移动平台的开放源码操作系统。到编写本教程时,它是一种纯软件的平台,没有可用的硬件设备。
Android 平台被称为一个产品组合,因为它是一系列组件的集合,包括:
- 基于 Linux 内核的操作系统
- Java 编程环境
- 工具集,包括编译器、资源编译器、调试器和模拟器
- 用来运行应用程序的 Dalvik VM
简要介绍了 Android 平台的体系结构之后,我们来从市场的角度看看这个平台的一些重要特性。
自从 Android 和最初的 SDK 发布以来,计算机技术新闻界一直非常关注 Android。Android 之所以重要主要有两个原因。
Android 是 Google 进军移动市场的主要行动。移动应用程序领域竞争激烈,新的竞争者很难涉足。Google 拥有大量资源和强大的品牌实力,有能力涉足任何市场。Google 进军移动市场已经好几年了。Android 原来属于另一家公司,Google 通过收购这家公司大大提高了在移动市场上的竞争力。Google 的任何行动都会受到关注,而且引入新平台也很引人注目。Android 同时具备这两个因素。
第二个原因是 Android 的应用程序模型与众不同。Android 应用程序并不是需要大量单击操作的纯粹的菜单式应用程序。Android 应用程序中确实有菜单和按钮,但是 Android 在体系结构中引入了一种新颖的设计元素 intent。
intent 是一种构造,应用程序可以通过它发出请求,这就像是发出求助信号。intent 可能像下面这样:
"Wanted: An application to help me look up a contact" 或 "Wanted: An application to help me display this image" 或 "Wanted: An application to perform this geographic-based search"
应用程序可以按照相似或互补的方式进行注册,表明它们有能力或有兴趣执行各种请求或 intent。比如:
"Available: Application ready and willing to present contact records in clear, concise manner" 或 "Available: Application ready and willing to perform a geographic search"
这些是 IntentFilter
的示例,下面将要讨论。
应用程序通过一个称为 IntentFilter
的构造声明它们能够执行某些类型的操作。IntentFilter
可以在运行时进行注册,也可以在 AndroidManifest.xml 文件中设置。下面的代码片段取自一个对 SMS(文本)消息进行响应的 Android 应用程序:
清单 1. 对 SMS 进行响应的 Android 应用程序
<receiver class=".MySMSMailBox" >
<intent-filter>
<action android:value="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
简要介绍 intent 和
IntentFilter
之后,下一节介绍 Android 应用程序的四种主要类型。
Android 应用程序 — 概述
我们来看看 Android 应用程序的四种主要类型:活动、服务、接收器和 ContentProvider
。我们还要看看显示用户界面(UI)元素的视图。
活动是最常用的 Android 应用程序形式。活动在一个称为视图 的类的帮助下,为应用程序提供 UI。视图类实现各种 UI 元素,比如文本框、标签、按钮和计算平台上常见的其他 UI 元素。
一个应用程序可以包含一个或多个活动。这些活动通常与应用程序中的屏幕形成一对一关系。
应用程序通过调用 startActivity()
或 startSubActivity()
方法从一个活动转移到另一个活动。如果应用程序只需 “切换” 到新的活动,就应该使用前一个方法。如果需要异步的调用/响应模式,就使用后一个方法。在这两种情况下,都需要通过方法的参数传递一个 intent。
由操作系统负责决定哪个活动最适合满足指定的 intent。
与其他多任务计算环境一样,“在后台” 运行着一些应用程序,它们执行各种任务。Android 把这种应用程序称为 “服务”。服务是没有 UI 的 Android 应用程序。
接收器是一个应用程序组件,它接收请求并处理 intent。与服务一样,接收器在一般情况下也没有 UI 元素。接收器通常在 AndroidManifest.xml 文件中注册。清单 2 是接收器代码的示例。注意,接收器的类属性是负责实现这个接收器的 Java 类。
清单 2. 接收器代码
package com.msi.samplereceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentReceiver;
public class myreceiver extends IntentReceiver
{
public void onReceiveIntent(Context arg0, Intent arg1)
{
// do something when this method is invoked.
}
}
ContentProvider
是 Android 的数据存储抽象机制。我们以移动设备上常见的一种数据为例:地址簿或联系人数据库。地址簿包含所有联系人及其电话号码,用户在使用手机时可能需要使用这些数据。ContentProvider
对数据存储的访问方法进行抽象。ContentProvider
在许多方面起到数据库服务器的作用。对数据存储中数据的读写操作应该通过适当的 ContentProvider
传递,而不是直接访问文件或数据库。可能还有 ContentProvider
的 “客户机” 和 “实现”。
Android 活动通过视图显示 UI 元素。视图采用以下布局设计之一:
-
LinearVertical
- 后续的每个元素都排在前一个元素下面,形成一个单一列。
-
LinearHorizontal
- 后续的每个元素都排在前一个元素右边,形成一个单一行。
-
Relative
- 后续的每个元素相对于前一个元素有一定的偏移量。
-
Table
- 与 HTML 表相似的一系列行和列。每个单元格可以包含一个视图元素。
选择一种布局(或布局的组合)之后,就可以用各个视图显示 UI。
视图元素由大家熟悉的 UI 元素组成,包括:
- Button
- ImageButton
- EditText
- TextView(与标签相似)
- CheckBox
- Radio Button
- Gallery 和 ImageSwitcher(用来显示多个图像)
- List
- Grid
- DatePicker
- TimePicker
- Spinner(与组合框相似)
- AutoComplete(具有文本自动补全特性的 EditText)
视图是在一个 XML 文件中定义的。
清单 3 给出一个简单的 LinearVertical
布局示例。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Activity 1!"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Activity 1, second text view!"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch To Activity 2"
id="@+id/switchto2"
/>
</LinearLayout>
注意,每个元素有一个或多个属于 Android 名称空间的属性。
Android Software Developer Kit
我们已经大致了解了 Android 平台,现在讨论如何设置 Eclipse 环境来支持 Android 应用程序开发。本节讨论如何获取 Android SDK 并在 Eclipse 环境中配置它。
如果您还没有安装 Eclipse,那么从 Eclipse Foundation 下载并安装 Eclipse IDE 最新的稳定版(参见 参考资料)。安装包是一个压缩的文件夹。把这个文件夹的内容解压到您计算机上的适当位置。安装程序并不在 Windows® 上创建任何图标或快捷方式。对于本教程,Eclipse 文件夹位于 c:\software\eclipse 目录。
双击 eclipse 安装目录中的 eclipse.exe 启动 Eclipse。这会启动 IDE。软件提示您指定一个 “工作空间” 并建议一个默认位置,比如 c:\documents and settings\username\workspace。选择这个位置或者指定另一个工作空间位置。
启动 Eclipse 之后,单击主屏幕上的 Workbench - Go to the workbench 图标。
现在该获取 Android SDK 了。
在 参考资料 中找到 Android 的下载链接。
有针对 Windows、Mac OS X(只有 Intel® 版)和 Linux(i386)的 SDK 安装版。选择适合您平台的最新的 SDK 版本。注意,到编写本教程时,最新的 Android SDK 版本是 m3-rc37a。
Android SDK 是一个压缩的文件夹。下载这个文件夹并把它的内容解压到您计算机上的适当位置。对于本教程,SDK 安装在 c:\software\google\android_m3-rc37a。显然,如果要在 Mac OS X 和 Linux 上安装 SDK,应该安装在通常安装开发工具的位置。
Eclipse 和 Android SDK 都已经安装好了。现在应该安装 Eclipse 插件。
下面介绍安装 Eclipse 插件 Android Developer Tools 的步骤。注意,Android 网站上也提供了安装说明。更多信息请参见 参考资料。
按照以下步骤安装 Android Developer Tools:
- 在 Eclipse 中运行 “Find and Install” 特性(在 Help > Software Updates 菜单下面)。
- 选择 Search for new features to install 选项。
- 选择 New Remote Site。给站点命名,比如 “Android Developer Tools”。在对话框中输入以下 URL:https://dl-ssl.google.com/android/eclipse。注意,这个 URL 使用 HTTPS 协议。这是一个安全的下载。
图 1. New Update Site
- 列表中会增加一个新条目并被默认选中。单击 Finish。搜索结果会显示 Android Developer Tools。选择 Developer Tools 并单击 Next。
- 阅读并接受许可协议之后,单击 Next。注意,许可协议中对于使用 Google Maps API 有一个特殊的要求。
- 检查并接受安装位置,然后单击 Finish。
现在下载并安装这个插件。这个插件没有经过数字签名(到编写本教程时),所以只需单击 Install All,然后重新启动 Eclipse。
重新启动 Eclipse 之后,应该把这个插件连接到 SDK 的安装位置。在 Window 菜单中选择 Preferences。单击左边树视图中的Android。在右边的面板中,指定 SDK 的安装位置。本教程使用的安装位置是 c:\software\google\android\m3-rc37a(同样,在 Mac OS X 和 Linux 系统上也应该使用适当的位置)。
指定 SDK 安装位置之后,可以配置另外三部分设置。下面简要介绍一下:
- Build 部分中的选项用来自动地重新构建资源。保持这个选项的设置不变。Build 选项可以改变输出的详细程度。Normal 是默认设置。
- DDMS — Dalvik Debug Monitor Service 用来监视正在运行的 VM。这些设置指定调试器用来连接 VM 的 TCP/IP 端口号、各个日志记录级别和选项。默认设置应该是合适的。
- LogCat — 这是在底层 Linux 系统上创建的一个日志文件。可以在这个对话框中选择字体。根据需要调整这个选项。
好了!Eclipse 环境已经设置好了,可以开始创建 Android 应用程序了。
构建 SaySomething Android 应用程序
本节要使用 Android Developer Tools 创建一个基本的 Android 应用程序,它称为 SaySomething。创建这个应用程序之后,将调试和运行它。
第一步是创建一个新项目。选择用来创建 Android 项目的向导,如下所示。
图 2. New project 向导
这个应用程序需要:
- Name
- Location
- Package name
- Activity name — 可以认为这是应用程序的主 “表单” 或屏幕
- Application name
看看这个新项目。
图 3. 新的 Android 项目
这会创建一个默认的应用程序,可以构建和运行它。可以在 Package Explorer 中查看它的组件。
Package Explorer(在 Eclipse 的 Java 透视图中)显示 Android 示例应用程序的所有组件,见图 4。
图 4. Package Explorer
需要注意的组件包括:
-
src 文件夹
-
包含示例应用程序的包,即
com.msi.ibmtutorial
。
-
R.java
- Android Developer Tools 自动创建这个文件,它提供访问 Android 应用程序的各种资源所需的常量。后面会详细讨论 R 类与资源之间的关系。
-
SaySomething.java
- 应用程序的主活动类的实现。
-
Referenced libraries
- 包含 android.jar,这是 Android SDK 中的 Android 运行时类的 jar 文件。
-
res 文件夹
-
包含应用程序的资源,包括:
- 图标
- 布局文件
- 字符串
-
AndriodManifest.xml
- 示例应用程序的部署描述符。
接下来,详细研究一下源代码。
这个示例应用程序由一个活动组成,即 SaySomething
。正如前面提到的,SaySomething
类是在 SaySomething.java 文件中实现的。
package com.msi.ibmtutorial;
import android.app.Activity;
import android.os.Bundle;
public class SaySomething extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
}
}
在这个源代码片段中,要注意几点:
-
SaySomething
是一个普通的 Java 类,包含包和导入语句。 -
SaySomething
扩展 android.app 包中的 Android 基类 Activity。 -
onCreate()
方法是这个活动的入口点,它接受一个Bundle
类型的参数。Bundle
类本质上是 map 或 hashmap 的包装器。在这个参数中传递构造活动所需的元素。本教程不讨论这个参数。 -
setContentView(..)
负责用 R.layout.main 参数创建主 UI。R.layout.main 是应用程序资源中主布局的标识符。
正如前面提到的,Android 中的资源放在项目的 res 子目录中。资源分为三类:
-
Drawables
- 这个文件夹包含图形文件,比如图标和位图。
-
Layouts
- 这个文件夹包含表示应用程序布局和视图的 XML 文件。后面会详细研究这些文件。
-
Values
- 这个文件夹包含 strings.xml 文件。这是为应用程序实现字符串本地化的主要方法。
这个示例应用程序包含一个活动和一个视图。应用程序包含一个名为 main.xml 的文件,它代表活动的主 UI 的视觉方面。注意,在 main.xml 中没有指定在哪里使用这个布局。这意味着,如果需要的话,可以在多个活动中使用它。清单 5 给出布局文件的内容。
清单 5. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, SaySomething"
/>
</LinearLayout>
这是最简单的布局,其中只有一个垂直的线性布局,这意味着所有元素排成一列。这里有一个 TextView
元素,它与其他开发环境中的标签类似。TextView
代表不可编辑的静态文本。
注意,每个视图元素(比如这个示例中的 LinearLayout
和 TextView
)都有属于 Android 名称空间的属性。一些属性是所有视图元素都有的,比如 android:layout_width
和 android:layout_height
。这些属性可以采用的值是:
-
fill_parent
- 使视图元素占满可用的空间。也可以认为这就是 “拉伸”。
-
wrap_content
- 这个值让 Android 把元素一个接一个地排列,不进行拉伸。
在构建期间,对所有资源进行编译。编译过程的输出之一是 R.java 文件,这个文件向应用程序的其余部分提供资源。下面讨论 R.java 文件。
R.java 文件是在构建时自动创建的,所以不要手工修改它,因为所有修改都会丢失。清单 6 给出这个示例应用程序的 R.java 文件。
清单 6. R.java 文件
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.msi.ibmtutorial;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040000;
}
}
R
类包含一些匿名子类,每个子类包含前面描述的各种资源的标识符。注意,这些类都是静态的。
请注意 R.layout.main 代表的元素。这个标识符代表由 main.xml 定义的布局。在活动的 onCreate
方法中使用过这个值:setContentView(R.layout.main);
。这就是在运行时把特定的活动(在这个示例中是 SayAnything
)和特定的布局(主布局)联系在一起的方法。
在默认情况下,每次保存文件时,都将对它们进行编译。
图 5. 错误面板
我们在源代码中引入了一个错误,即在 setContent
和 View
之间加了一个空格。在保存这个文件时,它被编译并在屏幕底部的 Problems 面板中显示错误。在源代码中纠正这个错误之后,应用程序就能够成功编译,并从问题列表中删除错误。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.msi.ibmtutorial">
<application android:icon="@drawable/icon">
<activity class=".SaySomething" android:label="@string/app_name">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
请注意以下情况:
- 这里指定了源文件中的包名。这里采用与 Java 源文件和导入语句相似的模式。
<manifest>
标记的实际作用是 “导入” 这个包中的类。在这个文件中,所有非完全限定的类都属于 package 属性指定的包。 -
<application>
标记的一个属性引用了应用程序的一个资源。请注意 drawable 标识符前面的@
符号。这里的意思是,在应用程序资源的 drawable 文件夹中寻找名为 “icon” 的资源。 -
<activity>
标记包含以下属性和值:
- class 属性表示实现这个活动的 Java 类。
-
android:label
是应用程序的名称。注意,它来自一个字符串资源。string.xml 文件包含应用程序的本地化字符串。 -
<intent-filter>
表示应用程序中可用的IntentFilter
。这是 Android 应用程序中最常见的IntentFilter
。这个过滤器的实际意思是,它实现 “主” 操作(也就是入口点),而且它位于 OS 的启动器中。这意味着可以在 Android 设备上像启动其他应用程序一样,从应用程序主列表中启动它。
应用程序已经成功地编译了,现在该运行这个示例应用程序了。在 Eclipse 中选择 Open Run Dialog 或工具栏上的快捷按钮。这会打开一个对话框,可以在这里创建启动配置。选择 Android Application 选项并单击 New 的图标。
图 6 显示本教程示例所用的值。
图 6. Run 对话框
指定配置名称。本教程使用的名称是 Tutorial Configuration。在可用项目列表中选择 ibmtutorial 项目(单击 Browse 可以看到可用项目)。在下拉列表中选择启动活动。现在选择 Emulator 选项卡,根据需要指定模拟器设置。可以保持默认设置。有两个设置需要注意,见图 7。
图 7. Run 对话框,Emulator 选项卡
有几种可供选择的屏幕大小和方向,还有网络选择。如果运行应用程序的移动设备的因特网连接速度不同,网络选择就很重要了。在构造应用程序原型时,选择完整网络速度而且没有延迟。开发了主要功能之后,最好在比较真实的网络环境中进行测试,看看应用程序的响应速度如何。
选择 Run 运行示例应用程序。
图 8. 模拟器
应用程序已经在模拟器上运行了,现在看看幕后发生的情况。Dalvik Debug Monitor Service(DDMS)将会帮助检查应用程序的运行情况。
要想检查正在运行的应用程序中发生了什么情况,就需要查看正在运行的 Dalvik VM。在 Eclipse 中,选择 Window > Open Perspective > Other。在出现的对话框中选择 DDMS。这会在 Eclipse 中打开一个新的透视图,其中有许多有趣的窗口。下面简要介绍一下 DDMS 透视图中提供的资源:
LogCat
是一个日志文件,它记录 VM 中发生的活动。应用程序可以通过 Log.i(tag,message);
在这个日志文件中添加自己的日志项,其中的 tag
和 message
都是 Java 字符串。Log
类属于 android.util.Log
包。
图 9 显示 LogCat
。
图 9.
LogCat
DDMS 中的另一个方便的工具是文件管理器,可以用它访问模拟器的文件系统。图 10 显示在模拟器上部署本教程示例应用程序的位置。
图 10. 在模拟器上部署的示例应用程序
用户应用程序部署在 /data/app 目录中,而 Android 内置的应用程序部署在 /system/app 目录中。
在 DDMS 中还可以查看正在运行的进程。
图 11. 正在运行的进程列表
全面讨论 Android 应用程序的调试超出了本教程的范围,更多信息请参见 参考资料。
创建内容提供器和 Google Maps 应用程序
您已经看到了一个完整的应用程序示例,现在简要讨论一下更加复杂的应用程序。
本教程中讨论的第二个应用程序适用于提供上门服务的专业人员,比如设备维修技术人员,这些人必须找到去客户地址的路线。这个应用程序使用 Android 内置的联系人数据库作为记录存储库。本节将讲解如何访问内容提供器中的数据,还将看看 intent 的效果。我们将用联系人数据库中的地址数据执行 Google Maps 搜索。为了让这个应用程序在 Android 模拟器上正确运行,必须记录一些联系人,而且必须填写家庭地址字段。图 12 显示模拟器中与联系人应用程序相关的条目。
图 12. 模拟器中与联系人应用程序相关的条目
下面是这个应用程序的一个代码片段。注意,这个应用程序的主 Activity
类扩展 ListActivity
。这是因为我们需要在列表中显示信息
public class MobileServiceCallContacts extends ListActivity
{
final String tag = "MSCC";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
// Get a cursor with all people
Cursor c = getContentResolver().query(People.CONTENT_URI, null, null,
null, null);
startManagingCursor(c);
ListAdapter adapter = new SimpleCursorAdapter(this,android.R.
layout.simple_list_item_1,c,new String[] {People.NAME} ,new int[]
{android.R.id.text1});
setListAdapter(adapter);
}
...
}
注意,这里使用游标类查询联系人数据库。这个 “结果集” 游标通过 ListAdapter
类链接到 UI。图 13 显示当设备上记录了联系人时应用程序的效果。注意,这个屏幕上的记录没有排序。
图 13. 应用程序的运行效果
可以通过鼠标单击、按模拟器的中间按钮或按键盘上的 Enter 键选择一个联系人。选择联系人之后,代码必须查询所选联系人的地址。这要使用覆盖的 onListItemClick()
方法。这个方法的实现有四个重要参数,其中最重要的是 dbidentifier
。因为游标绑定到 UI,所以在调用这个方法时,它实际上会获得底层数据源的标识符。可以使用 dbidentifier
字段在联系人数据库中查询所需的信息。还可以使用它启动联系人应用程序,所用的 intent 见清单 9 中被注释掉的代码。
onListItemClick()
方法
@Override
protected void onListItemClick(ListView list,View view,int position,long
dbidentifier)
{
super.onListItemClick(list,view,position,dbidentifier);
try
{
// this commented out code below will launch the Contacts application
// and "view" the contact Intent myIntent = \
new Intent(android.content.
// Intent.VIEW_ACTION,new ContentURI("content://contacts/people/"
// + dbidentifier)); startSubActivity(myIntent,position);
// let's lookup specifics on this record
ContentURI theContact = \
new ContentURI(android.provider.Contacts.ContactMethods.CONTENT_URI.toURI());
// IMPORTANT
// in order to use this sample application, you need to have at least
// one Contact record on your Android emulator\
// and be sure to have populated the 'Home Address field'
//
// this "where clause" is for HOME address and for the person record
// selected in the GUI (id, dbidentifier)
Cursor c = managedQuery(theContact,null," type = 1 and person = " +
dbidentifier,null);
if (!c.first())
{
showAlert("MSCC","No Contact Methods Available!","",true);
return;
}
String address = c.getString(c.getColumnIndex("data"));
address = address.replace("\n","");
address = address.replace(",","");
address = address.replace(" ","+");
Intent geoIntent = new Intent("android.intent.action.VIEW",
new ContentURI\
("geo:0,0?q=" + address));
startActivity(geoIntent);
}
catch (Exception ee)
{
Log.i(tag,ee.getMessage());
}
}
找到地址之后,需要通过一些简单的字符串操作清理数据,准备查询 Google Maps。geoIntent
是一个用来执行地理搜索的新的 intent,它通过调用 Google Maps 提供默认的 Android 模拟器图像。
第一个应用程序的所有主要元素仍然适用于这个应用程序。它有一个从主应用程序屏幕启动的活动。当然,还有 AndroidManifest.xml 文件。在 下载 一节中可以找到完整的源代码。
关于第二个应用程序,还有最后一点需要注意。AndroidManifest.xml 文件中包含一个条目,它使应用程序能够读取联系人数据库:<uses-permission id="android.permission.READ_CONTACTS" />
。如果不这样做,Linux 内核就会禁止应用程序访问联系人数据库。