Android是什么?
作者:Mark L. Murphy
Android是一个用于移动设备的软件栈(software stack),包括一个操作系统,中间件,和一些关键应用软件。Android SDK提供了采用Java语言在Android平台上开发应用程序的一些必要的工具和API。
特点
Ø 应用程序框架。可重用和替换组件
Ø Dalvik虚拟机。针对移动设备进行了优化
Ø 集成浏览器。基于开源的WebKit引擎
Ø 图像优化。通过一个传统的2D图库支持;基于OpenGL ES 1.0规范的3D图像(可选的硬件加速)
Ø SQLite。结构化数据存储
Ø 多媒体支持。音频,视频,静态图片(MPEG4,H.264,MP3,AAC,AMR,JPG,PNG,GIF)
Ø GSM电话。(依赖于硬件)
Ø 蓝牙,EDGE,3G和WiFi。(依赖于硬件)
Ø 照相机,GPS,指南针,加速计。(依赖于硬件)
Ø 丰富的开发环境。包括一个设备模拟器,调试工具,内存和性能剖面图,Eclipse插件
Android架构
下图展示了Android操作系统的主要组件。每一部分会在后面详细描述。
应用程序
Android包含一组核心的应用程序,包括: 电子邮件客户端,SMS程序,日历,地图,浏览器,通讯录等。所有的应用程序用Java语言实现。
应用程序框架
开发人员可以和核心应用程序使用同样的框架API。应用架构的设计可以简化组件的重用;任何应用程序可以发布其功能,任何其他的应用程序都可以使用这些功能(必须服从于框架的安全限制)。同样的机制允许组件可以被用户替换。
在所有应用程序之下是一组服务和系统,包括
Ø 一组完善且可扩展的用于构建应用程序的视图,包括:列表,网格,文本框,按钮,可嵌入的Web浏览器
Ø 使应用程序可以访问其他应用程序(如通讯录)数据或共享自己数据的内容提供者
Ø 一个资源管理器,用于访问非编码的资源,如:本地化的字符串,图像,布局文件
Ø 一个通知管理器,使所有应用程序可以在状态条显示警告
Ø 一个活动管理器,控制应用程序的生命周期,提供导航栈
更多有关应用程序的细节,请看开发一个Android应用程序
库
Android包含一组被多个Android系统组件使用的C/C++库。这些功能通过Android应用程序框架提供给开发者使用,一些核心库如下:
Ø C系统库。一个源于BSD实现的标准C系统(libc),并已被调整以用于基于Linux的嵌入式设备
Ø 多媒体库。基于PacketVideo的OpenCORE;该库支持多种流行格式的音频和视频的重放和记录,同样支持静态图像文件,如:MPEG4,H.264, MP3, AAC, AMR, JPG, PNG
Ø 表面管理器。管理显示子系统的使用,从多个应用无缝集成2D和3D图像层
Ø LibWebCore。一个现代的Web浏览器引擎,支撑Android浏览器和一个嵌入式的Web视图
Ø SGL。底层的2D图像引擎
Ø 3D库。一个基于OpenGL ES 1.0 API的实现;该库利用硬件3D加速(如果可用)或者高度优化的3D软件光栅
Ø FreeType。位图和矢量字体展现
Ø SQLite。一个共所有应用程序使用的强大的轻量级关系数据库引擎
Android运行时
Android包含一组核心库提供大部分Java语言核心库所提供的功能。
所有Android应用程序在其自己的线程内运行,用于独立的Dalvik虚拟机实例。Dalvik被实现以支持单设备可高效运行多个虚拟机实例。Dalvik虚拟机执行Dalvik可执行文件格式(.dex)的文件,该格式以被优化以保证最小化的内存痕迹。虚拟机是基于注册可用,运行被“dx”工具转换为.dex格式的class文件,class文件通过Java语言编译器编译。
Dalvik虚拟机依赖与Linux内核提供底层的线程管理和底层内存管理。
Linux内核
Android依赖于Linux2.6提供核心系统服务,如:安全,内存管理,进程管理,网络协议栈,驱动模型。Linux内核同时扮演硬件和其它软件栈之间的抽象层。
使用XML进行布局
虽然纯粹通过Java代码在activity上创建和添加部件,在技术上是可行的,我们在第4章中做的一样,更常见的方法是使用一种基于XML的布局文件。动态的小部件实例保留更多,情况复杂,小工具在编译时不为人所知(例如,在数据检索了互联网基础上将单选按钮填充柱。
考虑到这一点,现在是时候打破XML来学习如何用此种方式来布置Android activities。
什么是基于XML的布局?
正如其名称所示,一个基于XML的布局是一个关系到每个规格的小部件,和他们的容器(更多关于此内容的在第7章)编码的XML格式。具体来说,Android认为基于XML的布局是资源,因此布局文件存储在res /在你的Android项目布局目录中。
每个XML文件包含一个指定的部件和容器布局元素树,一种意见认为构成层次。对XML元素的属性,描述一个部件应如何看或者一个容器应如何运转。例如,如果一个按钮元素。
有一个Android的属性值:文字样式=“bold”,这意味着该文本出现在按钮的表面应该是呈现一个粗体字体样式.
Android的SDK中附带一个使用的布局的工具(aapt)。这个工具应自动调用你的Android工具链(例如,Eclipse中,Ant’s build.xml)。作为一个开发人员,尤其重要的是,在您的项目中aapt生成R.java源文件,让您能在那些布局中直接从Java代码中获取布局和部件。
为什么使用基于XML的布局?
使用XML布局文件做的大部分都可以通过Java代码。例如,你可以使用setTypeface()命令一个按钮使用粗体文本,而不是在一个XML布局中使用属性。由于XML布局是为你跟踪的另一个文件,所以我们需要好的理由来使用这样的文件。
也许最大的原因是为了在视图定义中协助工具的建立,如IDE中一个GUI创建者像Eclipse或者一个像DroidDraw1设计GUI图形用户界面建设者。这样GUI建设者们,在原则上,生成Java代码而不是XML。目前的挑战是重新阅读用户界面的定义,以支持编辑,也就是说,
如果是像XLM的结构公式数据比一个程序语言中的数据简单的多。此外,保持生成的XML定义从手写的Java代码中分离,使得某人定制的来源意外重新生成不太可能。
XML形成一个良好的中间立场,使工具作家使用更简便,程序员需要时手工工作更简易。
此外,XML作为一个GUI定义格式是越来越普遍。微软的XAML,Adobe的Flex,和Mozilla的XUL都采取Android类似的方法:把布局细节放在一个XML文件和把编程智慧资料放在源文件(例如,XUL中的JavaScript)。许多不太知名的图形用户界面框架,如ZK,还使用视图定义的XML。而“随大流”并不一定是最好的政策,但他们有优势帮助从任何其他XML为中心的观点描述语言轻松进入Android。
使用基本部件
每一个GUI工具包都有一些基本的部件:字段,标签,按钮等,Android的工具包在范围内没有不同,其基本部件将提供一个良好的介绍,关于这些部件在Android activities中是如何运行的。
指派标签
最简单的部件是标签,在Android提到的作为一个TextView。像大多数的GUI工具包,标签的文本是不可被用户直接编辑的。通常情况下,它们被用来确定相邻部件(例如,一个“姓名:”一个填充姓名前的标签)。
在Java中,你可以通过创建一个TextView的实例l来创建一个标签。更常见的,虽然,
你将通过添加一个TextView元素到布局来在XML布局文件中创建标签,与一个Android:文本属性来设置标签的本身价值。如果您需要交换基于某些标准的标签,例如国际化,你可能想使用XML中的资源参考代替,这些将在第9章叙述。 TextView有许多相关的其他标签属性,如:
• android:typeface to set the typeface to use for the label (e.g., monospace)
• android:textStyle to indicate that the typeface should be made bold (bold), italic (italic),
or bold and italic (bold_italic)
• android:textColor to set the color of the label’s text, in RGB hex format (e.g., #FF0000
for red)
例如,在Basic/Label项目中,你将找到下列布局文件:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="You were expecting something profound?"
/>
正如你看到的图6-1,
图6-1 示例应用程序的LabelDemo
只是单独的布局,由android的项目生成器提供的Java源的(如activityCreator),生成应用程序。
按钮,归属于谁?
我们已经在第4和第5章看到了按钮部件用法。按钮是文本视图的一个子类,所以一切都在上一节讨论了,按钮格式所面临的问题仍然成立。
短暂的图像
Android有两个部件,来帮助你将照片嵌入activities:ImageView和ImageButton。
正如名称所暗示的,他们是分别对于文本视图和按钮基于图像的类似物。
每个部件带有一个android:src属性(在一个XML布局中),指明使用什么图片。这些通常引用一个可绘制的资源,在讲资源的这个章节中更详细地描述了。您还可以通过setImageURI()从内容提供商在Uri基础上设置图像。
ImageButton控件,一个ImageView子类,混合在标准按钮行为中,应对点击和诸如此类的东西。
例如,从Basic/ImageView样本项目中看main.xml布局,这可以在http://apress.com以及所有其他代码示例种找到。
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/icon"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:src="@drawable/molecule"
/>
结果,只用代码生成activity,如图6-2所示。
图6-2 示例应用程序的ImageViewDemo
绿色字段或者其他色彩
紧接着按钮和标签,字段是大多数GUI工具包的第三个“锚”。在Android中,他们通过EditText部件运行,它是标签的一个子类TextView。
随着标准TextView属性(例如,Android:文本样式),EditText有许多其他方面可以帮助你创建字段,包括:
• android:autoText, to control if the field should provide automatic spelling assistance
• android:capitalize, to control if the field should automatically capitalize the first letter
of entered text (e.g., first name, city)
• android:digits, to configure the field to accept only certain digits
• android:singleLine, to control if the field is for single-line input or multiple-line input
(e.g., does <Enter> move you to the next widget or add a newline?)
除了这些,你可以使用专门配置字段输入方法,如android:仅数字输入numeric,android:为笼罩密码输入密码,还有Android:phoneNumber进入电话号码。如果你想创建自己的输入
法计划(如邮政编码,社会安全号码),您需要创建自己的执行情况InputMethod接口,然后通过android设定字段来使用:inputMethod。
例如,从the Basic/Field项目,这里是一个XML布局文件显示 EditText:
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/field"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:singleLine="false"
/>
请注意android:singleLine是错误的,因此,用户将能够输入几行文字。对于这一项目,FieldDemo.java文件填充了一些散文输入栏:
package com.commonsware.android.basic;
import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;
public class FieldDemo extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
EditText fld=(EditText)findViewById(R.id.field);
fld.setText("Licensed under the Apache License, Version 2.0 " +
"(the \"License\"); you may not use this file " +
"except in compliance with the License. You may " +
"obtain a copy of the License at " +
"http://www.apache.org/licenses/LICENSE-2.0");
}
}
结果,一旦建成并投入安装成模拟器,如图6-3所示。
图6-3 示例应用程序的FieldDemo
注意:Android的模拟器只允许在每一个独特的Java包发射器中应发射用。由于本章中的所有演示共享com.commonsware.android.basic包,您将只能在你的模拟器发射的任何时候的看到这些演示之一。
另一个字段的特色,提供自动完成,以帮助用户在整个无文本输入一个值。这是作为AutoCompleteTextView部件在Android中提供的并将在第8章讨论。
另一种复选框
经典的复选框有两种状态:选中的和未选中的。在这两种状态之间点击复选框切换来
指示选择(例如,“添加快递到我的命令”)。
在Android中,还有一个CheckBox控件,以满足这种需要。它作为一个TextView先驱,因此您可以像Android使用TextView性能:格式部件添加文字颜色。
在Java中,你可以调用:
• isChecked() to determine if the checkbox has been checked
• setChecked() to force the checkbox into a checked or unchecked state
• toggle() to toggle the checkbox as if the user checked it
此外,当复选框的状态发生改变时,你可以注册一个侦听器(这种情况下,一个OnCheckedChangeListener实例)来提醒。
例如,从the Basic/CheckBox的项目,这里是一个简单的复选框的布局:
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This checkbox is: unchecked" />
相应的CheckBoxDemo.java检索和配置checkbox的行为:
public class CheckBoxDemo extends Activity
implements CompoundButton.OnCheckedChangeListener {
CheckBox cb;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
cb=(CheckBox)findViewById(R.id.check);
cb.setOnCheckedChangeListener(this);
}
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
cb.setText("This checkbox is: checked");
}
else {
cb.setText("This checkbox is: unchecked");
}
}
}
请注意为复选框的状态变化activity作为其自身监听器,因为它执行OnCheckedChangeListener 分界面(通过cb.setOnCheckedChangeListener(this))。回调侦听器在onCheckedChanged(),它接收复选框的状态有什么新的变化和状态。在这种情况下,我们更新了文本的复选框来反映复选框中包含的实际内容。
结果呢?点击复选框立即更新其内容,你可以看图6-4和6-5。
图6-4 CheckBoxDemo示例应用程序,未选中的复选框
图6-5 同样的应用,选中的复选框
打开收音机
由于与其他单选按钮在其他工具包执行时,Android的单选按钮是两种状态,如复选框,但可分为这样,只有一组中的单选按钮可以随时选中。
像复选框,RadioButton从CompoundButton中继承,从而继承了TextView。因此,所有的标准TextView的字体,样式,颜色等特性,可用于控制单选按钮的外观。同样,您可以在一个单选按钮上调用isChecked(),看看它是否被选中,切换()来选择它,等等,就像你可以用一个复选框。
大多数时候,你会想要在RadioGroup里面放进一个RadioButton的小部件。该RadioGroup表明其状态的单选按钮设置联系在一起,这意味着只有一个按钮退出组可以在任何时间选择。如果您指派一个android:在您的XML布局中ID到你的RadioGroup,您可以访问您的Java代码和调用组:
• check() to check a specific radio button via its ID (e.g., group.check(R.id.radio1))
• clearCheck() to clear all radio buttons, so none in the group are checked
• getCheckedRadioButtonId() to get the ID of the currently-checked radio button (or -1 if
none are checked)
例如,the Basic/ RadioButton的示例应用程序,这里是一个XML布局显示一个RadioGroup包装的RadioButton的部件集合:
<?xml version="1.0" encoding="utf-8"?>
<RadioGroup
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RadioButton android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rock" />
<RadioButton android:id="@+id/radio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scissors" />
<RadioButton android:id="@+id/radio3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Paper" />
</RadioGroup>
图6-6显示了使用Android生成的Java项目和此布局的结果:
图6-6 示例应用程序的RadoiButtonDemo