2008年12月12日星期五

教程:Notepad程序


教程:Notepad程序


本章的教程手把手介绍Android框架和工具,以便用之建立应用程序。从预先配置的项目文件开始,本教程引导你深入一下过程:简单的Notepad程序开发、提供设置项目的具体例子、开发程序逻辑和UI、编译运行程序。
教程作为一套练习介绍notepad程序的开发,每个联系由几个步骤组成。你可以按照每个联系中的步骤逐步建立和完善你的程序。这些联系详细解释每个步骤,并提供所有你需要的例子代码以完成程序。
当你完成教程时,你会成功创建正常运行的Android程序,并深入了解Android开发的更多重要概念。如果你想计入更多复杂功能到你的程序,你能通过notepad程序的可替换实现来检查代码,notepad程序在“ Sample Code”文档中提及。


谁应该使用这个教程

这个教程为有经验的开发人员设计,尤其是那些拥有JAVA编程知识的人。如果你没有编写过JAVA程序,你仍旧能使用这个教程,但是,你可能需要花费较多的时间,速度较慢。
这个教程假设你已经熟悉基本的Android程序概念和术语。如果你还不熟悉这些,你应该再继续以前阅读“Overview of an Android Application ”
也要注意:这个教程使用Eclipse开发环境,并安装有ADT插件。如果没有使用Eclipse,你能按照练习建立程序,但是你将会决定怎样在你的环境中完成和Eclipse相关的步骤。

准备练习

这个教程建立在“Installing the SDK ”、“Hello Android ”两篇文章的信息之上,这两篇文章详细解释了怎样设置你的开发环境。在你开始这个教程之前,你应该阅读这两篇文章,安装SDK,设置工作环境。
为了这个课程,准备如下:
1.下载项目练习数据包(zip)
2.解压到合适的位置
3.打开NotepadCodeLab文件夹

在NotepadCodeLab文件之内,你应该找到六个项目文件:Notepadv1, Notepadv2, Notepadv3, Notepadv1Solution, Notepadv2Solution 和Notepadv3Solution。Notepadv#项目是每个练习的起点,而Notepadv#Solutio项目是练习的解决方案。如果你在某个练习中有麻烦,你能通过比较你目前的工作和练习解决方案来解决。


练习

下表列举了教程练习,描述了每一条的发展领域。每个联系假定你已经所有前面的联系。

1、练习1
这里还是。构造简单的便签列表,让用户增加新的便签但是不能编辑。展示基本的ListActivity以及创建处理菜单选项。使用SQLite数据库存储便签。
2、练习2
增加第二个活动到程序中。展示构建新活动,增加活动到Android manifest文件,在两个活动之间传递数据,还有使用更高级的屏幕布局。还展示了怎么使用startActivityForResult()调用另外一个活动并返回一个结果.
3、练习3
增加生命周期事件处理到程序中,并让该事件维持生命周期内的程序状态。
4、练习4
展示怎样使用Eclipse调试器,怎样使用调试器来查看生命周期事件。本章是可选的但是强烈推荐。

其他资源以及进一步的学习

* 针对概念的更浅显更广泛的介绍并没有在教程中覆盖,请参考“Common Android Tasks”
* AndroidSDK包含各种各样具有完备功能的例子程序,有极好的机会进一步学习。你能在SDK的samples/目录下找到例子程序。
* 这个教程引入了完整Notepad应用程序,包含在SDK的samples/目录中,尽管它不能完全匹配。当你按照教程做的时候,强烈推荐你仔细看看Notepad程序的这个版本,它展示了多种有趣的补充,比如:
o 针对便签列表,设置一个自定义条纹列表
o 创建一个自定义文本视图,重载draw()方法以便使便签看起来像一个内忖的便签。
针对便签实现一个完整的ContentProvider。
o 还原、丢弃编辑,而不只是自动保存

2008年12月9日星期二

Android程序的解剖

Android程序的解剖

* Activity,即活动
* Broadcast Intent Receiver,即广播接收器
* Service,即服务
* Content Provider,即内容提供商

并不是每个程序都需要所有的这四个组件,但是你的程序将会使用这四个方面的某些部分组合而成。
一旦你已经决定你的应用程序需要的组件,你应该在AndroidManifest.xml文件中列举出来。AndroidManifest.xml是一个XML文件,你在其中声明你的程序的组件以及他们的能力和需求。请阅读“Android manifest file documentation”以了解更详细的资料。

Activity


活动(Activity)是Android生成块的最常用组件。一个活动通常是程序中的一个单一的屏幕。每个活动作为Activity基类的单个的继承类来实现。你的类将会显示一个UI,这个UI由Views(视图)以及对应的事件(event)组成。大多数程序由多个界面组成。例如,一个文本消息程序可能有一个展示发送消息目标的通讯录列表的界面,以及一个写消息到选中的通讯录的界面,还有查询旧消息或者修改设置的其他界面。这些界面的每一个都会被作为一个活动实现。移动到另外一个界面通过启动一个新的活动来完成。一些情况下,一个活动可能返回一个值给上一个活动——例如:一个让用户挑选图片的活动将会返回所选图片给呼叫者。
当一个新界面打开时,前一个界面暂停,放入一个历史堆栈中。用户能回退到历史堆栈中的前一个打开的界面。当不适合保留的时候,界面能从历史堆栈中选出来删除。Android为每个程序从主界面开始的所有界面保留历史堆栈。

Intent(计划)和计划过滤

Android使用一个特殊类调用Intent来从一个屏幕移动到另外一个界面。一个Intent描述了一个应用程序想做什么。intent数据结构的两个最重要部分是动作以及起作用的数据。动作的典型是MAIN(应用程序的入口)、VIEW、PICK、EDIT等。数据表达为一个URI。例如,为了浏览个人的通讯录信息,你会创建一个intent,该intent携带VIEW动作以及描述那个人的URI指向的数据。
有一个相关类称为IntentFilter。当意图(intent)是做什么事情的有效请求时,intent filter是说明活动(或者BroadcastReceiver)能处理的意图(intent),能显示个人通信录信息的活动将会发布一个IntentFilter,以说明活动知道当应用数据描述一个人时怎么处理动作VIEW。活动在AndroidManifest.xml文件中发布他们的IntentFilter。
从一个界面导航切换到另外一个界面是通过解析intent来完成的。为了向前导航,活动调用startActivity(myIntent)。然后系统搜索所有已安装程序的intent filter(意图过滤器),选择intent filter和myIntent最匹配的活动。新活动接到intent的通知,从而导致他启动。解析intent过程发生在运行时,此时startActivity被调用,提供了两个关键好处:
* 活动对于其他组件可以功能重用,只需简单的以Intent的形式发出请求。
* 活动能在任何时候被携带同等的IntentFilter的新活动替换。

广播接收器


当你想程序的代码用于外部事件的反馈时,你可以使用BroadcastReceiver,例如,电话铃声响时,或者,数据网络可获得时,或者午夜时分。BroadcstReceivers不显示UI,尽管他们可以使用NotificationManager来警告用户其感兴趣的事情是否已经发生。BroadcastReceivers在AndroidManifest.xml中注册,但是你也能使用Context.registerReceiver()从代码中注册。你的程序不一定在运行,因为BroadcastReceiver被调用;系统将会启动你的程序,如果必要的话,当BroadcastReceiver被触发的时候。程序也能通过Context.sendBroadcst()发送他们自己的intent广播到其他应用程序。


服务


服务是长期存活的没有UI运行的代码。好例子是从播放列表播放歌曲的媒体播放器。在媒体播放程序中,可能有一到多个活动供用户选择歌曲并开始播放。但是,音乐回放自己不应该被一个活动处理,因为用户希望音乐继续播放即使切换到一个新的界面。这种情况下,媒体播放器活动可使用Context.startService()启动一个后台运行的服务来保持音乐播放。然后,系统会继续运行音乐回放服务直到音乐播放完成。你可以通过阅读“Life Cycle of an Android Application”来了解系统服务的优先级。注意:你可以连接到服务(如果没有运行就启动它),使用方法Context.bindService()。当连接到服务时,你能通过服务暴露的接口和服务通信。对于音乐服务,这可能允许你暂停、重放等。


内容提供者


程序能保存数据到文件,一个SQLite数据库,或者,合理的其他任何机制。但是,内容提供者是有用的,如果你想你的程序的数据和其他程序共享。内容提供者是一个类,实现一个标准方法集,以便其他程序存取内容提供者能处理的的数据类型。
To get more details on content providers, see Accessing Content Providers.
为了了解内容提供者的详细情况,请参见“ Accessing Content Providers”

2008年12月3日星期三

升级UI到XML布局

升级UI到XML布局

你刚完成的“Hello,World”例子使用叫作“programmatic”(编码)UI布局,也就是你直接在源代码中构造和建立你的应用程序UI。如果你做过UI编程,你可能了解道路有时可能非常不容易的:布局小变动可能导致代码方面的大头痛。忘记恰当地融入VIew也是非常容易的,这将导致布局错误,并浪费时间来调试你的代码。
这就是Android提供另外一种UI构造模式:XML布局文件的原因。解释这种模式的最容易的方法是展示一个例子。下面是一个XML布局文件,其行为等同于你刚完成的基于编码构造的例子:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Hello, Android"/>

一个AndroidXML布局文件的普通结构是简单的。它是一棵标记树,每个标记是View类的名称。这个例子是包含一个元素,TextView,的非常简单的树。你可以使用在XML布局文件中View扩展类的名称,包括你在自己代码中定义的自定义View类。这种结构使快速建立UI变得非常容易,相比你在代码中使用的结构和语法,更简单。这种模式对web开发模式更有吸引力,你能隔离应用程序的表示层(UI)和逻辑层(存取数据)。
这个例子中,有四个XML属性。下面总结他们的意思:
(1)xmlns:android
这是一个XML名称空间声明,告诉Android工具:你打算引用在Android名称空间定义的通用属性。在每个Android布局文件中的外层标签必须有这个属性。
(2)android:layout_width
这个属性定义了View使用的屏幕的有效宽度是多少。这个例子中,他是唯一的VIew,所以我们想它占用整个屏幕,“fill_parent”就是这个意思。
(3)android:layout_height
这个属性很像android:layout_width,只是用于规定有效高度。
(4)android:text
这个属性设置TextView应该包含的文本内容。在这个例子中,他是我们司空见惯的"Hello, Android" 信息。

所以,那就是XML布局文件看起来的样子,但是你把它放在哪里呢?放到你的项目下/res/layout目录下。“res”是资源单词的缩写,这个目录存放你的程序需要的非代码资源,包括图片、本地化字符、XML布局文件。
ADT插件为你创建一个XML文件。在我们的上面的例子中,我们简直从来没有使用它。在Package浏览器总,展开文件夹/res/layout,编辑文件main.xml,使用上面的文字提供main.xml的内容然后保存。
马上打开文件r.java,这个文件在Package浏览器的源代码文件夹中。你将会发现它现在看起来像这样:
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.java文件是一个指向文件中定义的所有资源的索引。你在你的源代码中使用这个类,作为一种快捷引用你项目中的资源的方式。这是特别强大的代码完成功能,该功能存在于诸如Eclipse的集成开发环境中,之所以强大是因为他让你快速地、互动地定位你正在寻找的具体引用。
现在要注意的重要事情是名叫“layout”的内嵌类,以及他的成员“main”。ADT插件注意到你增加了一个新的XML布局文件,然后产生了这个r.java文件。当你加入其他资源进入你的项目时,你会发现r.java会跟着改变。
你需要做的最后的事情是使用你的UI的新XML版本而不是硬编码版本来修改HelloAndroid源代码。下面是你的新类看起来的样子,正如你看到的一样,源代码变得非常简单:
package com.android.hello;

import android.app.Activity;
import android.os.Bundle;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

当你做这个修改的时候,不要仅仅拷贝粘贴进入。在那个R类上试试代码完成功能。你可能会发现它会帮助你许多。
既然你已经做了修改,进一步重新运行你的程序,你需要做的所有事情是点击绿色的Run箭头图标,或者选择菜单Run > Run History > Hello, Android。你应该看到...好,和你以前看到的是完全相同的界面!毕竟,这一点是要表明,两种不同的布局方式产生了相同的结果。
创建XML布局文件有更多的知识,但是我们在这里只介绍这么多了。想要知道这种强力方式的更多信息请参见“Implementing a User Interface”。

调试你的工程项目

ADT插件也和Eclipse调试器进行了完美集成。为了证明这点,让我们介绍我们代码的一个BUG。像这样修改你的代码:
package com.android.hello;

import android.app.Activity;
import android.os.Bundle;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object o = null;
o.toString();
setContentView(R.layout.main);
}
}

这个修改引入了一个NullPointerException异常。如果你再次运行你的程序,你最后会在模拟器上看到:


按"Force Quit"来终止应用程序,并关闭模拟器窗口。

为了找出更多的错误,在Object o = null;行上设置断点,设置断点的操作是双击紧靠源代码行的标记栏。从主菜单中选择菜单Run > Debug History > Hello, Android进入调试模式。你的应用程序会在模拟器中重新启动,但是这次她会挂起在你设置的断点处。你能在Eclipse调试视图中单步调试你的代码,正如你为其他任何程序做的事情一样。


没有Eclipse时创建工程项目

如果你没有使用Eclipse,比如如果你喜欢其他IDE,或者简单地使用文本编辑器和命令行工具,那么Eclipse插件不能帮助你。但是,不要太担心,你不会因为不使用Eclipse而损失任何功能。
Android插件实际只是对包含在AndroidSDK内的一套工具的封装,这套工具包括模拟器、AAPT、ADB、DDMS,以及其他在别的地方提到的工具。因此,使用诸如ant建立文件之类的别的工具封装这些工具是可能的。
AndroidSDK包含一个称为“activitycreator.py”的Python描述脚本,这个脚本用于为你的工程项目创建所有的源代码和目录桩,又兼容ant的build.xml。这允许你从命令行建立你的工程项目,或者和你选择的IDE集成。
例如,为了创建一个HelloAndroid项目,和你在Eclipse中创建的一样,你使用如下的命令:
activitycreator.py --out HelloAndroid com.android.hello.HelloAndroid

为了建立项目工程,你运行命令“ant”。当命令成功完成时,你会放置一个文件helloAndroid.apk到bin目录下。.apk文件是一个Android包,能使用adb工具在模拟器中安装和运行。
欲知更多信息,请阅读上面引用的文档。

2008年11月26日星期三

转:从《西游记》和《魔戒》看东西方项目管理

打开电视,电视里正在播放《魔戒第一部.护戒使者》。面对墨多的黑君主索伦无以伦比的可怕力量,一个义无反顾的护戒小队成立了,他们的目标就是墨多的核心地带——末日火山。这看起来就像是一个不可能完成的任务,一开始就面临着难以逾越的劫难。这让我想起了我们的神怪小说《西游记》,同样是一个团队,同样是面临千难万险的征途,但是,中西方文化的差别却在这里表现得淋漓尽致。

首先,我们看看这两个团队的成立

“你挑着担,我牵着马,迎来旭日送走晚霞。。。。”这首歌好像描绘了一个非常和谐的,分工明确、责任清晰的最佳合作团队。但是,这个团队起初只有唐僧一个人,只有唐僧才真正明白此行的目的,一行四人中最坚决的取经者仅此一人而已。其他几位包括白龙马、孙悟空、猪八戒、沙和尚等基本上都是连哄带骗外加紧箍咒强行拉壮丁拉进来的,这几个人各打各的主义,各有各的心思,可以这样说:他们怀着不同的目的,为了同一个目标,走到了一起。

而护戒使者小分队的成立,则完全是另外一个样子。首先在精灵国的林谷会议上,大家对面临的问题非常清晰,索伦要找回魔戒,得到魔戒的索伦将成为不可战胜的力量。那样的话,人类、精灵、矮人、侏儒等一切爱好和平的种族将会面临灭顶之灾,解决问题的唯一办法就是将魔戒带到墨多的核心末日火山,然后将魔戒丢到火山中将其毁灭。但是,达到这个目的的困难是完全不可想象的,其难度完全不亚于去西天取经。这时候,英勇无畏的勇士们站了出来。游侠阿拉贡、战士博罗米尔、精灵莱格拉斯、矮人金利、巫师甘道夫以及几个以弗罗多为首的霍比特人,九个人的护戒使者可以说目的非常明确(皮平除外),而且完全是自发的主动的建立起这个团队。这个团队没有明确的队长,只有带戒人和护戒使者,遇到事情基本上采取协商解决。

从团队建设来看,东方文化带有明显的阶级因素。最高阶级是神,如来佛、观音菩萨、玉皇大帝等,神是法力无边的,与神斗,绝没有好下场,齐天大圣够厉害了吧?最后还不是逃不出如来佛的手心,如来佛一翻手掌就将他压在五界山下永世不得脱身。第二个阶级是师傅唐僧,唐僧作为神的代言人,具有管辖和掌握手下四个徒弟的特权,他忠实地行使神赋予他的权力和义务。但是神给他的权力是明确的,有限的,他只能管理这几个徒儿,除此之外,即便是面对狐狸兔子等最下等的小妖,他也无能为力。再下面是三个人形的徒弟,尽管他们个个长的实在没个人样,但是与连人形也没有修得的白龙马相比,他们显然要高一个阶级。在这个第三阶级里面,每个人的地位也是不平等的,因为唐僧给他们排了座次,大师兄悟空,二师兄八戒,三师弟沙僧,人人都有自己的位置安排,遇到事情大家依据自己的位置发表议论。如果谁违背了这个顺序,后果将不堪设想。唐僧曾经听信了八戒的谗言,忽视了大师兄悟空的权利,孙悟空越想越气,最后一怒之下撂挑子不干了。可见,在西游团队中,需要论资排辈,每个人既定的地位、座次都是非常重要、不可动摇地。最后一个阶级就是大家的奴隶——白龙马。白龙马说起来也是龙的传人,可惜他被神定位为马,从此只能负重行走,没有说话的权利,连吃饭也没份,是一个活脱脱的奴隶。

而西方文化,更看重个人的尊严。在护戒使者这个团队中,每个人都有他存在的价值,他们的地位是平等的。开始时,山姆是弗罗多的仆人,但是弗罗多以及其他小组成员从没有把他当奴隶看,最后,随着大家一起克服重重困难,弗罗多完全把山姆当成了自己的亲兄弟。因为没有不可逾越的阶级,人与神的界限就没有那么明显,黑君主索伦是强悍无比的黑暗势力,但是,只要你有足够的勇气,即便你是一个普通人,一样有可能打败他。

其次,我们来看一看两个团队如何处理所面对的困难

西游团队碰到困难时,师傅是不出面的。就像大话西游里唱得那样:“背黑锅我来,送死你去!”唐僧作为领导,当然是养尊处优的,碰到难处理的事情,你们三个去想办法。这时候,这三个人的责任便很明确,大师兄地位高,自然承担的责任也最大,降妖除怪一般都是大师兄责无旁贷。孙悟空也从来不推托,总是第一个冲了上去,这时候东方文化的良好秩序发挥了效率。由于地位清晰,责任明确,大家该干什么干什么,碰到妖怪,唐僧只要说一句:“悟空,你去看看!”接下来降妖机器便自动运转起来,来一个妖怪是这个打法,来一百个妖怪,也是这个打法。每个人对自己的工作都驾轻就熟,孙悟空自然是打妖的主力,八戒主要保护师傅,有时候是机动力量,由于能力有限,常常充当第二梯队打打二流小妖;沙僧地位最低,责任也最小,只要看好行李物品不要丢失就行了。白龙马是奴隶,没有地位,自然也没有责任,打不打妖和他没有任何关系,谁也不会把责任推到他的头上。

而护戒使者队伍因为大家地位相同,因此碰到怪物的时候,只要喊一声:“大家并肩子上啊!”便人不分老幼,地不分南北一拥而上,打得个不亦乐乎。虽然大家的能力是不一样的,但是杀敌的勇气却是一样的,面对蜂拥而至的妖怪,谁也不能够独善其身,只能拿起武器战斗。这种同进同退的战斗生活,能够加深团队成员之间的友谊,实际上这个团队最终大家都成了生死兄弟。一个兄弟般的团队,其战斗力自然会更强,正所谓:“兄弟同心,其利断金!”正是这个互相关心,共同努力的团队,面对一次次令人绝望的危险,都能够涉险过关。

这两种不同的态度,所造成的后果也是各有千秋。东方人讲秩序,讲责、权、利分工明确,“各人自扫门前雪,莫管他人瓦上霜”这句话便是东方人处世态度的最好写照。作为团队的管理者,最核心的问题就是赏罚分明,只有纪律严明赏罚分明的队伍才是一个有能力的团队。而西方人鼓动人的主动性、积极发挥个人的创造力,要求团队更主动,更合作,团队管理的核心是激发每个人的主观能动性与创造力。


第三,我们再看看两个团队处理问题的方式

西游团队碰到危险,总是按照一定的思维方式来处理。首先,孙悟空会看到一股妖气,或者孙悟空的火眼金睛看出对方是妖怪,然后孙悟空先上去斗法。如果斗法成功,则为民除害,大家继续上路。如果斗法不成功,十有八九唐僧师徒被捉,这时候悟空总是有法子脱身,然后便会去找更厉害的帮手。通常帮手都是是天上位列仙班的大罗神仙,或者观世音菩萨的同道中人。而那些妖怪十有八九都是这些人的家眷、门人或者家禽家畜等等,因为有了这一层关系,便下界为祸人间。对待这些妖怪,孙悟空是搞不定的,因为他们出身高贵,必须找到 他们的上级才能够把问题解决。

西游记的九九八十一难,十有八九是因为高层领导的裙带关系,家属腐败等等原因造成的。所以,尽管取经路上危险重重,但是大家心里并不担心,为什么?因为一切尽在掌握中。所有的磨难或者危险,都是有因有果,都逃不出这四大阶级的天罗地网。只要这个阶级秩序能 够保持稳定,一切困难都会迎刃而解。

因此,西游团队面对问题的时候,他们首先回来分辨这个妖怪到底是什么来历?也就是说,妖怪的出身很重要,知道了妖怪的出身,问题也就解决了一大半了,接下来无非是怎样起出妖怪背后的最大靠山而已。这也符合东方文化的谋定而后动的操作要领,最后收拾妖怪,不过是整个行为的收关之作,整个降妖过程,很多工作都在幕后进行。所谓“功夫在诗外”,诗写道好的关键是你能够有足够的素材。通过自己的人情脉络找出那个真正的谋后主使,才是孙悟空能够降妖除魔的看家本领。

护戒使者所碰到的磨难,往往是突发的,没有任何征兆的,也绝不可能通过外援来调解的。他们没有一个掌控全局的神来主持大局,有的只是正义和邪恶两个完全不可调和的对立面,要么杀死敌人,要么被敌人杀死。水怪、炎魔、布鲁克武士、狼骑士,所有的敌人都是呼啸而来。应付的办法也是出奇的简单,拿起武器拼个你死我活。西方文化当中的正义与邪恶观点相对来说要幼稚的多,与西游团队不同,护戒使者面对敌人时,采取最直接也最有效的解决办法。在这种情况下,一切的运筹帷幄、一切的人情世故都是没用的,取胜只能靠自己的 力量、勇气、信心和敏捷的反应能力。

在应急处理问题的方式上,东西方文化截然不同的反应,给我们很大的启示。面对困难,西方人总是鼓励你主动地、勇敢地去尝试,或许你的方法完全不对,但是只要你有勇气尝试去解决问题,你就会得到尊重。西方文化更看重你解决问题的态度。与此相反,东方人在面临巨大困难的时候,他们首先考虑的是如何解决,或者如何选择最恰当的方式来解决问题。而不是贸然动手,如果你贸然动手,一旦你失败了,可能会招致大量的批评。

这种解决问题的思维方式,已经深深的烙在每一个人的心里。我们在教育方面,会花费大量的精力来告诉学生事物的原理,我们有十万个为什么?我们有格物致知的祖训,我们每个人都在探索事情的规律和论证最佳的解决方案。我们唯独忘了鼓励小朋友大胆去尝试自己的想法;我们总是告诉小朋友正确的解决方法,但是却忘了告诉小朋友如何通过自己的尝试获得正确地解决方案。授人以鱼不如授人以渔,很多人已经发现了我们教育方面的问题,但是扭转局面谈何容易,因为我们的文化根源与西方文化是那么的格格不入。我们的高考制度,考的是你能否给出问题的正确答案,而不是你能否以正确的方式来回答问题。高考制度不改变,模仿西方的所谓素质教育将永远是一句空话。

扯远了,我想如果西游一行碰到得九九八十一难都是像护戒使者面对的那样的敌人的话,唐僧可能已经死了七八十回了。但是,你放心,东方的妖怪也是东方化的。当他们捉住了唐僧,通常都不会便吃,而是要弄清楚齐天大圣走了没有?危险过去了没有?有的妖怪更是可爱的很,他们会很有孝心的邀请自己的长辈来共食,这样的妖怪自然给悟空留下了足够做好后台工作的时间,足以让你找到解决问题的法门。东方的妖怪还是比较仁义的,抓住唐僧后会对悟空说:不是我没给你机会阿,你要抓紧时间来救你师傅啊,你不来救可就莫怪我嘴下不 留情了。

第四,两个故事的结局

西游的结局大家都知道,五个人取经成功修的正果,都脱离苦海成了佛。而护戒使者一行人,除了为此事业献身的波罗米尔,其他人奋斗的结果便是成功阻止了索伦的强大,其结局非常简单。

从两个故事的结局可以清楚地看到,东方人功利思想要重得多,尽管当初一行人各怀鬼胎走上去西天取经之路。但是,当取经成功之后,孙悟空也老是不客气地做起了佛爷,那花果山的猴头看样子到底没有做佛爷来的风光啊。

但是在西方人眼里,成功就是任务的完成,对成功者来说,这件事情本身就够他自豪一辈子了,其他虚名则可有可无。

近年来,西方拍了很多的灾难片,有火山爆发的,有龙卷风的,有地震海啸的,有暴风雪的。在这些片子里,主人公无一例外的尝试去对抗大自然的力量。人类还没有取得应付自然灾害的能力,这时候面对它和解决它的勇气非常重要。东西方文化各有所长,但是,在我们这一代以及我们的下一代,在面对突发事件的情况下,我们的应变能力显然已经落于人后。

从西游记与魔戒这两部神怪小说分析,东西方文化有他根源上的巨大差异。东方文化胜在秩序的稳定和对事物原理孜孜不倦的追求上。而西方文化在人性的尊重,个性化创造力的培养,以及鼓励主动尝试等方面略高一筹。二十一世纪是全球一体化时代,东西方文化的融合将成为大家关心的主题。为了我们的下一代,西方一些优秀的教育理念是值得我们研究和学习的。

Hello, Android!

Hello, Android!

作为一个开发人员,你得到一个开发框架的第一映像是编写“Hello, World!”程序是否容易,对于Android,他是非常容易的。

创建项目

创建项目能有多容易就多容易。获得Eclipse插件使Android开发非常容易。
你需要安装有EclipseIDE的开发计算机,你还需要安装ADT插件。一旦你准备好了,你现在就可以开始进入开发。
首先,下面是高度概括的建立"Hello, World!"程序的方法:
1)在菜单File > New > Project中创建一个新的"Android Project"
2)在New Android Project对话框中填写项目详细信息
3)编辑自动产生的源代码模板以便使程序显示一些输出信息
这就是全部!下一步,让我们详细进入每一步。

1、创建一个新的Android项目
从Eclipse中,选择菜单File > New > Project。如果ADT插件成功安装,结果对话框应该有一个标记为“Android”的文件夹,该文件夹包含一个简单入口:"Android Project"。
一旦你选择了"Android Project"文件夹,点击Next按钮。
2、填写项目详细信息
下一步的屏幕允许你填写项目详细信息。下面是例子:


以下列出这个屏幕的每个字段的意思:
(1)Project Name
这是存放该项目的目录或者文件夹名称。
(2)Package Name
这是包的名称空间(JAVA语言针对包使用同样的规则),你的所有代码均驻留在该命名空间中。同时也设置了即将产生的桩活动下面的包名称
你用在应用程序中的包名称必须在系统安装的所有包中唯一;基于这样的原因,你的应用程序使用标准域风格的包是非常必要的。上面的例子中,你使用了包域“com.android”;你应该使用一个不同的名字,根据你的组织做适当变化。
(3)Activity Name
这是类桩的名称,类桩(class stub)由插件产生。这是Android活动的子类。一个活动是一个能运行和完成一定工作的简单类。如果选择的话,能创建一个UI,但是不是必要的。
(4)Application Name
这是你的应用程序供使用者查看的标题。

复选项切换选项“Use default location”允许你改变磁盘位置,该位置用于项目文件产生和保存。

3、编辑自动产生的源代码

插件运行后,你将会有一个称为HelloAndroid的类,位于包HelloAndroid > src > com.android.hello。它看起来是这样的:
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

现在,你能马上运行这些代码,但是让我们更进一步,我们应该理解到底发生了什么事情。下一步让我们修改一些代码!

建立UI

仔细看看下面的这些修改过的代码,在你的HelloAndroid.java文件中做同样的修改。我们会一行一行的剖析他们:
package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Hello, Android");
setContentView(tv);
}
}

提示:如果你忘记引入TextView包,请试着做:按Ctrl-Shift-O (Cmd-Shift-O, 在 Mac操作系统上),这是一个Eclipse组织引入操作的快捷键——他自动识别丢失的包并为你自动加入。

Android的UI由叫做Views类的体系构成。一个View是一个简化的绘图对象,比如单选按钮、动画、文本标签。处理文本的View子类的名称为TextView。
下面是你建立TextView的方法:
TextView tv = new TextView(this);

TextView的构造函数的入参是Android Context实例。Context是系统的句柄;它提供诸如资源解析、数据库访问、参数选取等服务。Activity类继承自Context。因此,我们的HelloAndroid类是Activity的子类,它也是一个Context,所以我们能把this引用传送给TextView。
一旦我们建立了TextView,我们需要告之显示什么:
tv.setText("Hello, Android");

这里没有什么太令人惊讶的。
在此处,我们建立了TextView,并告之显示什么文本内容。最后一步是连接这个TextView到屏幕显示,像这样:
setContentView(tv);

在Activity中的setContentView方法指示系统和Activity的UI联系起来。如果一个Activity没有调用这个方法,根本没有UI出现,系统将会显示一个空白屏幕。为了我们的目的,我们想的所有事情是现实一些文本,因此我们传送文本给才创建的TextView。
这就是Android的“Hello, World”!下一步我们来看看他怎样运行的。


运行代码:Hello, Android

ADT插件非常容易运行应用程序。选择菜单Run > Open Run Dialog开始,Eclipse3.4,选择菜单Run > Run Configurations。

下一步,选中"Android Application"条目,然后点击左上角的图标(在角上画有加号的一张纸),或者双击"Android Application" 入口。这样,你就有了一个叫“New_configuration”的新的入口条目。

修改名称来表达要做的事情,比如"Hello, Android",然后双击Browse按钮来选取你的项目。(如果你在Eclipse中打开了不止一个项目,保证你选取正确的一个。)
插件自动扫描你的项目以寻找活动子类,自动添加找到的每一个到"Activity:" 标签下的下拉列表中。因为,你的 "Hello, Android"仅仅有一个,所以它将会是默认的一个活动子类,你可以继续下面的步骤。
点击“Apply”按钮。

那就是他,大功告成!点击Run按钮,Android模拟器应该会启动。一旦模拟器启动,你的应用程序将会显示出来。当说过和做过这一切,你应该会看到这样的事情:
在Android中显示“Hello, World”。非常简单。教程的下一章提供更多的详细信息,你可以找到你能更多了解Android的有价值的内容。

2008年11月24日星期一

设备调式和测试设置

设备调式和测试设置

Android让你设置需许多设置,这些设置会让测试和调试应用程序更容易。进入模拟器的开发设置页的方法:进入菜单“Dev Tools”-->“Development Settings”,系统会打开开发设置页面,里面包含如下的选项:
* Debug app——选中将要调式的应用程序。你不需要设置这个来attach绑定一个编辑器,但是设置这个值两种效果:
(1)如果你调试时长时间暂停在断点上,这个设置会阻止Android抛出异常。
(2)这个设置会使你选择“Wait for Debugger”选项,该选项会暂停应用程序启动直到你的调试器重新联系上。
* Wait for debugger——阻止被选择的应用程序调用直到一个调试器被依附。你能用于在OnCreate()上设置断点,在调试一个活动的启动过程时很重要。当你变更这个选项时任何正在运行的被选择的应用程序将会被终止。为了能选中这个选项,你必须象上一个选项描述的那样选中一个调试应用程序。你能通过在代码里面调用waitForDebugger()来达到同样的目的。
* Immediately destroy activities——告诉系统一旦活动停止就摧毁这个活动(类似Android回收内存)。这有助于测试onSaveInstance(Bundle)/onCreate(android.os.Bundle)代码执行路径,否则强制测试是很困难的。选用这个选项会恰当暴露许多程序问题,这些问题多半是不节约内存。
* Show screen updates——瞬时刷新一个粉红色的矩形框,在正在重画的任何屏幕区域。这个选项非常有利于发现不必要的屏幕重画动作。
* Show CPU usage——在屏幕顶端显示CPU仪表盘,用于显示CPU使用了多少。顶上的红色条显示全部的CPU使用,下面的绿色条显示话费在组合屏幕上的CPU时间。注意:一旦打开你不能关闭这个功能,除非你重新模拟器。
* Show background——当没有活动屏幕可见时显示一个背景屏幕。一般不会发生,但是调试期间可能发生。
这些设置经过模拟器重启后被记住。

顶级调试技巧

快速堆栈转储
为了从模拟器上获得堆栈转储,你可使用adb外壳登录,使用ps命令找到你想要的进程,然后使用kill -3。堆栈跟踪会显示在日志文件中。
在模拟器屏幕显示有用的信息
设备能显示有用的信息,比如CPU使用情况或者高亮显示重画区域。在开发设置窗口中打开或者关闭这些设置,参见“Setting debug and test configurations on the emulator”
从模拟器(dumpstate)中获取系统状态信息
从Dalvik调试监视器服务工具上你能访问dumpstate(转储状态)信息。参见adb主题页的“dumpsys and dumpstate”

从模拟器(dumpsys)中获取状态信息

从Dalvik调试监视器服务工具上你能访问dumpsys(转储系统)信息。参见adb主题页的“dumpsys and dumpstate”

获取无限连接信息

从Dalvik调试监视器服务工具上你能访问无线连接信息。从Device菜单中,选择“Dump radio state”

记录跟踪数据

你能记录活动中的方法调用以及其他跟踪数据,方法是:调用android.os.Debug.startMethodTracing()。参见“Running the Traceview Debugging Program”。

记录无线电数据

默认情况下,无线电信息不记录在系统中,因为数据量很大。但是,通过下面的命令打开无线电数据记录功能。
adb shell
logcat -b radio

运行adb

Android使用一个提供众多能力的工具称为adb,包括移动和同步模拟器文件、转发端口、在模拟器上运行UNIX外壳。详情请参考“Using adb”。

从模拟器中捕获屏幕

DDMS能从模拟器中捕获屏幕截图。

使用调试帮助类

Android提供调试帮助类,比如util.Log,方便调试。


生成和安装Android程序

Android需要定制生成工具,以便能够恰当的生成资源文件和应用程序的其他部分。正因为如此,你必须有一个针对你的应用程序特定的生成环境。

定制的Android编译步骤包括编译XMl和其他资源文件、创建合适的输出格式。一个已编译的应用程序是一个.apk文件,该文件是压缩文件,包含.dex文件、资源文件、原始数据文件以及其他文件。你可以创建一个合适结构的Android项目,从零开始,或者基于已存在的源代码。
Android目前不支持在本地代码级别(C/C++)上的第三方应用程序开发。

推荐开发方式是使用Android插件的Eclipse,提供生成、运行、调试支持。

如果你有其他IDE,Android提供工具来生成、调试应用程序,但是他们没有和IDE整合。


移除一个Android程序


为了移除一个你已经安装到模拟器上的程序,你需要运行adb并删除安装时送到模拟器上的.apk文件。使用adb外壳落入设备的命令外壳,就像相关主题描述的那样,定位到data/app/,然后使用rm your_app.apk移除文件。

Eclipse技巧

在Eclipse中执行任意Java表达式
当Eclipse展厅在一个断点时你能执行任意代码。例如,进入带称为zip的字符串参数的一个函数时,键入android.os.Debug.startMethodTracing()将会启动dmTrace。
打开一个代码执行窗口,选择主菜单下的菜单Window>Show View>Display打开Display窗口,一个简单的文本编辑器。输入您的表达式,突出显示文字,然后点击' J '图标(或按Ctrl + Shift + d )来运行您的代码。这里的代码运行在被选择的线程所在的上下文环境中,被选择的线程指在断点下停止或者处于单步运行点下的线程。(如果你手工挂起线程,你不得不一次运行一步;如果线程处于Object.wait()中就不会起作用。)
If you are currently paused on a breakpoint, you can simply highlight and execute a piece of source code by pressing CTRL + SHIFT + D.
如果你目前暂停于一个断点,你可以简单突出显示一段代码然后按“CTRL + SHIFT + D”执行之。
你能突出显示一段文本,该文本位于同一段范围内,该范围通过按ALT +SHIFT + UP ARROW选择的最大封闭块,或者按DOWN ARROW选择更小块。
这里有几个在Desplay窗口中执行的例子,还提供了执行响应。
Input Response
zip (java.lang.String) /work/device/out/linux-x86-debug/android/app/android_sdk.zip
zip.endsWith(".zip") (boolean) true
zip.endsWith(".jar") (boolean) false
你也能执行任意代码,而不是用剪贴簿来调试。请搜索和“scrapbook”相关的Eclipse文档。

手工运行DDMS

尽管推荐调试方法是使用ADT插件,但是你也可以手工运行DDMS并在8700端口上配置Eclipse。注意:保证你第一次使用DDMS。

加入JUnit测试类

在Eclipse/ADT中,你能加入JUnit测试类到你的程序中。但是,在你的测试适当运行之前,你需要设置一个自定义的JUnit配置。欲知有关怎样设置Junit配置的更多信息,请参见“ I can't run a Junit test class in Eclipse”。

2008年11月21日星期五

使用ApiDemos例子程序

使用ApiDemos例子程序

AndroidSDK包含一套例子程序,用于证明API和许多功能。ApiDemos包预装到模拟器上,因此你能访问他(通过启动一个模拟器),然后平滑打开主界面的应用程序抽屉。
你能找到ApiDemos应用程序的源代码,位于 /samples/ApiDemos目录里面,仔细考察他一边了解怎么实现的。
如果你想,你能作为源代码项目调用ApiDemos例子程序并修改他,然后在模拟器中运行他。但是,为了达到目的,你需要首先反安装ApiDemos的预装版本。如果你试图在你的开发环境中运行或者修改ApiDemos,而不是首先卸载预装版本,你会获得一个安装错误。
为了获取更多关于反安装和重新安装ApiDemos的信息,请参考问题主题文章“ I can't install ApiDemos apps in my IDE because of a signing error”。

调试

Android有一套相当广泛的工具来帮助你调试程序:
* DDMS——一款图形程序,支持端口映射(以便你在IDE中设置代码断点)、模拟器上屏幕捕获、线程堆栈信息以及其他特性。你也能运行logcat检索你的日志信息。欲知更多信息请查看相关主题。
* logcat——转储系统消息的日志。这些消息包括当模拟器抛出一个异常时堆栈跟踪,以及日志信息。为了运行logcat请参阅更过信息。
*Android Lod——一个日志记录类,用于输出消息到一个模拟器的日志文件。你能通过在DDMS上运行logcat来实时阅读消息。需要加入几个方法调用到你的代码。
为了使用这个Log类,你仅仅需要调用Log.v()(详细),Log.d()(调式),Log.i()(信息),Log.w()(警告)或者Log.e(错误),根据你的设计的日志消息的重要性来区别调用。
Log.i("MyActivity", "MyClass.getView() — Requesting item number " + position)
你能使用logcat来读这些消息。
* TraceView——Android能保存大量方法调用和次数到一个日志文件中,这个日志文件你能调用Traceview在图形阅读器中浏览。欲知更多信息请查看相关信息主题。
* Eclipse插件——Eclipse的Android插件整合了诸如ADB、DDMS、Logcat输出等工具。欲知更多信息请查看相关信息主题。
* Debug和Test Device设置——Android开放了几种设置,可以获取有用的信息,比如CPU使用率、帧速率。请参见下面的“Debug and Test Settings on the Emulator”

同时,请参见文档的问题解决章节,这些章节指出了为什么程序不能显示在模拟器中,或者为什么不能启动。