第 1 章 Android 的系统介绍
1.2 软件结构和使用的工具
1.1 系统介绍
1.2 软件结构和使用的工具
1.1 系统介绍
Android 是 Google 开发的基于 Linux 平台的、开源的、智能手机操作系统。
Android 包括操作系统、中间件和应用程序,由于源代码开放,Android 可以被移 植到不同的硬件平台上。
OHA(Open Handset Alliance,开放手机联盟),为 Google 与 33 家公司联手 为 Android 移动平台系统的发展而组建的一个组织。
HTC 和 Google 合作推出了几款手机:G1、G2、Hero 和 Nexus One,其他的 手机厂商也推出了几款 Android 手机,如下图所示:
Android入门到精通详解
图 G1、G2、Hero 和 Nexus One 手机
围绕在 Google 的 Android 系统中,形成了移植开发和上层应用程序开发两个 不同的开发方面。手机厂商从事移植开发工作,上层的应用程序开发可以由任何 单位和个人完成,开发的过程可以基于真实的硬件系统,还可以基于仿真器环境。
Android 1.5 以前的仿真环境,Android 1.6 以后的仿真器环境如下所示:
图 Android 1.5 以前的仿真器环境
Android入门到精通详解
图 Android 1.6 以后的仿真器环境
作为一个手机平台,Android 在技术上的优势主要有以下几点:
全开放智能手机平台
多硬件平台的支持
使用众多的标准化技术
核心技术完整,统一
完善的 SDK 和文档
完善的辅助开发工具
Android 的开发者可以在完备的开发环境中进行开发,Android 的官方网站也
提供了丰富的文档、资料。这样有利于 Android 系统的开发和运行在一个良好的
生态环境中。
1.2 软件结构和使用的工具
从宏观的角度来看,Android 是一个开放的软件系统,它包含了众多的源代 码。从下至上,Android 系统分成 4 个层次:
第 1 层次:Linux 操作系统及驱动;
第 2 层次:本地代码(C/C++)框架;
第 3 层次:Java 框架;
第 4 层次:Java 应用程序。
Android 系统的架构如图所示:
第一层:Linux操作系统及驱动 第二层:本地框架和Java运行环境 第三层:Java框架
第四层:Java应用程序
内核空间 <--> 用户空间 C/C++ <--> JAVA
系统API
图 Android 系统的架构
Android 的第 1 层次由 C 语言实现,第 2 层次由 C 和/C++实现,第 3、4 层 次主要由 Java 代码实现。
第 1 层次和第 2 层次之间,从 Linux 操作系统的角度来来看,是内核空间与 用户空间的分界线,第 1 层次运行于内核空间,第 2、3、4 层次运行于用户空间。
第 2 层次和第 3 层次之间,是本地代码层和 Java 代码层的接口。
第 3 层次和第 4 层次之间,是 Android 的系统 API 的接口,对于 Android 应 用程序的开发,第 3 层次以下的内容是不可见的,仅考虑系统 API 即可。
Android入门到精通详解
由于 Android 系统需要支持 Java 代码的运行,这部分内容是 Android 的运行 环境(Runtime),由虚拟机和 Java 基本类组成。
对于 Android 应用程序的开发,主要关注第 3 层次和第 4 层次之间的接口。
除了软件本身的代码之外,Android 还提供了一系列工具来辅助系统开发,
这些主要的工具包括:
aapt(Android Asset Packaging Tool):用于建立 zip 兼容的包(zip、jar、apk),
也可用于将资源编译到二进制的 assets。
adb(Android Debug Bridge,Android 调试桥):使用 adb 工具可以在模拟器 或设备上安装应用程序的.apk 文件,并从命令行访问模拟器或设备。也可以 用它把 Android 模拟器或设备上的应用程序代码和一个标准的调试器连接 在一起。
android 工具:android 工具是一个脚本,用于创建和管理 Android Virtual Devices (AVDs) 。
AIDL 工具(Android Interface Description Language,Android 接口描述语言 工具) ,AIDL 工具可以生成进程间接口的代码,诸如 Service 可能使用的接 口。
AVDs(Android Virtual Devices,Android 虚拟设备)
用于配置模拟器,模拟出类似的设备效果
DDMS(Dalvik Debug Monitor Service,Dalvik 调试监视器服务):这个工具 集成了 Dalvik,能够在模拟器或者设备上管理进程并协助调试。可以使用它 杀死进程,选择某个特定的进程来调试,产生跟踪数据,观察堆(heap)和 线程信息,截取模拟器或设备的屏幕画面,还有更多的功能。
dx:dx 工具用于将.class 字节码(bytecode)转换为 Android 字节码(保存 在.dex 文件中)这个字节码文件是给 Android 的 Java 虚拟机运行用的。
Draw 9-patch:Draw 9-patch 工具允许使用所见即所得(WYSIWYG)的编 辑器轻松地创建 NinePatch 图形。
Emulator(模拟器):模拟器是一个运行于主机上的程序,可以使用模拟器
来模拟一个实际的 Android 系统的运行,使用模拟器非常适合调试和测试应
用程序。
映像来模拟外部存储卡(例如 SD 卡)。
Monkey:Monkey 是在模拟器或设备上运行的一个小程序,它能够产生随机 的用户事件流,例如:点击(click)、触摸(touch)、挥手(gestures),还包 括一系列系统级事件。可以使用 Monkey 给正在开发的程序做随机的但可重 复的压力测试。
sqlite3:sqlite3 工具能够方便地访问 SQLite 数据文件,这是一个 sqlite 标准 命令行工具。
Traceview:这个工具可以将 Android 应用程序产生的跟踪日志(trace log)
转换为图形化的分析视图。
Android入门到精通详解
第 2 章 Android SDK 的开发环境
2.1 Android SDK 的结构
2.2 Android SDK 的环境安装
2.3 Android 中运行仿真器环境
2.4 Android 中建立中程
Android 的 SDK 开发环境使用预编译的内核和文件系统,屏蔽了 Android 软
SDK 的目录结构如下所示:
add-ons:附加的包;
docs:HTML 格式的离线文档;
platforms:SDK 核心内容;
tools:工具。
在 platforms 中包含了的各个 Android SDK 版本的目录中,包含系统映像,工 具、示例代码等内容。
data/ :包含默认的字体、资源等内容;
images/ :包含默认的 Android 磁盘映像,包括了系统映像(Android system image), 默认的用户数据映像(userdata image),默认的内存盘映像 (ramdisk image)等等,这些映像是仿真器运行的时候需要使用的; platform version.
android.jar:Android 库文件的 JAVA 程序包,在编译本平台的 Android 应用
程序的时候被使用。
2.2 Android SDK 环境安装
Android 的 SDK Windows 版本需要以下的内容:
JDK 1.5 或者 JDK 1.6
Eclipse 集成开发环境
ADT(Android Development Tools)插件
Android SDK
Eclipse 3.3(Europa)
Eclipse 3.4(Ganymede)
Android入门到精通详解
Eclipse 3.5(Galileo)
在 Android 的开发中,推荐使用 Eclipse 3.4 和 Eclipse 3.5,Eclipse 3.3 虽然也 可以使用,但是没有得到 Android 官方的验证。
如果使用 Eclipse 3.4,可以去下载 eclipse-SDK-3.4-win32.zip 包;如果使用 Eclipse 3.5,可以去下载 eclipse-SDK-3.5.1-win32.zip 包。这个包不需要安装,直 接解压缩即可,解压缩后执行其中的 eclipse.exe 文件。 1.1,Android SDK 1.5,Android SDK 1.6 可以直接从 Android 开发者中下载得到,
每个 SDK 包含 Linux、Windows 和 MAC 三个版本。在 Windows 环境中,使用 Windows 的 版 本 , 例 如 : android-sdk-windows-1.5_r2.zip , android-sdk-windows-1.6_r1.zip,这个包通常用几百 M 的大小。
以这种方式下载的 Android SDK,不需要安装,直接解压缩即可。
目前 Android 系统推荐使用的方式软件升级获得 Android 包:
第一步:获得 android-sdk_r04-windows.zip
从 Android 开发者上,获取 Android SDK 的相关包 android-sdk_r04-windows.zip,
这个包比实际的 Android 的 SDK 要小得多,只有 20 多 M,其中包含了一个 Setup 可 执行程序,获取完整的 SDK 是通过这个可执行程序获得的。解压缩这个包,获得 Android SDK 的基本目录结构,但是其中还没有实际的内容。
第二步:运行 SDK Setup.exe 程序,下载实际的 Android SDK
运行程序,Android SDK 的,出现 SDK 的下载界面:
图 Android SDK 的安装界面
在 Settings 中进行设置,选中 Force ……项,并且选择保存(Save and Apply)。
Android入门到精通详解
图 设置安装路径
回到 Installed Packages 中,进行安装,出现 Android 的各个版本的 SDK、工 具、文档的安装界面,如下所示:
图 选择要安装的组件
每个组件可以选择,接受(Accept)表示安装,拒绝(Reject)表示不安装,
接受全部(Accept All)表示安装所有的内容。文档一般安装成最新的版本。
选择后,安装程序将依次安装各个组件。
图 安装界面
下载过程中,每个组件将首先被放置到 temp 中,以一个 zip 包的形式存在。
下载完成后,得到完整的 Android SDK。
2.2.4(1). 在 Eclipse 3.4(Ganymede)中安装 ADT
第一步:启动 Eclipse 选择“Help”>“Software Updates...”准备安装插件。
Android入门到精通详解
图 Eclipse 3.4 中选择软件升级
第二步:在打开的对话框中点击“Available Software”,出现 Eclipse 的
现有软件对话框。
点击右侧自上而下的第 3 个按钮,“Add Site...”准备增加插件。
图 增加 ADT 的路径
在“Add Site”对话框中,输入 Android 插件的路径:
https://dl-ssl.google.com/android/eclipse/
另外的一种方式是点击 Archive„按钮,这样可以不使用网络,直接指定磁 盘中的 ADT 包(目前最新的版本是 ADT-0.9.5.zip)。
第三步:回到安装对话框,可以看到 plugin 的 URL 下面有“Developer Tools”。
选择到“Developer Tools”中,
图 Eclipse 3.4 中选择安装 Android 的 DDMS 和 ADT
然后点击“Install...”按钮,继续运行,如图所示:
Android入门到精通详解
图 Eclipse 3.4 中进行安装 Android 的 DDMS 和 ADT
选择 Next 将出现如图的对话框:
选择接受(accept)并且选择 Finish 完成安装之前的配置,后面的将进入安 装的 Android 组件的阶段。
安装的过程要经过寻找依赖和安装两个阶段,如图所示:
图 Eclipse 3.4 中解决依赖关系和安装
第四步:安装完成,关闭并重新启动 Eclipse。再次进入 Eclipse 3.4 后,将发 现 ADT 已经被安装。
2.2.4(2). 在 Eclipse 3.5(Galileo)中安装 ADT
第一步:启动 Eclipse 选择 “Help”>“Install New Software...”准备安装插 件。
Android入门到精通详解
图 Eclipse 3.5 中选择安装新软件
第二步:出现软件升级的对话框
图 Eclipse 3.5 中增加 ADT 插件的路径
在“Add Site”对话框中,输入 Android 插件的路径:
https://dl-ssl.google.com/android/eclipse/
另外的一种方式是点击 Archive„按钮,这样可以不使用网络,直接指定磁 盘中的 ADT 包(最新的版本是 ADT-0.9.5.zip)。
第 四 步 : 回 到 软 件 升 级 对 话 框 , work with 的 路 径 变 为 了 https://dl-ssl.google.com/android/eclipse/,后面的列表变为了“Developer Tools”,
其中包含了两个项目:
Android DDMS
Android Development Tools 选择继续进行安装:
Android入门到精通详解
图 Eclipse 3.5 中选择安装 Android 的 DDMS 和 ADT
选中后,点击 Finish 将出现安装的详细信息的对话框,如图所示:
图 Eclipse 3.5 中选择安装 Android 的插件
选择 Next 进行下一步的安装。
Android入门到精通详解
图 Eclipse 3.5 中选择同意 Android 的协议
选择接受(accept)并且选择 Finish 完成安装之前的配置,后面的将进入安
装的 Android 组件的阶段。安装的过程如图所示:
图 Eclipse 3.5 中选择进行 Android 的插件
第五步:安装完成,关闭并重新启动 Eclipse。再次进入 Eclipse 3.5 后,将发 现 ADT 已经被安装。
2.2.5. 在 Eclipse 中配置 Android SDK
进入安装 ADT 的 Eclipse 环境后,选择“Window”>“Preference”,从左侧 的列表中选择 Android 项:
Android入门到精通详解
图 Eclipse 中选择 Android SDK 的路径
左侧的 Android 选项是由于安装了 Android 的 SDK 而出现的。
在 SDK 设置 SDK Location 中,点击“Browse”„按钮;选择 Android,SDK
的目录,点击“OK”按钮。
2.3 Android 中运行仿真器环境 2.3.1. 建立 Android 虚拟设备
为了运行一个 Android 仿真器的环境,首先需要建立 Android 虚拟设备
(AVD)。在 Eclipse 的菜单中,选择“Window”>“Android AVD Manager”,
出现“Android SDK and AVD Device Manager”窗口,界面如图所示:
图 Android SDK 和 AVD 管理器
界面中间的列表表示了目前可以使用的 Android 虚拟设备,在没有虚拟设备 的情况下点击右侧的 New 选择建立一个虚拟设备。
建立新的 Android 虚拟设备的窗口为 Create new AVD,如图所示:
Android入门到精通详解
图 建立新的 AVD
Android 虚拟设备的建立包含了以下的一些选项:
名字(Name):这个虚拟设备的名称,由用户自定义;
目标(Target):选择不同的 SDK 版本(依赖一目前 SDK 的 platform 目中包含了 哪些版本的 SDK)
SD 卡:模拟 SD 卡,可以选择大小或者一个 SD 卡映像文件,SD 卡映像文件是 使用 mksdcard 工具建立的。
皮肤(Skin):这里皮肤的含义其实是仿真器运行尺寸的大小,默认的尺寸有
HVGA-P(320x480) ,HVGA-L(480x320)等,也可以通过直接指定尺寸的方
2.3.2. 运行虚拟设备
在“Android SDK and AVD Device Manager”窗口中,选择一个设备,点击 右侧的 Start,将启动虚拟设备,运行一个 Android 系统,一个 HVGA-P(320x480)
尺寸的运行结果如图所示:
图 使用仿真器的运行 Android 系统
出现窗口的左侧是运行的仿真器的屏幕,右侧是模拟的键盘。设备启动后,
可以使用右侧的键盘模拟真实设备的键盘操作,也可以用鼠标点击(或者拖拽和 长按)屏幕,模拟触摸屏的操作。
除了使用右侧的模拟键盘之外,也可以使用 PC 机的键盘来进行模拟真实设 备的键盘操作。尤其是当仿真器的大小不是标准值的时候,可能不会出现按键的 面板,在这种情况下只能使用键盘的按键来控制仿真器的按键
按键之间的映射关系如下表所示:
仿真器的虚拟按键 键盘的按键
Home HOME
Android入门到精通详解
Menu (左软按键) F2 or Page-up button Star (右软按键) Shift-F2 or Page Down
Back ESC
Call/dial button F3
Hangup/end call button F4
Search F5
Power button F7
Audio volume up button KEYPAD_PLUS, Ctrl-5 Audio volume down button KEYPAD_MINUS, Ctrl-F6 Camera button Ctrl-KEYPAD_5, Ctrl-F3 切换到上一个布局方向(例如 portrait 和
landscape) KEYPAD_7, Ctrl-F11
切换到下一个布局方向(例如 portrait 和
landscape) KEYPAD_9, Ctrl-F12
切换 Cell 网络的开关 on/off F8
DPad left/up/right/down KEYPAD_4/8/6/2 DPad center click KEYPAD_5
Onion alpha 的增加和减少 KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)
Android 仿真器启动虚拟设备之后,默认就可以使用主机的网络作为自己的 网络、使用主机的音频设备作为自己的声音输出。
2.3.3. 使用 Android 中的工具
图 选择 Android 的各个工具
选择 Android 工具的对话框如图所示:
Android入门到精通详解
图 选择 Android 工具的对话框
这里可以选择的主要工具有 Device(设备控制)、Emulator Control(仿真器 控制)、File Explore(文件浏览)、Heap(堆内存)、Logcat、Resource Explore
(资源浏览)、Threads(线程等)。每个工具开启之后,将出现一个单独的选项 卡。
2.3.4. 使用 logcat
Logcat 工具是查看系统 Log 信息的工具,可以获得 Android 系统运行的时候
打印出来的信息。工具的界面如下所示:
图 使用 Logcat 工具显示 LOG
Logcat 实际上是一个运行在目标系统的工具,也就是一个 Linux 的命令行程 序,这是界面种是带有 GUI 的效果。Logcat 的窗口中记录的信息也就是实际的 Android 系统打印出来的。包含了时间(Time)、级别(Level)、进程 ID(Pid)、
标签(tag)、Log 内容(Message)等项目。
Logcat 窗口可以设置 Log 的过滤器(Filter),这样可以仅仅获得自己需要的 Log 信息,屏蔽其他的信息。
命令行程序 logcat,位于目标文件系统中该工具位于 system/bin 目录中,
Logcat 的使用方法如下所示:
# logcat [options] [filterspecs]
logcat 工具的选项如下所示:
-s 设置过滤器,例如指定 '*:s
Android入门到精通详解
-f <filename> 输出到文件,在默认情况下是标准输出 -r [<kbytes>] 循环 log 的字节数(默认为 16),需要 –f -n <count> 设置循环 log 的最大数目,默认为 4
-v <format> 设置 log 的打印格式,<format> 是下面的一种:
brief process tag thread raw time threadtime long -c 清除所有 log 并退出
-d 得到所有 log 并退出(不阻塞)
-g 得到环形缓冲区的大小并退出
-b <buffer> 请求不同的环形缓冲区('main'(默认)、'radio'、'events')
-B 将 log 输出到二进制文件中
2.3.5. 使用仿真器控制
选择 Emulator Control 选项可以开启仿真器的控制对话框,它的界面如下所
示:
图 Android 仿真器控制界面
它甚至可以模拟打电话,发短信的过程。例如在 incoming number 中输入电 话号码,然后点击 Call 按钮。这是仿真器的运行界面如图所示:
Android入门到精通详解
图 Android 仿真器接收来电
接受电话的程序已经被调用起来,这里显示的电话号码 1-234-56,也是在仿 真器控制的窗口中设置的。
模拟发送短信的界面显示如下所示:
图 Android 仿真器接收短信
2.3.6. 命令行工具 adb、mksdcard 等
有一些 Android 的工具需要在命令行的环境中运行,只是可以选择 Windows 的开始->运行,键入 cmd 并确定,进入命令行的界面中运行。主要的命令行工具 包括 adb 和 mksdcard 等。命令行的工具在 Android SDK 的 tools 目录中,使用命 令行的窗口如图所示:
Android入门到精通详解
图 在命令行中使用 adb
adb(Android Debug Bridge,Android 调试桥)是 Android 的主要调试工具,
它可以通过网络或者 USB 连接真实的设备,也可以连接仿真器。使用 adb 进行调 试,通常在命令行的界面中。
将出现 shell 提示符,这就是 Android 所运行的 Linux 系统中的 shell 终端,
可以在这个 shell 提示符后执行 Android 系统提供的 Linux 命令。
使用 ls 命令查看 Android 系统根目录:
# ls -l
drwxr-x--- root root 1970-01-01 00:00 sbin
内容相对应,此外 etc、proc 等目录是在 Android 启动后自动建立的,system 映像 被挂接到根文件系统的 system 目录中,data 映像被挂接到根文件系统的 data 目录
system 541 1 808 264 c01654b4 afe0c45c S /system/bin/servicemanager root 542 1 836 364 c008e3f4 afe0c584 S /system/bin/vold
root 543 1 668 264 c0192c20 afe0cdec S /system/bin/debuggerd radio 544 1 5392 684 ffffffff afe0cacc S /system/bin/rild root 545 1 72256 20876 c008e3f4 afe0c584 S zygote
media 546 1 17404 3496 ffffffff afe0c45c S /system/bin/mediaserver bluetooth 547 1 1168 568 c008de04 afe0d25c S /system/bin/dbus-daemon root 548 1 800 300 c01f3b04 afe0c1bc S /system/bin/installd root 551 1 840 356 c00ae7b0 afe0d1dc S /system/bin/qemud root 554 1 1268 116 ffffffff 0000e8f4 S /sbin/adbd system 570 545 175652 23972 ffffffff afe0c45c S system_server radio 609 545 105704 17584 ffffffff afe0d3e4 S com.android.phone app_4 611 545 113380 19492 ffffffff afe0d3e4 S android.process.acore app_12 632 545 95392 13228 ffffffff afe0d3e4 S com.android.mms
app_4 645 545 97192 12964 ffffffff afe0d3e4 S com.android.inputmethod.latin
Android入门到精通详解
app_5 655 545 95164 13376 ffffffff afe0d3e4 S android.process.media app_7 668 545 97700 14264 ffffffff afe0d3e4 S com.android.calendar app_11 684 545 94132 12624 ffffffff afe0d3e4 S com.android.alarmclock root 702 540 888 340 00000000 afe0c1bc R ps
> adb install XXX.apk
使用 adb 在主机和目标机之间传送文件的方法为:
> adb push {host_path} {target_path}
> adb pull {target_path} {host_path}
mksdcard 是用来建立 SD 卡映像的工具,用来建立一个 Fat32 格式的磁盘映 像,其使用方法如下所示:
mksdcard [-l label] <size> <file>
mksdcard 的参数-l 用于指定磁盘映像的标签,size 用于指定磁盘映像的大小,
其后面可以跟 K、M、G 等参数,file 是磁盘映像的文件名称,这个文件也就是在 仿真器运行过程中指定的文件。
mksdcard 的一个使用的示例如下所示:
> mksdcard 128M sdcard.img
这表示建立了一个大小为 128M,名称为 sdcard.img 的 Fat32 磁盘映像文件。
2.3.7. 使用设备控制
Device 工具可以用于进一步控制仿真器的运行状况,在其中可以查看 Heap
图 Android 的设备工具
点击 Device 窗口工具栏最右侧的 Screen Capture 按钮,可以打开截取屏幕的 窗口,如上图所示。
2.4 Android 中建立工程 2.4.1. 建立工程
Android 的 SDK 环境安装完成后,就可以在 SDK 中建立工程并进行调试了。
建立 Android 工程步骤如下:
选择“File”>“New”>“Project”
选择“Android”>“Android Project”,点击“Next”按钮:
Android入门到精通详解
选择 the contents for the project。
图 建立新的 Android 工程
可以选择新建工程或从源代码建立工程,如果从源代码建立工程,那么所指
定的目录中需要具有 AndroidManifest.xml 文件。
图 使用已有的示例建立新工程
可以使用 SDK 的 platforms/android-XXX/samples 中的各个子目录建立工程,
这是 SDK 自带的示例程序,例如,使用 HelloActivity 示例程序。
Android入门到精通详解
图 选择工程示例
点击“Finish”按钮,工程将被建立。
2.4.2. 查看和编辑各个文件
建立工程后, 可以通过 IDE 环境查看和编辑 Android 应用程序中的各个文件。
不同的文件将使用不同的工具查看。
查看 AndroidManifest.xml 文件的情况,如图所示:
图 查看和编辑 AndroidManifest.xml 文件
显示的内容是以窗口的方式查看和更改 AndroidManifest.xml 中的内容,点击 下面的 AndroidManifest.xml 标签将切换到文本模式,使用文本的形式查看和编辑 AndroidManifest.xml 中的内容。
浏览布局文件,如图所示:
Android入门到精通详解
图 查看和编辑布局文件
浏览布局文件是一个更有用的功能,可以直观地查看程序的 UI 布局,点击 标签(布局文件的名称)可以切换到文本模式。利用 IDE 的布局查看器,可以在 程序没有运行的情况下直接查看和组织目标 UI 界面。
查看各个 value 文件和建立数值,如图所示:
图 查看各个 value 文件和建立数值
查看各个 Java 源代码文件,如图所示:
Android入门到精通详解
图 Java 源代码文件的编辑界面
Java 源代码采用文本的方式,但是在右边也列出了 Java 源代码中类的层次结 构。在 IDE 的源代码环境开发 JAVA 程序,还具有自动修正、自动增加依赖包、
类方法属性查找等功能。
2.4.3. 运行工程
在 Android 中运行一个工程,可以使用,右键单击工程名称,“选择 Run As”
或者“Debug As”来运行和调试工程:
图 运行 Android 工程
开始运行的时候,如果现在已经有连接到真实的设备或者仿真器设备上,将 直接使用这个设备,否则将启动一个新的仿真设备。
开始运行后,在 IDE 下层的控制台(console)标签中,将出现目标运行的 log 信息,可以获取目标运行的信息。出现类似的 Log 信息:
[HelloActivity]Android Launch!
[HelloActivity]adb is running normally.
[HelloActivity]Performing com.example.android.helloactivity.HelloActivity activity launch
[HelloActivity]Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'HVGA'
[HelloActivity]WARNING: Application does not specify an API level requirement!
[HelloActivity]Device API version is 4 (Android 1.6)
[HelloActivity]Uploading HelloActivity.apk onto device 'emulator-5554' [HelloActivity]Installing HelloActivity.apk...
[HelloActivity]Success!
[HelloActivity]Starting activity
Android入门到精通详解
com.example.android.helloactivity.HelloActivity on device
[HelloActivity]ActivityManager: Starting: Intent
{ cmp=com.example.android.helloactivity/.HelloActivity }
图 运行 HelloActivity 程序
在运行的一个仿真设备的时候,可以进一步通过选择“Run As”中的“Run
Configurations”进行进一步的配置。 启动后的界面如图所示:
图 选择工程中运行的动作
其中,在 Android 的标签中可以选择启动的工程,启动活动(Launch Action)
选项中可以选择启动的哪一个活动(Android 的一个工程中可以包含多个活动)。
在 Target 标签中可以选择启动的时候使用的设备。
Android入门到精通详解
第二篇 Android 应用程序的概述和框架 第 3 章 Android 应用层程序的开发方式
3.1 应用程序开发的结构
3.2 API 参考文档的使用
3.1 应用程序开发的结构
Android 应用程序开发是 Android 开发中最上面的一个层次,它们构建在 Android 系统提供的 API 之上。 Android 应用程序的基础是 Android 提供的各个 Java 类,这些类组成了 Android 系统级的 API。
Android预置 Android 应用程序
系统API
自开发 应用程序
自开发 应用程序
自开发
应用程序
„„
Android手机 Android仿真器
硬件抽象层 硬件抽象层
Android框架层软件
图 Android 应用的开发结构
Android 应用程序可以基于两种环境来开发: Android SDK 和 Android 源代码。
Android 系统本身内置了一部分标准应用(也包括内容提供者),在仿真器(包 括 SDK 环境和源代码环境)中已经包含这些内置的程序。
用户自行开发的应用程序和 Android 内置的应用层程序包位于同一个层次,
都是基于 Android 框架层的 API 来构建的,它们的区别仅仅在于他们是否被包含 在默认的 Android 系统中。
Android入门到精通详解
3.2 API 参考文档的使用
Activity
extends ContextThemeWrapper
implements ComponentCallbacks KeyEvent.Callback LayoutInflater.Factory View.On CreateContextMenuListener Window.Callback
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper ↳ android.view.ContextThemeWrapper ↳ android.app.Activity
Known Direct Subclasses
ActivityGroup, AliasActivity, ExpandableListActivity, ListActivity
Known Indirect Subclasses
LauncherActivity, PreferenceActivity, TabActivity
android.view.ContextThemeWrapper,并且被 ActivityGroup, ListActivity 等几个类 直接继承。被 LauncherActivity 等几个类间接继承。
Inherited Constants
(继承的常量的列表,按照继承类的顺序)
Public Constructors (公共的构造函数)
(详细的介绍) Known Direct Subclasses CompoundButton
CompoundButton A button with two states, checked and unchecked.
Known Indirect Subclasses
CheckBox, RadioButton, ToggleButton
XML attributes
See Button Attributes, TextView Attributes, View Attributes Summary
Button 类的头部信息和普通的类基本相同,但是包含了 XML attributes 一个
项目,在这里包含了 Button Attributes,TextView Attributes,View Attributes,根
据类的继承关系可以得知,这个启示是自己的属性、父类的属性(Button 类的父
类 是 android.widget.TextView ) 、 祖 父 类 的 属 性 ( Button 类 的 祖 父 类 是
android.view.View 可以得到这些属性的列表。每个属性包含了 Attribute Name(属 性名称) Related Method(相关方法) Description(描述)几个项目。
例如,TextView 的几个属性如下所示:
android:text setText(CharSequence) Text to display.
android:textColor setTextColor(ColorStateList) Text color.
android:text 等表示了属性在 XML 文件中的名称,setText()等表示了在 JAVA 源文件中使用的方法,最右侧的内容是这个属性的描述。
点击 XML attributes 中的连接可以进入其详细的内容中查看,这些 XML 属性 的帮助以及相关的值可以在 android.R.styleable 类中查找,这个类也可以直接被调 出,方法为:
Package Index → android → android.R.styleable
android.R.styleable 中列出了一些类的 XML 属性,例如 TextView 的 capitalize 属性的相关内容如下所示:
public static final int TextView_capitalize
If set, specifies that this TextView has a textual input method and should automatically capitalize what the user types. The default is "none".
Must be one of the following constant values.
Constant Value Description
none 0 Don't automatically capitalize anything.
sentences 1 Capitalize the first word of each sentence.
words 2 Capitalize the first letter of every word.
characters 3 Capitalize every character.
This corresponds to the global attribute resource symbol capitalize.
Constant Value: 44 (0x0000002c)
这里列出了属性的值(Value),这些值的本质是整数常量,但是在 XML 中 使用的还是名称。整数值是 Android 内部运作使用的。
XML 属性有些是在布局文件中使用的,也有在 AndroidManifest.xml 中使用 的,或者在其他的 XML 文件中使用。
这在 android.R.styleable 的帮助信息中,以 AndroidManifest 为开头的内容是 在 AndroidManifest.xml 中使用的属性。
例如,AndroidManifestAction 项目是 AndroidManifest.xml 中的 Action 标签中 使用的内容,如下所示:
public static final int[] AndroidManifestAction
Android入门到精通详解
Attributes that can be supplied in an AndroidManifest.xml action tag, a child of the intent-filter tag. See addAction(String) for more information.
Includes the following attributes:
Attribute Summary
android:name The name of an action that is handled, using the Java-style naming convention.
See Also
AndroidManifestAction_name
Attribute Summary 中的 android:name 引用的内容是 AndroidManifest.xml 中 的 Action 标签可以使用的 android:name 属性。
相比各种类的帮助信息,接口(Interface)的帮助信息更加简单一些。一般 的接口是需要被实现才能够使用的。
例如,View.OnClickListener 的帮助信息前面的内容如下所示:
public static interface View.OnClickListener
android.view.View.OnClickListener
Known Indirect Subclasses
CharacterPickerDialog, KeyboardView
这里的,android.view.View.OnClickListener 表示了 View.OnClickListener 这个 接口在 android.view 这个包中。对于一个接口,Indirect Subclasses 的含义为实现
(
implements)这个接口。
第 4 章 Android 应用程序示例
4.1 HelloActivity 程序的运行 4.2 HelloActivity 的源文件结构 4.3 HelloActivity 的编译结构 4.4 SkeletonApp 的程序的运行 4.5 SkeletonApp 源文件结构 4.6 SkeletonApp 编译结构
Android入门到精通详解
在软件开发的最初阶段,通常使用一个 Hello World 程序作为最简单的示例,
本部分介绍一个 Android 中最简单应用程序,通过这部分内容可以了解到 Android 程序的文件结构和编译后的结构。
4.1 HelloActivity 程序的运行
HelloActivity 是 一 个 简 单 的 Android 应 用 程 序 , 其 工 程 文 件 名 称 为 HelloActivity,在 Android 的源代码和 SDK 中,都包含了这个包。
HelloActivity 的图标和运行情况如图所示。
图 HelloActivity 的图标和运行情况
4.2 HelloActivity 的源文件结构
HelloActivity 工程中另有一个 tests 目录,其中也具有自己的 Android.mk 和 AndroidManifest.xml 文件,这是另一个工程,是 HelloActivity 工程的测试程序。
4.2.1.Android.mk 文件
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := HelloActivity
Android入门到精通详解
LOCAL_SDK_VERSION := current include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))
Android.mk 文件是 Android 编译过程中通用的工程管理文件,本地程序、
本地库和 Java 程序包都使用这个文件。这个文件仅仅在基于源代码开发的情况 中使用,在 Java 应用程序工程的管理中,该文件不用定义过多的内容,其中关键 的内容是使用 include $(BUILD_PACKAGE)表示从当前目录编译 Java 应用程序 包 。 LOCAL_PACKAGE_ NAME 定 义 的 是 这 个 程 序 的 APK 包 的 名 称 。 LOCAL_MODULE_TAGS 表示这个包的类型。
这个包的 LOCAL_MODULE_TAGS 定义成了 samples,这将编译 APK 包,
但是不安装在系统中。使用不同的值,可以决定是否编译和安装,例如使用 eng,
package="com.example.android.helloactivity">
<application android:label="Hello, Activity!">
<activity android:name="HelloActivity">
<intent-filter>
com/example/android/helloactivity 中寻找程序中的 Java 源代码。活动名称将被定 义为 HelloActivity,表示活动的代码是上述源代码目录中的 HelloActivity.java 文 件 。 intent-filter 中 的 内 容 指 定 了 程 序 的 启 动 方 式 , 这 里 category 中 的 android.intent.category.LAUNCHER 表示活动将在 Android 的桌面(Android 默认 的桌面程序名称也是 LAUNCHER)上出现。
这里指定 application 的 android:label 为"Hello,Activity!",这和桌面图标下面 的文字以及活动启动后上面的标题文字是一致的。本例没有指定图标,所以桌面 上的图标使用的是默认图标。
在 AndroidManifest.xml 文件中为一个活动指定 label(标签)和 icon(图标)
的方法 如下所示:
<activity android:name="HelloActivity"
android:label="@string/label_name"
android:icon="@drawable/icon_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
android:label 指定为字符串、android:icon 指定为图标后,将使用 res/drawable 中对应名称的图片文件作为图标(本例中将使用 icon_name.png)。
activity 和 application 都具有 android:label 和 android:icon 等属性,由于活动 是程序的单元,且应用可以包含多个活动,因此程序首先将使用 activity 中的这
public class HelloActivity extends Activity { public HelloActivity() { }
@Override
public void onCreate(Bundle savedInstanceState) { // 重载 onCreate()方法 super.onCreate(savedInstanceState);
setContentView(R.layout.hello_activity); // 使 用 hello_activity.xml 布局文件
Android入门到精通详解
} }
这 里 的 类 HelloActivity 继 承 实 现 了 Android 系 统 API 提 供 的 活 动 类
(Activity),使用 setContentView(R.layout.hello_activity)指定了当前活动的布局,
这里表示将从 res/layout 目录中找到 hello_activity.xml 文件作为本例的布局文件使 用。
android:layout_height="fill_parent"
android:textSize="18sp"
<string name="hello_activity_text_text">Hello, World!</string>
</resources>
4.3 HelloActivity 的编译结构
在 Android 的 SDK 环境开发中,HelloActivity 工程经过编译后,SDK 环境下 开发生成的所有目标文件均在当前工程目录中,包含了 assets、bin、gen 等目录。
在 gen 目录中,包含了以类的层次关系为结构的资源文件。例如,gen/com/
example/android/helloactivity 目录中的 R.java 就是 HelloActivity 中的资源文件。
在 bin 目录中,目录结构按照类的关系组织,com/example/android/helloactivity 子目录包含了经过编译后的各个 Java 类,以.class 为后缀。
在 bin 目录中包含的 classes.dex 文件是编译后的,可以在 Dalvik 虚拟机上运 行的 Java 的字节码文件,生成的 HelloActivity.apk 文件是最终的 APK 文件,可 以在兼容的 Android API 的目标系统中安装,进而运行程序。
SkeletonApp 是 Android 中一个应用程序的框架,这个程序比 HelloActivity 复杂一些,这个程序的运行结果如图所示:
Android入门到精通详解
图 SkeletonApp 程序的运行
这个程序包含了两个按钮和菜单,两个按钮分别用于清除编辑文本框中的内
容,菜单的功能和两个按钮时是相同的,点击菜单按钮将出现菜单,菜单是
Android 中的标准组件。
图 使用 SkeletonApp 程序中的按钮和菜单
4.5 SkeletonApp 的源文件结构
SkeletonApp 工程的源文件的结构按照目录树的方式如下所示:
SkeletonApp/
|-- Android.mk (工程管理文件)
|-- AndroidManifest.xml (工程描述文件)
|-- res (资源文件)
| |-- drawable
| | `-- violet.jpg (图片文件)
| |-- layout
| | `-- skeleton_activity.xml (布局文件)
| `-- values
| |-- colors.xml (颜色资源文件)
| |-- strings.xml (字串资源文件)
| `-- styles.xml (样式资源文件)
|-- src (Java 源代码文件)
Android入门到精通详解
`-- com
`-- example `-- android
`-- skeletonapp
`-- SkeletonActivity.java
在 SkeletonApp 中,资源目录 res 中的 values 目录中除了 strings.xml 文 件,还包含了 colors.xml 和 styles.xml 文件,这两种文件也是 Android 中的标准资 源文件。
colors.xml 文件的内容如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Retrieved via Resources.getColor() and friends. -->
<color name="red">#f00</color>
<!-- Retrieved via Resources.getDrawable() and friends. -->
<drawable name="semi_black">#80000000</drawable>
</resources>
styles.xml 文件的内容如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ActionButton">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAppearance">
@style/TextAppearance.ActionButton</item>
</style>
<style name="TextAppearance" parent="android:TextAppearance">
</style>
<style name="TextAppearance.ActionButton">
<item name="android:textStyle">italic</item>
</style>
</resources>
资源目录 res 还包含了 drawable 目录,表示可以绘制的内容,这里的 violet.jpg 是一个 jpeg 的文件。
在布局文件 skeleton_activity.xml 中的部分内容引用了以上的资源
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="4dip" android_paddingRight="4dip"
android:src="@drawable/violet" />
<Button android:id="@+id/clear" style="@style/ActionButton"
android:text="@string/clear" android:textColor="@color/red" />
</LinearLayout>
布 局 文 件 中 引 用 了 上 面 的 资 源 , 颜 色 可 以 作 为 字 体 的 颜 色 , style/ActionButton 作为按钮的样式,drawable/semi_black 表示了背景的内容,
drawable/violet 表示引用 violet.jpg 图片作为图像的内容。例如根据上面 styles.xml 文件中的定义,两个按钮上的字体为斜体,第二个按钮的字体红色。
JAVA 源代码 SkeletonActivity.java 中构建了菜单、按钮的动作等功能。
4.6 SkeletonApp 的编译结构
在这里 drawable 中图片文件保持原状,layout 中的布局文件经过 aapt 处理成 为压缩的文本文件,其他的资源文件在最终的程序包中,不再单独存在。
Android入门到精通详解
第 5 章 Android 应用程序的内容
5.1 Android 应用程序的感念性描述 5.2 应用程序包含的各个文件
5.3 使用 am 工具启动 Android 应用程序
5.1 Android 应用程序的概念性描述
内容提供者(Content Provider)。
一个 Android 应用程序是一个包(Package),包中可能包含一个或者多个
广播接收器用于让应用程序对一个外部事件做出响应。例如:电话呼入事件、
进程正在屏幕的最前端运行一个与用户交互的 Activity(它的 onResume()方法 被调用) ;
进 程 有 一 个 正 在 运 行 的 BroadcastReceiver ( 它 的 BroadcastReceiver.onReceive()方法正在执行) ;
进程有一个 Service,并且在 Service 的某个方法(Service.onCreate()、
Service.onStart()或者 Service.onDestroy())内有正在执行的代码。
(2)可见(Visible)进程
对话框之后,就可能出现这种进程。这样的进程很重要,一般不允许被杀死,除 非为了保证前台进程的运行不得不这样做。
(3)服务(Service)进程
有一个已经用 startService() 方法启动的 Service,虽然这些进程用户无法直接
看到,但它们做的事情却是用户所关心的(例如:后台 MP3 回放或后台网络数
均进入不可见状态(被完全覆盖)。
图 活动(Activity)的生命周期
Android入门到精通详解
活动被恢复的情景:当界面上最前面的活动退出后,它所覆盖的活动将被恢 复,这时 onResume()方法将被调用,活动重新转入前台运行。
活动完全退出的情景:当使用回退(Back)按钮退出活动时,onDestroy() 方法将被调用,活动关闭。如果系统缺少内存时,也会杀死(kill)后台的 活动,其中优先杀死不可见的活动,可见的活动一般不会被杀死。
2. 服务的生命周期
服务可以长时间运行,它的特点是没有可视化界面,服务的生命周期如图 2
所示。
图 服务(Service)的生命周期
使用 StartService 运行服务的情景:使用这种方法启动服务,服务的 onCreate() 和 onStart()这两个方法将被调用,服务会在后台运行直到退出,退出时将调用 onDestroy()方法。
使用 bindService 运行服务的情景:使用这种方法启动服务,调用者(也就是 服务的客户端)将获得和服务交互的类,通过其调用时服务的相关内容会处于活 动状态。
3. 广播接收器的生命周期
Android入门到精通详解
广播接收器有一个单一的回调方法 onReceive(),当广播消息到达接收器时,
Java 源代码 AndroidManifest.xml 资源文件
的字节码集成在一起。资源文件和 AndroidManifest.xml 文件通过 aapt 工具进行处
理。
5.3 使用 am 工具启动 Android 应用程序
am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]
[-w] <COMPONENT>
使用 am start 是其中的一个功能,INTENT 使用的选项如下所示:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>] [<URI>]
主要的参数是使用-a 指定使用的动作(action),使用-d 指定数据(data),
使用 URI 的格式,使用-n 指定组件。
例如:使用 am 启动应用程序的格式如下所示:
# am start -n {包名}/{包名}.活动名
启动 Android 设置工具的命令如下所示:
# am start -n com.android.settings/com.android.settings.Settings
启动 Android 计算器程序的命令如下所示:
# am start -n com.android.calculator2/com.android.calculator2.Calculator
启动 Android 录音机程序的命令如下所示:
# am start -n
com.android.soundrecorder/com.android.soundrecorder.SoundRecorder
# am start -n com.android.camera/com.android.camera.VideoCamera
启动 Android 音乐浏览器的命令如下所示:
# am start -n com.android.music/com.android.music.MusicBrowserActivity
启动 Android 视频浏览器的命令如下所示:
# am start -n com.android.music/com.android.music.VideoBrowserActivity
启动 Android 网络浏览器等的命令如下所示:
# am start -n com.android.browser/com.android.browser.BrowserActivity
在上面的程序中,有些程序位于同一个包中,例如:音乐浏览器和视频浏览 器都在 Music 包中,照相机和摄像机都在 Camera 包中。
对于某些具有附加数据的应用程序,还可以使用-d 选项增加数据 URL,示例如 下所示:
# am start -n com.android.music/com.android.music.MediaPlaybackActivity -d /a.mp3
# am start -n com.android.music/com.android.music.MediaPlaybackActivity -d file: ///a.mp3
# am start -n com.android.camera/com.android.camera.MovieView -d file:///b.mp4
# am start -n com.android.camera/com.android.camera.MovieView -d /b.mp4
# am start -n com.android.camera/com.android.camera.ViewImage -d file:///c.jpg
以 上 程 序 分 别 进 行 了 音 乐 播 放 、 视 频 播 放 、 图 片 浏 览 等 功 能 。 com.android.music. MediaPlaybackActivity 、 com.android.camera.MovieView 和 com.android.camera.ViewImage 分别是对应的应用程序。
对于上述内容,还可以使用 mime type 方式启动程序,如下所示:
# am start -a android.intent.action.VIEW -d file:///a.mp3 -t audio/*
# am start -a android.intent.action.VIEW -d file:///b.mp4 -t video/*
# am start -a android.intent.action.VIEW -d file:///c.jpg -t image/*
这里使用的是 am -a 参数,表示执行一个动作,后面的 audio/*、video/*和 image/*表示数据 mime 类型,Android 将自动找到支持相应数据 mime 类型的程序 来打开对应的音乐、视频和图片文件。
Android入门到精通详解
第三篇 Android 的 UI 系统实现 第 6 章 UI 的基本外形和控制
6.1 控制和基本事件的响应 6.2 键盘事件的响应
6.3 运动事件的处理
6.4 屏幕间的跳转和事件的传递 6.5 菜单的使用
6.6 弹出对话框
6.7 样式的设置
Android UI 系统的知识结构如下图所示:
本小节介绍在 Android 中几种基本的程序控制方法,要获得的效果是通过 2 个按钮来控制一个文本框的背景颜色,其运行结果如图所示:
图 控件事件的响应
6.1.1.事件响应方法
本例构建一个应用程序,其在 AndroidManifest.xml 描述文件中的内容如下所示:
<activity android:name="TestEvent1" android:label="TestEvent1">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
本例定义了一个 Android 中基本的活动。
android:orientation="vertical">
<TextView android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="24sp"
android:text="@string/text1" />
<Button android:id="@+id/button1"
android:layout_width="80sp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/red"/>
<Button android:id="@+id/button2"
android:layout_width="80sp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/green"/>
public class TestEvent1 extends Activity {
private static final String TAG = "TestEvent1";
public TestEvent1() { }
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
final TextView Text = (TextView) findViewById(R.id.text1); // 获得句 柄
final Button Button1 = (Button) findViewById(R.id.button1);
final Button Button2 = (Button) findViewById(R.id.button2);
Android入门到精通详解
Button1.setOnClickListener(new OnClickListener() { // 实现行为功能 public void onClick(View v) {
Text.setBackgroundColor(Color.RED);
} });
Button2.setOnClickListener(new OnClickListener() { public void onClick(View v) {
根据 Button 控件的 setOnClickListener()设置了其中的点击行为,这个方法的参 数实际上是一个 View.OnClickListener 类型的接口,这个接口需要被实现才能够使用,
因此在本例的设置中,实现了其中的 onClick()函数。这样既可实现点击的时候实现相 应的功能,在点击的函数中,将通过 Text 的句柄对其进行控制。
在 Android 的控件使用方面,这两个编程方面要点是:
使用 findViewById()获取布局文件(XML)中控件的句柄;
使用 setOnXXXListener()设置事件处理函数。
在获取句柄时需要转换成相应的控件类型,findViewById()函数的参数是一个整 数,返回值是一个 android.view.View 类型。通过 R.id.XXX 找到布局文件中定义的 ID,
然后通过将基础类转换成其实际的类获得真正的句柄。注意:所转换类必须和布局文 件中描述的控件一致。
SetOnXXXListener()等函数是 android.view.View 类的函数,各种控件(包括
Button、EditText)都扩展这个类,同族的函数包括:
这些函数用于事件处理,它们由程序实现,通过设置这些内容也就设置了控件的 行为。这些函数的参数都是所对应的 android.view.View 类中的方法。
Android 中 UI 基本控制内容:使用 findViewById()联系布局文件中控件和句柄,
并通过 OnClickListener()等定制句柄的行为。
public class TestEvent2 extends Activity implements OnClickListener { // 实现相关的接口
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
mText = (TextView) findViewById(R.id.text1);
public void onClick(View v) {
断,参数是一个 View 类型,通过 getId()获得它们的 ID,使用 switch…case 分别进 行处理。
public class TestEvent3 extends Activity{
Button2_OnClickListener();
public TestEvent3() { }
class Button1_OnClickListener implements OnClickListener { // 接口的第一个 实现
public void onClick(View v) {
mText.setBackgroundColor(Color.RED);
} }
class Button2_OnClickListener implements OnClickListener { // 接口的第一个 实现
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testevent);
mText = (TextView) findViewById(R.id.text1);
final Button mButton1 = (Button) findViewById(R.id.button1);
final Button mButton2 = (Button) findViewById(R.id.button2);
mButton1.setOnClickListener(mListener1); // 设置监听者的类 mButton2.setOnClickListener(mListener2); // 设置监听者的类
} }
本例通过定义实现活动类中的 2 个子类,来实现 View.OnClickListener 这个接口,
这种方式是一种最为直接的方式,即为不同的控件单独实现它的相应类。
图 按键事件的响应
本例的布局文件 testkeyevent.xml 如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/alphavalue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<ImageView android:id="@+id/image"
android:src="@drawable/robot"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
本例包含了一个文本框和一个显示图片的控件,这样可以文本框用作显示当前的
Alpha 的比例值,显示图片的控件 ImageView 用于显示一个图片。
import android.graphics.*;
public class TestKeyEvent extends Activity {
private static final String TAG = "TestKeyEvent";
private ImageView mImage;
private TextView mAlphavalueText;
private int mAlphavalue;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testkeyevent);
mImage = (ImageView) findViewById(R.id.image);
mAlphavalueText = (TextView) findViewById(R.id.alphavalue);
mAlphavalue = 100;
public boolean onKeyDown(int keyCode, KeyEvent msg){
Log.v(TAG, "onKeyDown: keyCode = "+ keyCode);
mAlphavalueText.setText("Alpha = " + mAlphavalue*100/0xff + "%");
return super.onKeyDown(keyCode, msg);
} }
Android入门到精通详解
本例子使用 onKeyDown()函数来获得按键的事件,同类的函数还包括 onKeyUp() 函数,其参数 int keyCode 为按键码,KeyEvent msg 表示按键事件的消息(其中包含 了更详细的内容) 。
上面打出的 log 信息为:
VERBOSE/TestKeyEvent(771): onKeyDown: keyCode = 20
VERBOSE/TestKeyEvent(771): onKeyDown: String = KeyEvent{action=0 code=20 repeat=0 meta=0 scancode=108 mFlags=8}
基本上通过 keyCode 可以获得是哪一个按键响应,而通过 msg 除了按键码之外,
public boolean onTouchEvent(MotionEvent event) public boolean onTrackballEvent(MotionEvent event)
在以上 2 个函数中,MotionEvent 类作为参数传入,在这个参数中可以获得运动 事件的各种信息。
本例介绍另外触摸屏事件的程序,这个程序在 UI 的界面中,显示当前的
MotionEvent 的动作和位置。
图 触摸屏程序的运行结果
本例的程序的代码如下所示:
package com.android.basicapp;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
public class TestMotionEvent extends Activity {
private static final String TAG = "TestMotionEvent";
TextView mAction;
TextView mPostion;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testmotionevent);
mAction = (TextView)findViewById(R.id.action);
mPostion = (TextView)findViewById(R.id.postion);
}
@Override
public boolean onTouchEvent(MotionEvent event) { int Action = event.getAction();
Android入门到精通详解
float X = event.getX();
float Y = event.getY();
Log.v(TAG, "Action = "+ Action );
Log.v(TAG, "("+X+","+Y+")");
mAction.setText("Action = "+ Action);
mPostion.setText("Postion = ("+X+","+Y+")");
return true;
} }
布局文件 testmotionevent.xml 的内容如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/action"
android:textSize = "20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/postion"
android:textSize = "20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
另外一个示例程序,当触摸屏按下、移动、抬起的时候,在坐标处绘制不同颜色
的点,在标题栏中显示当时的动作和坐标。程序的结果如图所示:
图 触摸屏程序的运行结果
public class TestMotionEvent2 extends Activity {
private static final String TAG = "TestMotionEvent2";
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(new TestMotionView(this));
}
public class TestMotionView extends View { private Paint mPaint = new Paint();
mY = 0;
坐标,在 Android 2.0 版本之后,MotionEvent 中还包含了多点触摸的信息,当有多个 触点同时起作用的时候,可以获得触点的数目和每一个触点的坐标。
6.4 屏幕间的跳转和事件的传递
在一般情况下,Android 的每一个屏幕基本上就是一个活动(Activity),屏幕之
Intent
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
Android入门到精通详解
</intent-filter>
</activity>
<activity android:name=".app.ForwardTarget"> </activity>
两个活动的名称分别为 Forwarding 和 ForwardTarget,由于第二个活动没有 intent-filter,因此在程序中只能由第一个活动来启动。
Forward 程序的运行结果如图所示:
图 Forward 程序的运行结果
点击“Go”按钮从 Forward 跳转到 ForwardTarget,这个内容在 Java 源文件 Forward.java 的以下片段中处理:
public void onClick(View v) {
Intent intent = new Intent(); // 建立 Intent intent.setClass(Forwarding.this, ForwardTarget.class); // 设置活动
这里使用的 Intent 的 setClass()的方法的原型如下所示:
Intent setClass(Context packageContext, Class<?> cls)
第一个参数是当前的上下文类型 Context,因此把当前的活动设置过去即可
(Activity 本身继承了 Context),第二个是 Intent 所包含的 JAVA 类,直接设置 ForwardTarget.class 类即可。
android:label="@string/activity_receive_result">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity android:name=".app.SendResult"> </activity>
ReceiveResult 程序的运行结果如图所示:
Android入门到精通详解
图 ReceiveResult 程序的运行结果
初始化界面如图所示,点击“Get Result”按钮将跳转到第二个屏幕,如中图所
示;在第二个屏幕中点击“Corky”和“Violet”按钮将返回第一个屏幕,并获得对应
显示,如右图所示。
startActivityForResult (intent, GET_CODE);
} };
这里调用的是 startActivityForResult()方法,设置一个 GET_CODE 为请求代码,
这样可以获得目标活动的返回信息。这个函数的原型为:
public void startActivityForResult (Intent intent, int requestCode)
被跳转的目标的 Java 源文件 SendResult.java 的代码片段如下所示:
private OnClickListener mCorkyListener = new OnClickListener() {
private OnClickListener mVioletListener = new OnClickListener() {
onActivityResult()函数来实现,两个整数类型的参数 requestCode 和 resultCode 分别代 表请求代码和结果码,第三个参数 Intent(类型 data)表示活动间交互附加的数据信 息。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
text.append(") ");
if (data != null) {
text.append(data.getAction());
} }
text.append("\n");
} }
这里 onActivityResult()是一个被继承的函数,其参数 data 就是这个活动作为返回 值接受到,data.getAction()可以从返回的 Intent 中取回内容。
这里的参数 requestCode 也是根据当时的在调用 startActivityForResult()的时候指 定的返回值。
Android 中使用 Intent 并使用 startActivity()和 startActivityForResult()调用一个新 的活动,实现屏幕的跳转功能,调用者可以获得跳转对象的返回信息。
6.5 菜单的使用
菜单是屏幕中比较独立的一个元素,它和普通的控件略有不同,很多 GUI 系统 都对菜单有单独的接口和运作方式。在 Android 中具有单独接口,用于在活动中使用 菜单。
本例使用一个菜单来控制按钮的背景颜色,从其中可以了解如何在应用程序中使
用菜单。
图 菜单示例程序的运行结果
建立菜单和调用的代码片段如下所示:
package com.android.basicapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.graphics.Color;
import android.view.View;
import android.view.Menu;
import android.view.Gravity;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
import android.util.Log;
public class TestMenu extends Activity {
Android入门到精通详解
private static final String TAG = "TestMenu";
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.testmenu);
mButton = (Button) findViewById(R.id.color_button);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) {
return super.onOptionsItemSelected(item);
} }
使用菜单主要通过重载 Activity 中的两个函数来实现:
public boolean onCreateOptionsMenu(Menu menu) public boolean onOptionsItemSelected(MenuItem item)
菜单类在 Android 中表示为 android.view.Menu 类。使用这个类可以进行一些更 为细节的设置和操作。
abstract MenuItem add(int groupId, int itemId, int order, CharSequence title) abstract MenuItem add(int groupId, int itemId, int order, int titleRes)
add()的第 1、2 个参数是整数值,分别代表按钮项的组 ID 和选项 ID,第 3 个参 数用于设置按钮上的文件。
6.6 弹出对话框
在 GUI 程序中,有时需要弹出对话框来提示一些信息。这些对话框比一个独立 的屏幕简单,在 Android 中弹出式对话框不同于表示一个屏幕的活动,它通常用于简 单的功能处理。
对话框的父类是 android.app.Dialog,通过构建类 android.app.AlertDialog 来实现 弹出式对话框,可以使用 AlertDialog.Builder 和不同的参数来构建对话框。
参考示例程序:Dialog(ApiDemo => App=>Dialog)
源代码:com/example/android/apis/app/AlertDialogSamples.java 布局文件:alert_dialog.xml
Dialog 程序的运行结果如图所示:
Android入门到精通详解
图 Dialog 程序的运行结果
通过点击屏幕上的不同按钮(第 4 个按钮除外)将会启动不同的对话框。
实现方法是继承 onCreateDialog()函数,返回一个 Dialog 类型:
@Override
protected Dialog onCreateDialog(int id) { }
onCreateDialog()函数的参数 id 是区分对话框的标示,当调用对话框的时候需要 调用 showDialog()。
public final void showDialog (int id)
showDialog()函数也是通过 id 来区分对话框。 通过 showDialog()和 onCreateDialog() 函数可以统一活动中的对话框。
6.6.1. 提示信息和两个按钮的对话框
第 1 个按钮(OK Cancel dialog with a message)启动一个提示信息和两个按钮的
对话框,如图所示:
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_two_buttons_title)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 右键事件 */
} })
其中,setPositiveButton 表示设置的左面的按钮,setNegativeButton 表示设置 的右面的按钮,这两个按钮是确定的,但是可以设置其显示的字符和点击后的行为函 数。
6.6.2. 提示信息和三个按钮的对话框
第 2 个按钮(OK Cancel dialog with a long message)启动一个提示信息和三个按 钮的对话框,如图所示:
Android入门到精通详解
图 提示信息和三个按钮的对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_two_buttons_msg) .setMessage(R.string.alert_dialog_two_buttons2_msg)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 左键事件 */
} })
.setNeutralButton(R.string.alert_dialog_something, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { /* 中键事件 */
} })
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
图 列表项对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setTitle(R.string.select_dialog)
.setItems(R.array.select_dialog_items, new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { String[] items =
getResources().getStringArray(R.array.select_dialog_items);
new AlertDialog.Builder(AlertDialogSamples.this)
.setMessage("You selected: " + which + " , " + items[which]) .show();
} })
这里使用了 setItems()表示设置几个不同的项目,从 res/values/array.xml 文件中取 得 select_dialog_items 的内容,这部分内容如下所示:
<string-array name="select_dialog_items">
<item>Command one</item>
<item>Command two</item>
<item>Command three</item>
<item>Command four</item>
</string-array>
这里的 Item 也设置了点击函数,因此它们被点击后,也会弹出新的对话框。
Android入门到精通详解
6.6.4. 单选项和按钮对话框
第 5 个按钮(Single choice list)启动一个单选项和按钮对话框;
图 单选项和按钮对话框
代码实现的片断如下所示:
return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_single_choice)
.setSingleChoiceItems(R.array.select_dialog_items2, 0, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { }
})
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* 右键事件 */
} })
本 例 是 一 个 包 含 单 选 项 的 对 话 框 , 其 中 的 选 项 使 用 了 更 简 单 的 模 式 , 从 res/values/array.xml 文件中取得 select_dialog_items2 中的内容作为单选项的项目。
这部分的内容如下所示:
<string-array name="select_dialog_items2">
<item>Map</item>
<item>Map</item>