Microsoft Word - 第3章.doc

Similar documents
OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Microsoft Word - 第1章 Android基本概念.docx

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

書面

Lecture01_Android介绍

0511-Android程式之GPS應用_專題週記4

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页

Microsoft PowerPoint - 03 开发入门.ppt [兼容模式]

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之

Android 开发快速入门 第 章.1 开发环境的搭建 在开始 Android 开发之旅启动之前, 首先要搭建环境,Android 开发环境的安装和配置是 开发 Android 应用程序的第一步, 也是深入 Android 平台的一个非常好的入口.1.1 开发准备工作 配置 Android 开发环

Dynamic Layout in Android

Android Android Android SDK iv

_banneradview.settest(true); _banneradview.setuserkeywords("swimming"); _banneradview.setusercategories("1,3,4"); _banneradview.setusergender(jdbanner

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

03 开发入门.key

Android Service

PowerPoint 簡報

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple

建模与图形思考

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e

X713_CS_Book.book


小应用 Magic8

1

软件工程文档编制

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7.

建立Android新專案

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc

Android Fragment

幻灯片 1

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

ShareText

IDEO_HCD_0716

RxJava

ChinaBI企业会员服务- BI企业


Android + NFC

人民邮电

xforce keygen microsoft office 2013

手册 doc

内文-2.indd

图 6-1 主界面 MainActivity 界面对应的布局文件 (activity_main.xml) 如下所示 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="

01

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

使用Cassandra和Spark 2.0实现Rest API服务

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 :

Ioncube Php Encoder 8 3 Crack 4. llamaba octobre traslado General Search colony

3-插件化轻巧之道-林光亮

基于CDIO一体化理念的课程教学大纲设计

Microsoft Word - Broker.doc

Microsoft PowerPoint - 07.Android 介面元件-TableLayout、Toast、AlertDialog

untitled

X513_Book.book

版权声明

静态分析 投放文件 行为分析 互斥量 (Mutexes) 执行的命令 创建的服务 启动的服务 进程 cmd.exe PID: 2520, 上一级进程 PID: 2556 cmd.exe PID: 2604, 上一级进程 PID: 2520 访问的文件 C:\Users\test\AppData\Lo

<4D F736F F D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63>

PowerPoint Presentation

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

Java

ltu

PowerPoint Presentation

Microsoft PowerPoint - 05.Android 介面元件-RelativeLayout、Button、TextVeiw、EditText

Isis Unveiled Pdf Free Download chayanne downgrade london stage militar mapsource

Office Office Office Microsoft Word Office Office Azure Office One Drive 2 app 3 : [5] 3, :, [6]; [5], ; [8], [1], ICTCLAS(Institute of Computing Tech

Microsoft Word - 九月月刊.docx

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

M9 SDK

Microsoft Word - 新1-12.doc

Microsoft Word - QTP测试Flex.doc

建模与图形思考

Chapter #

Microsoft PowerPoint - 02-Servlet-Basics-Chinese.ppt

Java 1 Java String Date

Hive:用Java代码通过JDBC连接Hiveserver

水晶分析师

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

Microsoft Word - 第3章.doc

Android 教學

概述


「西醫基層總額支付委員會《第28次委員會議紀錄

可 Web 编程的NativeUI 设计与实现

Spark读取Hbase中的数据

Chapter 9: Objects and Classes

基于ECO的UML模型驱动的数据库应用开发1.doc

<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63>

浪潮移动应用平台(IMP) V1.1 开发手册--功能扩展(Android)

Microsoft PowerPoint - 05-Status-Codes-Chinese.ppt

<4D F736F F D20B5DA33D5C220B3CCD0F2C9E8BCC6BBF9B4A12E646F6378>

Microsoft Word - CX1000-HMI_程序开发_PLC通讯

2 Java 语 言 程 序 设 计 教 程 简 单 性 Java 语 言 的 语 法 与 C 语 言 和 C++ 语 言 很 接 近, 使 得 大 多 数 程 序 员 很 容 易 学 习 和 使 用 Java 另 一 方 面,Java 丢 弃 了 C++ 中 很 少 使 用 的 很 难

拦截器(Interceptor)的学习

Photoshop CS6 艺术设计案例教程 ( 第二版 ) 1.1 Photoshop 的应用领域 Photoshop,,, Photoshop Photoshop 的用途 Photoshop CIS ( ) ( ) 案例展现 ~ 1

Transcription:

第 3 章 Android 应用程序剖析 用户要想编写出复杂的应用程序, 首先要对 Android 应用程序的构成及程序的内部执行流程有一个清晰的了解 本章通过对一个简单的应用程序的深入剖析, 使读者对 Android 应用程序的构成及执行流程有个清晰的了解 3.1 Android 应用程序目录结构 之前我们已经开发了一个项目名称为 HelloWorld 的 Android 应用程序, 也许你很疑惑, 好像什么都没做, 只是输入了几个名字, 点了几下鼠标, 应用程序就可以运行 这里面到底发生了什么? 本节将对 HelloWorld 程序的目录结构进行详细分析 图 3.1 所示是 Hello World 在 Eclipse 中的目录层次结构, 下面对其中主要的目录极其文件进行介绍 图 3.1 项目目录结构 项目的根下有几个重要的文件 ( 夹 ), 下面详细讲解每个文件夹的功能和作用 src/ 专门存放编写的 java 源代码的包 android 2.1/ 存放 Android 自身的 jar 包 gen/ 该目录不用开发人员维护, 但又非常重要的目录, 该目录用来存放由 Android 开发工具所生成的目录, 该目录下的所有文件都不是用户创建的, 而是由 ADT 自动生成的, 该目录下的 R.java 文件非常重要, 后面会详细介绍 assets/ 该目录用来存放应用中用到的类似于视频文件 MP3 的一些媒体文件 res/ 是 resource 的缩写, 为资源目录, 该目录可以存放一些图标 界面文件 应

第 3 章 Android 应用程序剖析 21 用中用到的文字信息 AndroidManifest.xml 该文件是系 Android 项目的系统清单文件, 它用于控制 Android 应用的名称 图标 访问权限等整体属性 default.properties 该文件一般也不需要手工去更改, 文件存放了项目对应的一些环境配置, 如应用要求运行的最低 Android 版本 资源被编译到最终的 APK 文件里 Android 创建了一个被称为 R 的类, 这样在 Java 代码中可以通过它关联到对应的资源文件 接下来对 res/ 的子目录做更加详细的说明 (1)res/drawable res/ 目录下有三个 dawable 文件夹, 区别只是将图标按分辨率高低来放入不同的目录, 其中, drawable-hdpi 用来存放高分辨率的图标, drawable-mdpi 用来存放中等分辨率的图标, drawable-ldpi 用来存放低分辨率的图标 程序运行时可以根据手机分辨率的高低选取相应目录下的图标 不过, 如果不想准备过多图片, 那么也可以只准备一张图标将其放入三个目录的任何一个中去 (2)res/values 文件夹 1 strings.xml 用来定义字符串和数值, 在 Activity 中使用 getresources().getstring(resourceid) 或 getresources().gettext(resourceid) 取得资源 打开 helloworld 项目的 string.xml, 可以看到如下内容 <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">helloworld</string> <string name="hello_world">hello world!</string> <string name="menu_settings">settings</string> </resources> 每个 string 标签声明了一个字符串,name 属性指定其引用名 为什么需要把应用中出现的文字单独放在 string.xml 文件中呢? 原因有如下两点 一是为了国际化,Android 建议将在屏幕上显示的文字定义在 strings.xml 中, 如果今后需要进行国际化, 如开发的应用本来是面向国内用户的, 当然要在屏幕上使用中文, 而如今要让应用走向世界, 打入日本市场, 当然需要在手机屏幕上显示日语, 如果没有把文字信息定义在 strings.xml 中, 就需要修改程序内容了 但当我们把所有屏幕上出现的文字信息都集中存放在 strings.xml 文件之后, 只需要再提供一个 strings.xml 文件, 把里面的汉字信息都修改为日语, 再运行程序时,Android 操作系统会根据用户手机的语言环境和国家来自动选择相应的 strings.xml 文件, 这时手机界面就会显示出日语, 这样做国际化非常方便 二是为了减少应用的体积, 降低数据冗余 假设在应用中要使用 我们一直在努力 这段文字 10 000 次, 如果不将 我们一直在努力 定义在 strings.xml 文件中, 而是在每次使用时直接写上这几个字, 这样下来程序中将有 70 000 个字, 这 70 000 个字占 136KB 的

22 精通 Android 应用开发 空间 而由于手机的资源有限, 其 CPU 的处理能力及内存是非常有限的,136KB 对手机程序来说是个不小的空间, 在做手机应用时一定要记住 能省内存就省内存, 而如果将这几个字定义在 strings.xml 中, 在每次使用到的地方通过 Resources 类来引用该文字, 只占用了 14B, 对降低应用体积效果非常有效 当然我们在开发时并不会用到这么多的文字信息, 但是 不以善小而不为, 不以恶小而为之, 作为手机应用开发人员, 一定要养成良好的编程习惯 2 styles.xml 用来定义样式 打开本项目的 style.xml 文件, 内容如下 <resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vxx/styles.xml on newer devices. --> <style name="appbasetheme" parent="android:theme.light"> <!-- Theme customizations available in newer API levels can go in res/values-vxx/styles.xml, while customizations related to backward-compatibility can go here. --> </style> <!-- Application theme. --> <style name="apptheme" parent="appbasetheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> </style> </resources> 注意 :Android 中的资源文件不要以数字作为文件名, 这样会导致错误 (3)res/layout 目录下的布局文件本例中的布局文件是 ADT 默认自动创建的 activity_main.xml 文件 可以用两种方式 Graphical Layout 者 xml 清单显示其中的内容, 在 Eclipse 中, 这两种查看方式可以随意切换 双击打开此 xml 文件, 内容如下 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mainactivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"

第 3 章 Android 应用程序剖析 23 android:layout_centerhorizontal="true" android:layout_centervertical="true" android:text="@string/hello_world" /> </RelativeLayout> 与在网页中布局中使用 HTML 文件相同,Android 在 XML 文件中使用 XML 元素来设定屏幕布局 每个文件包含整个屏幕或部分屏幕, 被编译进一个视图资源, 可以被传递给 Activity.setContentView 或被其他布局文件引用 文件保存在工程的 res/layout/ 目录下, 它被 Android 资源编辑器编译 3.1.1 gen/ 目录下的 R.java 文件详解 R.java 文件中默认有 attr drawable layout string 等四个静态内部类, 每个静态内部类分别对应一种资源, 如 layout 静态内部类对应 layout 中的界面文件, 其中, 每个静态内部类中的静态常量分别定义一条资源标识符, 如 public static final int activity_ main=0x7f030000; 对应的是 layout 目录下的 activity_main.xml 文件 具体的对应关系, 如图 3.2 所示 图 3.2 R.java 中的资源的对应关系图 现在已经理解了 R.java 文件中内容的来源, 也即当开发者在 res/ 目录中任何一个子目录中添加相应类型的文件后,ADT 会在 R.java 文件中相应的匿名内部类当中自动生成一条静态 int 类型的常量, 对添加的文件进行索引 如果在 layout 目录下再添加一个新的界面, 那么在 public static final class layout 中也会添加相应的静态 int 常量 相反, 在 res 目录下删除任何一个文件, 其在 R.java 中对应的记录会被 ADT 自动删除 再比如说, 在

24 精通 Android 应用开发 strings.xml 添加一条记录, 在 R.java 的 string 内部类中也会自动增加一条记录 R.java 文件会给开发程序带来很大的方便, 如在程序中使用 public static final int ic_launcher= 0x7f020000; 就可以找到其对应的 ic_launcher 图片 R.java 文件除了有自动标识资源的 索引 功能外, 还有另一个主要的功能, 当 re s 目录中的某个资源在应用中没有被使用到, 在该应用被编译时系统就不会把对应的资源编译到该应用的 APK 包中, 这样可以节省 Android 手机的资源 3.1.2 组件标识符 通过对 R.java 文件的介绍, 读者已经了解了 R 文件的索引作用, 它可以检索到应用中需要使用的资源 下面介绍如何通过 R.java 文件来引用到所需要的资源 (1) 在 Java 程序当中, 可以按照 Java 的语法来引用 1 R.resource_type.resource_name 注意,resource_name 不需要文件的后缀名 比如, 上面的 ic_launcher.png 文件的资源标识符可以通过如下方式获取 R.drawable.ic_launcher 2 android.r.resource_type.resource_name Android 系统本身自带了很多资源, 用户也可以进行引用, 只是需要在前面加上 android. 以声明该资源来自 Android 系统 (2) 在 XML 文件中引用资源的语法如下 : 1 @[package:]type/name, 使用自己包下的资源可以省略 package 在 xml 文件中, 如 activity_main.xml 以及 AndroidMainfest.xml 文件中通过 @drawable/ ic_launcher 的方式获取 其中 @ 代表 R.java 类, drawable 代表 R.java 中的静态内部类 drawable, /ic_launcher 代表静态内部类 drawable 中的静态属性 ic_launcher 该属性可以指向 res 目录下的 drawable-*dpi 中的 ic_launcher.png 图标 其他类型的文件类似, 凡是在 R 文件中定义的资源都可以通过 @ Static_inner _ classes _name / resourse_name 的方式获取 如 @id/button, @string/app_name 2 如果访问的是 Android 系统中带的文件, 则要添上包名 android: 如 android:textcolor="@android:color/red" (3) @+id/string_name 表达式顺便说一下, 在布局文件当中我们需要为一些组件添加 Id 属性作为标示, 可以使用如下的表达式 @+id/string_name, 其中, + 表示在 R.java 的名为 id 的内部类中添加一条记录 如 "@+id/button" 的含义是在 R.java 文件中的 id 这个静态内部类添加一条常量名为 button, 该常量就是该资源的标识符 如果 id 这个静态内部类不存在, 则会先生成它 通过该方式生成的资源标识符, 仍然可以以 @id/string_name 的方式引用 示例代码片段如下 < RelativeLayout

第 3 章 Android 应用程序剖析 25 android:layout_width = "fill_parent" android:layout_height = "wrap_content" > < Button android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/cancle_button" android:layout_alignparentright = "true" android:id = "@+id/cancle" /> < Button android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_toleftof = "@id/cancle" android:layout_aligntop = "@id/cancle" android:text = "@string/ok_button" /> </ RelativeLayout > 其中,android:id="@+id/cancle" 将其所在的 Button 标识为 cancle, 在第二个 Button 中通过 "@id/cancle" 对第一个 Button 进行引用 3.1.3 AndroidMainfest.xml 详细介绍 每个应用程序都有一个功能清单文件 AndroidManifest.xml( 一定是这个名字 ) 在它的根目录里, 该清单文件给 Android 系统提供了关于这个应用程序的基本信息, 系统在运行任何程序代码之前必须知道这些信息 今后, 我们开发 Activity Broadcast Service 之后, 都要在 AndroidManifest.xml 中进行定义 另外, 如果使用到系统自带的服务如拨号服务 应用安装服务 GPRS 服务等都必须在 AndroidManifest.xml 中声明权限 AndroidManifest.xml 主要包含以下功能 命名应用程序的 Java 应用包, 这个包名用来唯一标识应用程序 描述应用程序的组件 活动 服务 广播接收者 内容提供者 ; 对实现每个组件和公布其功能 ( 比如, 能处理哪些意图消息 ) 的类进行命名, 这些声明使得 Android 系统了解这些组件及它们在什么条件下可以被启动 决定应用程序组件运行在哪个进程中 声明应用程序所必须具备的权限, 用以访问受保护的部分 API, 以及和其他应用程序交互 声明应用程序其他的必备权限, 用以组件之间的交互 列举测试设备 Instrumentation 类, 用来提供应用程序运行时所需的环境配置及其他信息, 这些声明只在程序开发和测试阶段存在, 发布前将被删除 声明应用程序所要求的 Android API 的最低版本级别 列举 application 所需要链接的库 下面以 HelloWorld 项目的功能清单文件为例进行讲解

26 精通 Android 应用开发 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="16" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.helloworld.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> </manifest> 以下详细讲解各个标签 (1)<manifest> 元素 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld" android:versioncode="1" android:versionname="1.0" > 该元素是 AndroidManifest.xml 文件的根元素, 该元素为必选 其中, 根据 xml 文件的语法, xmlns:android 指定该文件的命名空间 功能清单文件会使用 http://schemas. android.com/apk/res/android 所指向的一个文件 package 属性是指定 Android 应用所在的包 android:versioncode 指定应用的版本号 如果应用需要不断升级, 在升级时应该修改该值 android:versionname 是版本名称, 名称的取定可根据爱好而定 (2)<application> 元素 <application android:allowbackup="true" android:icon="@drawable/ic_launcher"

第 3 章 Android 应用程序剖析 27 android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.helloworld.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> <application> 是非常重要的一个元素, 今后, 开发的许多组件都会在该元素下定义, 该元素为必选元素 <application> 的 icon 属性用来设定应用的图标 <application> 的 label 属性用来设定应用的名称 指定其属性值所用的表达式 @string/app_name 含义与上面的表达式 @drawable/ic_launcher 相同, 同样指向 R.java 件中的 string 静态内部类中的 app_name 属性所指向的资源 这里它指向的是 strings.xml 文件中的一条记录 app_name, 其值为 HelloWorld, 因此, 这种表达方式等价于 android:label = HelloWorld (3)<activity> 元素 <activity> 元素的作用是注册一个 Activity 信息, 当我们在创建 HelloWorld 这个项目时, 指定了 Create Activity 属性为 MainActivity, 之后 ADT 在生成项目时帮我们自动创建了一个 Activity 名称就是 MainActivity.java,Activity 在 Android 中属于组件, 它需要在功能清单文件中进行配置 <activity> 元素的 name 属性指定的是该 Activity 的类名 <activity> 元素的 label 属性表示 Activity 所代表的屏幕标题, 其属性值的表达式在上面已经介绍过了, 不再赘述 该属性值在 AVD 运行程序到该 Activity 所代表的界面时, 会在标题上显示该值 (4)<intent-filter> 元素翻译成中文是 意图过滤器 首先简单介绍什么是意图(Intent) 应用程序的核心组件 ( 活动 服务和广播接收器 ) 通过意图被激活, 意图代表的是你要做的一件事情, 代表你的目的,Android 寻找一个合适的组件来响应这个意图, 如果需要会启动这个组件一个新的实例, 并传递给这个意图对象, 后面会有详细介绍 组件通过意图过滤器 (intent filters) 通告它们所具备的功能 能响应的意图类型 由于 Android 系统在启动一个组件前必须知道该组件能够处理哪些意图, 那么意图过滤器需要在 manifest 中以 <intent-filter> 元素指定 一个组件可以拥有多个过滤器, 每一个描述该组件所具有的不同能力 一个指定目标组件的显式意图将会激活那个指定的组件, 意图过滤器不起作用 但是一个没有指定目标的隐式意图只在它能够通过组件过滤器时才能激活该组件 第一个过滤器 <intent-filter>

28 精通 Android 应用开发 <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> 是最常见的, 它表明这个 activity 将在应用程序加载器中显示, 就是用户在设备上看到的可供加载的应用程序列表 换句话说, 这个 activity 是应用程序的入口, 是用户选择运行这个应用程序后所见到的第一个 activity (5) 权限 Permissions HelloWorld 项目的功能清单文件中并没有出现 <Permissions> 元素, 但是 Permission 也是一个非常重要的节点, 在后面的学习中会经常用到 Permission 是代码对设备上数据的访问限制, 这个限制被引入来保护可能会被误用而曲解或破坏用户体验的关键数据和代码 如拨号服务 短信服务等 每个许可被一个唯一的标签所标识 这个标签常常指出了受限的动作 如申请发送短信服务的权限需要在功能清单文件中添加如下语句 <uses-permission android:name="android.permission.send_sms"/> 一个功能 (feature) 最多只能被一个权限许可保护 如果一个应用程序需要访问一个需要特定权限的功能, 它必须在 manifest 元素内使用 <uses-permission> 元素来声明这一点 这样, 当应用程序安装到设备上之后, 安装器可以通过检查签署应用程序认证的机构来决定是否授予请求的权限, 在某些情况下, 会询问用户 如果权限已被授予, 那应用程序就能够访问受保护的功能特性 如果没有, 访问将失败, 但不会给用户任何通知 因此我们在使用一些系统服务, 如拨号 短信 访问互联网 访问 SDCard 时一定要记得添加相应的权限, 否则会出现一些难以预料的错误 应用程序还可以通过权限许可来保护它自己的组件 ( 活动 服务 广播接收器 内容提供者 ) 它可以利用 Android 已经定义 ( 列在 android.manifest.permission 中 ) 或其他应用程序已声明的权限许可, 或者定义自己的许可 一个新的许可通过 <permission> 元素声明 比如, 一个 Activity 可以用下面的方式保护 <manifest... > <permission android:name="com.example.project.debit_acct"... />... <application...> <activity android:name="com.example.project.freneticactivity"... > android:permission="com.example.project.debit_acct"... >... </activity> </application>... <uses-permission android:name="com.example.project.debit_acct" />...

第 3 章 Android 应用程序剖析 29 </manifest> 注意 : 在这个例子里, 这个 DEBIT_ACCT 许可并非仅仅在 <permission> 元素中声明, 如果该应用程序的其他组件要使用到该组件, 那么它同样声明在 <uses-permission> 元素里 (6) 库 Libraries 每个应用程序都链接到缺省的 Android 库, 这个库包含了基础应用程序开发包 ( 实现了基础类如活动 服务 意图 视图 按钮 应用程序 内容提供者等 ) 然而, 一些包处于它们自己的库中 如果你的应用程序使用了其他开发包中的代码, 它必须显式地请求链接到它们 这个 manifest 必须包含一个单独的 <uses-library> 元素来命名每一个库 如在进行单元测试的时候需要引入其所需要的库 代码片段如下 : <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="android.test.runner" /> </application> 3.2 Android 应用程序的执行流程 经过前面对 Android 项目目录结构的介绍, 以及相关文件的讲解, 我们对许多细节已经有所了解, 只是 Android 程序是如何执行呢? 下面做一个总结 发布程序到手机上之后, 当双击该应用的图标时, 系统会将这个点击事件包装成一个 Intent 该 Intent 包含两个参数 { action : "android.intent.action.main", category : "android.intent.category.launcher" }, 这个意图被传递给 HelloWorld 这个应用之后在应用的功能清单文件中寻找与该意图匹配的意图过滤器, 如果匹配成功, 找到相匹配的意图过滤器所在的 Activity 元素, 再根据 <activity> 元素的 name 属性来寻找其对应的 Activity 类 接着 Android 操作系统创建该 Activity 类的实例对象, 对象创建完成之后, 会执行到该类的 oncreate 方法, 此 OnCreate 方法是重写其父类 Activity 的 OnCreate 方法而实现 oncreate 方法用来初始化 Activity 实例对象 如下是 HelloWorld.java 类中 oncreate 方法的代码 @Override protected void oncreate(bundle savedinstancestate) { } super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); 其中,super.onCreate(savedInstanceState) 的作用是调用其父类 Activity 的 OnCreate 方法来实现对界面的画图绘制工作 在实现自己定义的 Activity 子类的 OnCreate 方法时一定

30 精通 Android 应用开发 要记得调用该方法, 以确保能够绘制界面 setcontentview(r.layout. main ) 的作用是加载一个界面, 该方法中传入的参数是 R.layout. activity_main, 其含义为 R.java 类中静态内部类 layout 的静态常量 activity_main 的值, 而该值是一个指向 res 目录下的 layout 子目录下 activity_main 文件的标识符, 因此代表着显示 activity_main 所定义的画面 关于 Activity 类的执行流程及其生命周期会在后面的部分详细讲解 Android 程序执行的整个序列图如图 3.3 所示 图 3.3 Android 应用执行序列图 3.3 Android 应用程序的基本组件 在第 1 章中我们提到了 Android 平台的几大优点, 其中, 包括开放性和应用程序平等 的确,Android 最吸引人的特性之一就是应用程序可以利用其他应用程序来完成想要的功能! 例如, 你的应用程序需要用到图片浏览功能, 而这时正好有另一个应用程序已经开发出一个合适的图片浏览程序, 太好了! 你再也不用自己开发图片浏览程序, 而是直接利用已有的程序即可 那么, 如何才能利用别的应用程序中的成果呢? 只需要在必要时启动那个图片浏览功能 这听起来简直不可思议,Android 平台是如何完成这样神奇的工作呢? 与其他计算机平台上的应用程序不同,Android 应用程序没有唯一的启动入口 ( 如 C 语言中 main() 函数入口 ), 一个 Android 应用程序是由多个不同的组件组合而成, 组件之间通过 Intent 来实现通信 Android 系统的基本组件包括 Activity Service BroadcastReceiver ContentProvider 等, 此外, 还包括专门负责在基本组件之间传递消息的 Intent 组件 所有这些组件都必须

第 3 章 Android 应用程序剖析 31 在 AndroidManifest.xml 文件中声明, 这些组件如何协调工作呢? 下面通过一个简单的用户与应用程序交互的例子来说明 Android 程序中上述组件是如何配合的, 这里包含了两个 Activity, 如图 3.4 所示 图 3.4 示例应用程序的结构 首先, 用户通过 Activity 与应用程序交互, 如图中步骤 1 应用程序中的 Activity 通过 Intent 来向 Android 平台请求启动一个能处理打开 Email 的应用程序, 如图中步骤 2 和步骤 3 Android 系统通过 AndroidManifest.xml 中声明的 IntentFilter 找到能处理打开 Email 的应用程序, 如图中步骤 4 和步骤 5 用户与 Email 应用程序进行交互, 如图中步骤 6 Email 应用程序通过 ContentProvider 来使用另一个录音应用程序产生的音频文件, 如图中步骤 7 用户播放刚才的音频文件, 并返回到了之前的应用程序, 此时音频文件仍然会继续播放, 因为 Service 将在后台工作, 如图中的步骤 8 当然, 并不是每个 Android 应用程序都必须包含这些组件, 但是一旦确定了应用程序中需要的组件, 就应该在 AndroidManifest.xml 中声明它们 接下来对这些基本组件做简单地介绍, 使读者对这些组件建立一个大致的认识, 后面章节还会对这些组件详细介绍 3.3.1 Activity Activity 是应用程序的表示层 应用程序中的每个屏幕显示都通过集成和扩展基类 Activity 来实现 Activity 利用 View 来实现应用程序的 GUI, 而手机用户则直接通过 GUI 和应用程序交互, 如应用程序通过 GUI 向用户显示信息, 用户通过 GUI 向应用程序发出指令和响应 例如, 一个短信应用程序, 需要一个 Activity 来显示联系人列表, 同时需要另一个

32 精通 Android 应用开发 Activity 显示用户输入的短信内容, 甚至还可能需要第三个 Activity 显示已收到短信的内容 虽然这些 Activity 整体形成了一个完整的短信程序用户界面, 但实际上每个 Activity 是独立的 当然, 它们也有共同点 每个 Activity 都是继承自 Activity 的子类 应用程序往往由多个 Activity 组成 一个应用程序需要多少个 Activity? 每个 Activity 表示什么样的用户界面? 这些问题都取决于具体的应用程序设计 通常的原则是, 程序启动后显示的第一副画面是应用程序的第一个 Activity, 以后根据应用程序的需要从一个 Activity 跳转到一个新的 Activity 下面这段代码展示了之前的项目 HelloWorld 创建 Activity 的方法 public class MainActivity extends Activity { @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); } 对于每个 Activity, 系统会分配一个默认的窗口 一般情况下, 窗口将沾满整个屏幕 改变默认属性, 窗口大小也是可调整的 窗口的显示位置也可以悬浮在其他窗口之上 Activity 同时也能使用别的窗口, 为了提醒用户, 可以在一个 Activity 中使用弹出对话框 Activity 窗口内的可见内容通过 View 提供,View 对象继承自 View 类, 每个 View 对象控制这窗口内的一个巨型空间 View 是一种层次结构, 父 View 包含的布局属性会被子 View 继承 位于 View 层次关系最底部的子 View 对象所代表的矩形空间就是跟用户进行交互的地方 例如, 我们可以用一个 View 对象来显示图片, 并在用户点击图片时产生相应的动作 Android 自带了很多不同的 View 供开发者使用, 如按钮 文本框 滚动条 菜单项等, 这些内容会在后续章节进行详细介绍 既然 Activity 的内容通过 View 来显示, 那么如何才能将 View 对象放入 Activity 中呢? 可以调用 Activity.setContentView(), 如上面代码中的最后一行 3.3.2 Service Service 与 Activity 的地位是并列的, 它也代表一个单独的 Android 组件 但与 Activity 相反,Service 没有可见的界面, 它的特点是能长时间在后台运行, 也可以这样理解,Service 是具有一段较长生命周期且没有用户界面的程序 为什么我们需要长时间在后台运行的 Service? 想想音乐播放器! 可能在播放音乐的同时去编辑短信或浏览网页, 就像笔者现在就一边写书一边听着音乐, 这种情况下音乐播放器不可能一直处于前台 为了让音乐一直播放下去, 需要将播放音乐的任务放在后台 这样, 即使音乐播放器已经不再显示了, 用户仍然可以听到音乐 所以, 我们需要这样的机制 长时间在后台运行的 Service 与 Activity 组件需要集成 Activity 基类相似,Service 组件需要继承 Service 基类 一个 Service 组件被运行起来后, 它将拥有自己独立的生命周期

第 3 章 Android 应用程序剖析 33 3.3.3 BroadcastReceiver BroadcastReceiver 是用户接受广播通知的组件 广播是一种同时通知多个对象的事件通知机制 Android 中的广播通知要么来自系统, 要么来自普通应用程序 很多事件都可能导致系统广播, 如手机所在的时区发生变化, 电池电量低, 用户改变系统语言设置等 当然也有广播来自应用程序, 比如, 一个应用程序通知其他应用程序某些数据已经下载完毕 为了响应不同的事件通知, 应用程序可以注册不同的 BroadcastReceiver, 而所有的 BroadcastReceiver 都继承自基类 BroadcastReceiver 需要说明的是,BroadcastReceiver 自身并不实现图形用户界面, 但是当它收到某个通知消息后,BroadcastReceiver 可以启动 Activity 作为响应, 或者通过 NotificationManager 提醒用户 3.3.4 ContentProvider 在 Android 中, 每个应用程序都使用自己的用户 id 并在自己的进程中运行 这样做的好处是, 可以保护系统及应用程序, 避免被其他不正常的应用程序影响, 每个进程都拥有独立的进程地址空间和虚拟内存 当应用程序彼此间需要共享资源时, 这样的架构必须需要一个妥善的解决方案 例如,Contacts 应用程序内存中保存使用者的联系资料, 当你在 Email 中要填写收信人时, 希望读取 Contacts 内的联系人资料 由于 Contacts 和 Email 这两个应用程序运行在不同的进程中, 因此, 它们无法直接通过内存共享联系人资料 为了解决应用程序间数据通信 共享的问题,Android 提供了 ContentProvider 机制 ContentProvider 能将应用程序特定的数据提供给另一个应用程序使用 数据的存储方式可以是 Android 文件系统, 也可以是 SQLite 数据库, 或者别的合理方式 ContentProvider 继承自父类 ContentProvider, 并且实现了一组标准的接口, 通过这组接口, 其他应用程序能对数据进行读写和存储 然而, 需要使用数据的应用程序并不是直接调用这组方法, 而是通过调用 ContentResolver 对象的方法来完成的 ContentResolver 对象可以与任意 ContentProvider 通信 3.3.5 Intent 和 IntentFileter 严格地说,Intent 并不是 Android 应用的组件, 但是它对于 Android 应用的作用非常大 它是 Android 应用程序内不同组件之间通信的载体 当 Android 运行需要连接不同的组件时, 通常需要借助 Intent 实现 Intent 可以启动应用中另一个 Activity, 也可以启动一个 Service 组件, 还可以发送一条广播消息来触发系统中的 BroadcastReceiver 也就是说, Activity Service BroadcastReceiver 三种组件之间的通信都以 Intent 为载体, 只是不同组件使用 Intent 的机制略有区别 具体组件间如何通过 Intent 进行通信, 后续章节会详细介绍, 在此不再赘述

34 精通 Android 应用开发 3.4 本章小结 本章主要对 Android 应用程序进行了深入剖析, 首先介绍了 Android 应用程序的构成及程序的内部执行流程, 并对一个 Android 应用程序所需要的基本组件功能及其作用进行简单介绍, 使读者对 Android 应用程序的内部执行有一个清晰的认识