LANZHOU UNIVERSITY OF TECHNOLOGY
毕业设计
基于Android的电子词典软件的设计与实现
学生姓名 学 号 专业班级 指导教师
学 院 计算机与通信学院
摘要
本文设计了基于Android平台的电子词典软件。此英文词典包括两部分,一部分是离线的英文词典,一部分是在线的英文词典。离线的英文词典主要是使用Android自带的轻量级数据库SQLite来保存单词信息,系统通过SQLite数据库的query方法来查找到与指定英文相对应的单词的中文释义。在线的英文词典是利用oracle数据库来保存单词信息,然后利用Http协议解析出单词信息显示到手机界面上,同时还能够增加、删除、更新单词信息。当然,对于查询到的生疏的单词可以添加到单词本以便于随时复习。
关键词:Android,oracle数据库,SQLite数据库,英文单词
II
Abstract
In this paper, we design and implementation about electronic dictionary software which is based on the Android platform. English dictionary mainly include two parts, and one is to realize the offline English dictionary, the other is to realize the online English dictionary. Offline English dictionary is mainly used a lightweight database SQLite that belongs to Android to preserve words information, we find the specified English word corresponding to the Chinese interpretation by using query method of SQLite database. Offline English dictionary use an oracle database to save the word information, and then parse out the word information to display in the mobile phone interface by Http protocol, at the same time there have the functions that is used to increase, delete, update word information. Of course, we can add unfamiliar word to the note of word in order to review at any time.
Keywords: Android; oracle database; SQLite database; English words
目录
第1章 绪论 ........................................................................................................................................................... 1 第2章 系统需求分析 ........................................................................................................................................ 3
2.1 软件的功能要求 ................................................................................................................... 3 2.2 需求分析 ............................................................................................................................... 3 2.3 功能需求(用例图分析) ................................................................................................... 4
2.3.1 基本功能需求例图 .................................................................................................... 4 2.3.2 离线词典的例图 ........................................................................................................ 6 2.3.3 在线查询用例图 ........................................................................................................ 7 2.3.4 添加到单词本的用例图 ............................................................................................ 8 2.4 系统结构图和流程图 ......................................................................................................... 10 2.5 系统界面需求 ..................................................................................................................... 14 2.6 运行环境 ............................................................................................................................. 15
2.6.1 关键技术 .................................................................................................................. 15 2.6.2 运行环境 .................................................................................................................. 16
第3章 数据库的设计 ...................................................................................................................................... 16
3.1 在线词典的服务器端的数据库设计 ................................................................................. 16
3.1.1 数据库中数据表的设计 .......................................................................................... 16 3.1.2 在线词典的客户端的数据库设计 .......................................................................... 17 3.1.3 离线时的数据库的设计 .......................................................................................... 18 3.1.4 软件数据模型 .......................................................................................................... 19 3.2 连接数据库 ......................................................................................................................... 20
3.2.1 数据库的创建 .......................................................................................................... 20 3.2.2.数据库的操作 ........................................................................................................... 20 3.2.3 数据的查看 .............................................................................................................. 21 3.2.4 服务器和客户端的连接 .......................................................................................... 21
第4章 环境的搭建 ........................................................................................................................................... 23
4.1关于 Android的简单介绍 ................................................................................................. 23
4.1.1 Android环境的搭建 ................................................................................................ 23 4.1.2Android命令行的使用 ............................................................................................. 24 4.1.3 Android工程的简单介绍 ......................................................................................... 25 4.2 Java Web环境的搭建.......................................................................................................... 28 第5章 具体功能模块的设计 ......................................................................................................................... 31
5.1 查询模块的设计 ................................................................................................................. 32
5.1.1 离线查询 .................................................................................................................. 32 5.1.2 在线查询 .................................................................................................................. 33 5.2 添加单词模块 ..................................................................................................................... 35 5.3 删除单词模块 ..................................................................................................................... 36 5.4 修改单词模块 ..................................................................................................................... 37 5.5 菜单模块的实现 ................................................................................................................. 38 5.6 生词本模块的设计 ............................................................................................................. 42
第6章 系统测试与性能分析 ......................................................................................................................... 44
6.1测试 ...................................................................................................................................... 44 6.2 性能测试及分析 ................................................................................................................................. 45 总 结 ...................................................................................................................................................................... 46 参考文献 ............................................................................................................................................................... 47 附录一:英文翻译原文 .................................................................................................................................... 48 附录二:英文翻译译文 .................................................................................................................................... 56 附录三:程序清单 ............................................................................................................................................. 63 致谢 ........................................................................................................................................................................ 70
第1章 绪论
如今,英语在人们的工作、学习中显得越来越重要,而手机词典软件的出现无疑带来了极大的便利,遇到遇到生疏的英语单词,现在拿起手机就能轻松解决。近两年,谷歌android手机系统日益盛行,支持该系统的应用软件日益增多,自然手机词典软件也不例外。纵观web网的发展,从21世纪初基于web网的应用开始逐步引入中国到现在基于web网的应用发展的如此火爆。基于android手机系统的应用也将成为未来我国网络行业的发展潮流。据我们调查2007年11月5日,Google与其他33家手机制造商(包括摩托罗拉、宏达电、三星、LG)、手机芯片提供商、软硬件提供商合作。电信业者所联合组成了开发手机联盟,发布了“android”的开发手机软硬件平台。而这平台的软件与其他手机平台受手机型号的影响相比,android完全可以通用。基于android手机系统的手机这两年来迅速的引入中国,而且受到中国用户的一致好评。且看下面这组资料
①据媒体报道,一位分析师称,作为苹果iphone在今年假日季节到来之时的竞争产品,美国最大的移动电话制造商摩托罗拉的智能手机Droid自09年11月6日通过Verizon Wireless推出以来,其销售量已经达到80万部。 摩托罗拉智能手机Droid,运行的是谷歌Android操作系统。
②纽约RBCCapitalMarkets公司分析师马克·休(MarkSue)周日在一份研究报告中表示,该数字将使得摩托罗拉在第四季度按计划实现销售100万部目标可见基于android操作系统的手机的发展很快,这也是我们为什么首先基于android平台开发这款软件的原因。
另外电子词典作为我们学习和生活的重要部分,对于很多英语不好的学生或上班族们,特别是在北、上、广、深,这种一线城市的工薪阶层们,随时都会遇到国外的同胞,或者随时都有可能到国外去深造,如果随身没有一个英汉互译的软件,可能会难以同别人交流,因此推出一款好的电子词典软件是很有必要的,个人认为开发一款大众化的手机电子词典软件显得很有必要,特别是对于受教育程度较低和没有任何相关专业知识的人群,意义显得犹为突出。
1
现行软件技术发展迅速,各种类型的软件更新速度快,手机电子词典已经不是什么有创意的软件了,而是一类实用的软件。正因为其具有实用性,各个手机软件开发者都已经开发出来了基于各种手机系统的电子词典软件。而基于android系统的电子词典软件也已经出现,
此软件就是基于Android平台开发的,具有操作简单,适合大部分人群使用。在设计出本软件之前,我们首先做了充分的市场调查,了解基于android平台的电子词典软件的现状,了解大部分人对手机电子词典软件在界面上和功能上的要求,然后进行了细致的软件需求分析,进行软件的整体结构设计,确保软件中的任何一个功能点都是有意义的,接着开始软件的实施,将项目分成多个模块,完成各个具体的功能,最后当整个软件完成后,我们对软件进行专业测试,确保软件能正确的运行。在设计该软件时,我们将该软件定义为CS结构,这样即使在手机不能接入网络的情况下软件的各项功能还是能照常使用,在设计代码时,我们采用常用软件开发中常用的MVC模式,将操作界面和业务逻辑进行分离,降低代码的藕合度,便于软件的升级和维护,而这一思想也正好和android工程的程序结构相符,因为在android软件开发中,界面完全可以以xml的形式设计而不需要进行任何的硬编码,在软件的具体功能实现时,使用android布局技术完成UI的设计,使用android数据存储技术sqlite完成底层数据的读写。软件最终现的功能除了精确查询,模糊查询,生词本等常用的功能外,还加入了独特的记忆单词提醒、数据备份和恢复等功能。
在本论文中,各章主要介绍的内容如下:第2章主要介绍了电子词典软件的系统需求,第3章主要介绍了数据库的设计,第4章主要介绍了本软件中用到的语言环境的搭建,第5章主要介绍了此软件的各个模块的具体功能的实现。
2
第2章 系统需求分析
2.1 软件的功能要求
经过以上详细的用户调查,在现行业务流程和数据分析的基础上,基本可以确定系统设计必须达到的目标了。根据软件工程的原理,需求分析的任务是确定系统必须完成的工作,也就是对目标系统提出完整、准确、清析、具体的要求。在经过了多方的调查了解后,就可以确定电子词典的功能需求。以下是电子词典系统具备的功能: ①设有主菜单选项界面,供用户选择要执行的操作。 ②设有增加单词界面,管理员可以添加单词和单词解释。 ③设有更新单词界面,管理员可以更新某个单词的解释。 ④设有删除单词界面,管理员可以删除某个单词。
⑤设有单词查询界面,用户可以查询某个单词的解释或者进行模糊查询。 ⑥设有生词本管理界面,用户可以查看生词本中的单词与解释。 ⑦设有单词解释显示界面,用来显示用户查询到的单词的解释。 ⑧设有设置界面,用户可以设置该软件的一些信息。
⑨设有数据备份和恢复界面,用户可以将生词本中的数据方便的备份起来和恢复。
2.2 需求分析
在软件设计之前,我们要做的工作就是对电子词典的流程,操作等,做出详细的调查,从而了解系统需要实现的功能。系统在开发过程中,经过比较长时间的设计阶段,可以说模型贴近生活,有很大的现实意义,一般学生或者上班族一般都都能较方便的使用本软件,考虑到软件本身具有较强的专业性,而这些知识普及率毕竟有限,所以在程序设计过程中一直遵循实际应用的原则。因此它的操作界面会尽可能的简单,明了。各种控件的布置也会非常的清晰,使用的控件种类不会太多且对控件的操作不会太复杂。这样就能让不参与该软件设计的人也能够熟练的更好的使用。
根据用户查询单词和记忆单词的要求,和记录数据的一些习惯,该软件实现后,能达到 以下目标:界面设计友好、数据存储安全,可靠。基本的设置保证单词查询功能。保证数据 查询的灵活性。对增加、删除、修改,查询的信息进行精密设计,保证能及时处理信息。此软件包括两部分的设计,第一部分是离线的单词查询,Android自带的轻量级数据库SQLite
3
来保存单词信息,系统通过SQLite数据库中保存的单词信息来查找到与指定英文相对应的单词的中文信息。实现这样一个英文词典需要解决一系列技术问题。例如,如何将保存英文单词信息的数据库随程序一起发布;发布后如何打开数据库;如何在输入前几个字母后,在AutoCompleteTextView组件提示裂变中显示以所输入字符串开头的所有单词。
在线的英文词典在设计该时,我们将该软件定义为CS结构,即使手机不能接入网络但是软件的各项功能还是能照常使用。在设计代码时,我们采用常用软件开发中常用的MVC模式,将操作界面和业务逻辑进行分离,降低代码的藕合度,便于软件的升级和维护。在软件的具体功能实现时,使用Android布局技术完成UI的设计,使用oralce数据库保存单词的基本信息,使用Android数据存储技术内置的小型嵌入式数据库sqlite完成底层数据的读写。同样在线英文词典也要解决一系列的技术问题。例如,如何将保存在oracle数据库中的单词信息解析出来,如何把选中的英文单词保存在手机上轻量级数据库中以及如何把保存在手机数据库中的单词信息查询出来。
2.3 功能需求(用例图分析)
根据项目的目标,我们可获得项目系统的基本需求,以下从不同角度来描述系统的需并且使用用例图来描述,系统的功能需求,我们分为以下几个本分分别描述:基本功能需求例图,离线词典的功能例图,在线词典的功能例图,单词本的共能例图。各个例图分别简单的描述了各个部分的基本功能和简单的实现。 2.3.1 基本功能需求例图
4
图 2.1 系统的基本功能例图
其中各个部分的详细功能描述如下表所示
查询 用户 从手机数据库中或者从服务器端的数据库中查询单词 程序启动 点击查询按钮查询 表2.1 查询功能表 用例名称 参与者 目标 前置条件 基本事件流
5
表2.2 添加到单词本功能表
用例名称 参与者 目标 前置条件 基本事件流 表2.3 发音功能表
用例名称 参与者 目标 前置条件 基本事件流 发音 用户 使查询到的单词发音 单词已经成功查询到 点击发音按钮使单词发音 添加到单词本 用户 把查询到的单词添加到单词本中 已经查到单词 点击添加按钮添加到单词本 2.3.2 离线词典的例图
图 1.2 离线的词典的基本功能例图
6
其中各个部分的详细功能描述如下表所示
表2.4 离线查询功能表
用例名称 参与者 目标 前置条件 基本事件流 离线查询 用户 从手机数据库中查询单词 切换到离线词典 1 点击离线词典 2 输入单词后点击查询按钮
2.3.3 在线查询用例图
图2.3 在线词典的基本功能的例图
其中各个部分的详细功能描述如下表所示
7
表2.5 离线查询功能表
用例名称 参与者 目标 前置条件 基本事件流 在线查询 用户 从服务器端的oracle数据库中查询单词 程序启动 1 切换到在线查询 2 输入单词点击查询 表2.6 离线查询的菜单的功能表
用例名称 参与者 目标 前置条件 基本事件流 菜单 用户 从客户端添加,删除,更新单词 已经切换到在线查询 1 点击菜单按钮 2 点击添加进行添加 3 点击删除进行删除 4添加更新进行更新
2.3.4 添加到单词本的用例图
8
图2.4 单词本的基本功能例图
其中各个部分的详细功能描述如下表所示
表2.7 添加到单词本的功能表 用例名称 参与者 目标 前置条件 基本事件流
添加到单词本 用户 将查询到的单词添加到单词本 单词已经成功查询到 点击添加按钮添加 9
表2.8 显示添加到单本的单词
用例名称 参与者 目标 前置条件 基本事件流 显示添加到单词本的单词 用户 显示添加到单词本的单词 单词已经成功添加到单词本 1 切换到单词本 2 单击上一个显示上一个单词 3 单击下一个显示下一个单词 4 单击播放播放添加到单词本的所有单词 2.4 系统结构图和流程图
此软件主要分为两部分来实现,一部分是离线的英文词典,一部分是在线的英文词典。离线的英文词典主要是使用Android自带的轻量级数据库SQLite来保存单词信息,系统通过SQLite数据库中保存的单词信息来查找到与指定英文相对应的单词的中文信息。实现这样一个英文词典需要解决一系列技术问题。例如,如何将保存英文单词信息的数据库随程序一起发布;发布后如何打开数据库;如何在输入前几个字母后,在AutoCompleteTextView组件提示裂变中显示以所输入字符串开头的所有单词。在线的英文词典在设计该时,我们将该软件定义为CS结构,即使手机不能接入网络但是软件的各项功能还是能照常使用。在设计代码时,我们采用常用软件开发中常用的MVC模式,将操作界面和业务逻辑进行分离,降低代码的藕合度,便于软件的升级和维护。在软件的具体功能实现时,使用Android布局技术完成UI的设计,使用oralce数据库保存单词的基本信息,使用Android数据存储技术内置的小型嵌入式数据库sqlite完成底层数据的读写。同样在线英文词典也要解决一系列的技术问题。例如,如何将保存在oracle数据库中的单词信息解析出来,如何把选中的英文单词保存在手机上轻量级数据库中以及如何把保存在手机数据库中的单词信息查询出来。
其中离线词典的主要的系统流程图如图2.5所示,在线词典的结构图和系统流程图分别如图2.6和2.7所示,系统功能结构图如图2.8所示:
10
输入 数据库操作
结束 开始 主界面管理 词典 返回 显示 菜单 单词本 菜单 选项 上一个,下一个,联想 显示 设置 帮助 退出 数据库操作 图 2.5 离线词典的系统流程图
说明:其中词典的部分分为在线的电子词典和在线的电子词典,在离线部分主要是对Android自带的SQLite数据的操作,即单词的信息是存储在SQLite数据库中的,我们所做的是如何把单词的基本信息从数据库中读取出来,并且存储到单词本。而在线词典的部分我们主要使用的是服务器端的oracle数据库,我们的首要工作就是如何把服务器端的数据库中的数据读取出来,显示在手机的界面上。此外还要单词本的中的单词信息的存储,在此处我们也是使用Android的SQLite数据库,而我们的播放单词的功能就是把存储在单词本的单词按照顺序播放。所以本软件很大以部分的工作是对数据库的操作。
11
clientLogonsearchdeleteaddupdate登录登录登录servermysql检索tabledisplay返回数据
2.6 在线词典的架构图(C/S)
在图2.6中主要针对C/S架构进行说明,所谓的C/S架构就是客户端和服务器端。我们把此软件的架构定义为C/S,最大的好处就是即使没有网络的情况下,我们仍然可以从服务器端的数据库中读取到我们的单词信息,只是因为我们通过web服务器发布了我们的服务器,构建了一个虚拟的网络资源。
12
开始Client主界面管理默认词典返回单词本输入显示菜单菜单选项?Connect toserver and mysgl上一个、下一个、联想记忆显示数据增加删除设置更新推出数据库操作Connect to serverand mysgl数据库操作结束
图2.7 在线词典的系统流程图
在图2.7中我们主要的是针对在线的电子词典进行设计,涉及到的问题就是如何把服务器端的数据库中的单词信息读取出来然后显示在手机界面上。我们使用的是Http协议来解析,通过把单词信息解析到浏览器上,然后我们再通过post()和get()方法来解析浏览器上的信息。
13
基于Android的电子词典 在线查询 离线查询 英汉查询 设置 单词操作 数据安全英汉查 询 单词操 作 设置 性 发音 单词本 删除 增加 更新 单词本 发音 上一个 下一个 播放 上一个 下一个 播放
图2.8 系统功能结构图
2.5 系统界面需求
当今社会的生活节奏越来越快,随着硬件移动设备的越来越先进,人们对移动设备的要求也越来越高,从以前的追求技术到现在的追求视觉,因此,也逐步的提高了对系统的要求。因此设计的过程中应该注意界面的友好性以及客户的用户体验。图2.9是词典的用户界面:
14
图1.9 电子词典用户界面
说明:在图2.9为默认的英文词典的主界面,在文本框中输入相应的单词或者汉字,点击查询按钮就能显示出相应的汉语释义或者英文单词。点击在线词典就会出现在线查询的界面,点击单词本就会显示添加到单词本中的单词。
2.6 运行环境
2.6.1 关键技术
本软件采用java作为开发语言,布局和数据存储是开发本软件的关键技术,布局用来设计用户交互界面,用户界面的设计是否美观和合理直接影响用户体验,因此运用好布局技术好是直接和用户相关的,而数据存储技术则记录了用户所有的操作数据和用户所需要提取的数据。在android中,软件UI通常使用xml技术设计,而xml中控年的位置和状态则离不开布局的使用,android中常用的布局有5种,分别是:AbsoluteLayout、LinearLayout、RelativeLayout、FrameLayout、TableLayout,由于布局的使用,并且布局之间可以互相嵌套,使得android软件UI的设计变得非常灵活,即使是一些非常复杂的界面设计,只要合理的使用布局,也会使开发变得很容易。
android中数据存储技术主要有:文件存储、preference、sqlite、ContentProvider和网络存储,在本软件中主要使用到了文件存储、sqlite,文件存储是以流的形式读写文件,可以以文
15
格的格式,也可以以二进制的形式,在java语言中要使用流,则写入文件的对象必须进行序列化,sqlite是嵌入式移动设备中常用的轻量级数据库,可看作计算机上使用的sqlserver、oracle数据库。本软件中,用户生词本中的数据都存在sqlite数据库中,而进行数据备份和恢复时则是用文件作为介质保存数据。 2.6.2 运行环境
操作系统:Android手机基于Linux操作系统 支持环境:Android 1.5 - 2.3.1版本 开发环境:Eclipse 3.5 ADT 0.95
第3章 数据库的设计
数据结构组织和数据库文件设计要根据不同用途,使用要求等,来决定数据的整体组织形式等一系列问题。数据库,顾名思义,是存放数据的仓库。只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的。数据库中的数据按一定数据模型组织、描述和存储,具有较小的重复度、较高的数据性和易扩展性,并且可以被在一定范围内的各种用户共享。在涉及数据库的软件开发中,需要根据有待解决的问题性质、规模,以及所采用的前端程序创建工具等,做出合适的数据库类型选择。
3.1 在线词典的服务器端的数据库设计
在线查询时需要把服务器端的oracle数据库中的数据解析出来。把单词库导入到oracle数据库。在本系统中采用了简易版的oracle,即数据库的名字为XE,首先要解决的是在该数据库里某个用户下创建表。 3.1.1 数据库中数据表的设计
在此软件中表的关系比较简单,只有一张单词表,其具体的设计为
表3.1 数据库中数据表的具体设计
数据库名字 表名 字段名
XE b_dict name,info 16
说明:name为单词的英文名称为数据表的主键,info为单词的中文释义不能为空。在DOS下创建数据表的具体步骤为:
安装oracle简易版的数据库之后打开DOS进行配置,配置Oracle的步骤为
(1)以oracle管理员的身份进入oraclesqlplus “as sysdba” (2)启动oracle监听先退出exit;然后启动监听lsnrctl start (3)创建新的用户首先以管理员的身份进入sqlplus “/as sysdba”
create user name identified by password; grant resourct,connect to name;
注:以新的用户登录 首先推出数据库exit;然后sqlplus name/password (4)修改当前的语言格式,默认为中文
alter session set nls_date_language=english; (5)创建新的数据表、
create table b_dict(
name varchar2(20) primary key, info varchar2(100) not null );
(6)查看数据表是否创建成功select table_name from user_tables;
查看数据表的内容desc b_dict;
查看数据表的所有内容select * from b_dict; 将单词导入到数据库中
insert into b_dict values(‘AD’,’/Ad/ abbr.公元(后);耶稣纪元后’);
图 3.1 数据表b_dict的内容
3.1.2 在线词典的客户端的数据库设计
客户端采用的是sqlite数据库,sqlite数据库是Android自带的小型数据库,可以将少量的数据存放在该数据库中。针对不同的用户的生词是不同的,可以很方便的将生词导入到数据库中,也可以很方便的将单词从数据库中删除。此软件中的数据表的关系也比较简单,只
17
有一张表用来存放添加到单词本中的单词具体设计如下表所示:
表3.2 单词本表的具体设计
数据库名称 表名 字段名 sqlite.db dict _id,title,body 说明:title:存放英文单词。body:存放相应的英文单词的中文解释。数据库定义为sqlite.db的原因是:android平台下采用的数据库是sqlite3,运行后生成数据库的名称.db文件.定义好的数据库可以直接导入到/data/data/com.briup.dictionary/databases/sqlite.db 。这样生词本的数据就可以直接在模拟器中显示出来。
建表语句为create table dict
(_id Integer primary key increment by, title text not null, body text not null);
在DOS下查看android下的数据库文件的内容如下:
(1)cd /data/data/com.briup.dictionary/databases/sqlite.db (2) sqlite3 sqlite.db (3).tables
(4)select *from dict;
(5)将单词导入到数据库中,insert into b_dict values(1,‘AD’,’/Ad/ abbr.公元;耶稣纪元后’); 3.1.3 离线时的数据库的设计
这里的数据库的设计和单词的单词表的设计基本类似,这里就省略一些详细的建表的过程而简单的给出设计的功能表。
18
表3.3 离线时的数据库的设计表
字段名 _id english chinese 3.1.4 软件数据模型
数据类型 数字 字符 字符 建立系统数据模型的主要工具是实体—关联图,即E-R图。E-R图形符号约定如下表:
表3.4 E-R图图形符号表
图形符号 将属性连接到实体集或将实体集连接到联系集 表示实体集合 表示属性 表示关系集 说明 根据上面的给出的E-R图的图形符号表的描述,画出的在线时的数据库的E-R分别如下:
单词 单词解释 词汇 图 3.2 在线时服务器端的单词表的E-R图
19
单词解释 单词 单词ID 词汇
图 3.3 在线时客户端的单词本中单词表的E-R图
3.2 连接数据库
在线时的服务器端用的Oracle数据库用来存储单词的基本信息(单词的名称和单词的中文释义),客户端用的是android自带的sqlite数据库。这里将首先介绍如何进行Android数据库连接,Android中自带SQLite数据库,这是一个十分小型的数据库,这样正适合Android这种移动平台使用。Android数据库存储的位置在data/data/<项目文件夹>/databases/目录下,Android是利用ContentProvider作为内容提供商,SQLiteOpenHelper数据库帮助类来进行对数据库的创建和操作。通过Context.getContentResolver()方法直接对数据库进行操作。程序中数据库类为DBHelper extends SQLiteOpenHelper(继承关系),内容提供类DBProvider extends ContentProvide(继承关系)。其次介绍服务器端的数据库的详细设计,再介绍服务器端和客户端的数据库的连接。 3.2.1 数据库的创建
Android 提供了标准的数据库创建方式。继承SQLiteOpenHelper ,实现onCreate() 和 onUpgrade() 两个方法,有个好处就是便于数据库版本的升级,连接数据库的算法见程序清单。数据库如果创建不成功则抛出FIleNotFoundException异常。服务器端数据库的创建主要是通过DOS利用命令进行创建的,详细的创建命令在2.1.1中已经详细的做了介绍,此处不再进行赘述。
3.2.2.数据库的操作
Android对SQLite数据库的操作主要有插入、删除、更新、查询操作。但是前置条件是必须打开数据库。在这里打开数据库用的主要的方法是openForReadable()和openForWriteable(),打开数据之后才能进行相关的操作,其中插入单词的方法是insertWord(),删除单词的方法是deleteNote(),更新单词的方法是updateWord()。其详细代码见程序清单。注
20
意:在操作完了数据库之后,需要对资源进行释放,这里就是对数据库资源进行关闭,关闭数据库的方法是close()。在服务器端的数据库同样有增加,删除和更新等操作,因为我们用在线电子词典时,需要把数据从服务器端通过URL读出来。因此我们用的是servlet来实现单词的增删改查。其中查询操作的介绍将在下面的3.2.3节数据的查看中详细的分析,这里不再赘述。 3.2.3 数据的查看
Android中程序是利用Cursor游标类指向数据表中的某一项,然后进行查询数据,用Log日志显示出来。查询时用的方法是数据库本身的查询方法query(),需要注意的是这个方法比较复杂,他有8个参数,因为它将一个完整的SQL语句拆成了若干个部分:
第一个参数table:表名,相当于SQL的from后面的部分。在此还要注意如果和多表联合查询时,就用逗号将两个表名分开,拼成一个字符串的table值。
第二个参数是columns,要查询出来的列名。相当于SQL的select后面的部分。
第三个参数是selection,查询的条件,相当于SQL的where后面的部分,在这个语句中允许使用“?”,也就是说这个用法和JDBC中的PreparedStatement的用法相似。
第四个参数selectionArgs,对应于selection的值,selection有几个问号,这里就得用几值。
第五个参数groupBy,相当于SQL的group by后面的部分。 第六个参数having,相当于SQL的having后面的部分。
第七个参数orderBy,相当于SQL的order by后面的部分,如果是倒序,或者是联合排序,可以写成类似这样:String orderBy = “id desc,name”。
第八个参数limit,指定的结果集的大小,它和Mysql的limit用法不太一样,Mysql可以指定从多少行开始之后取多少条,例如,“limit 100,10”,但是这里只支持一个数值。 注意:游标查询时,必须把Cursor移动到第一个位置,即moveToFirst(),因为每次查询时,游标都会从第一个往后查找,通常在查询数据库之前进行。此外,游标和数据库一样都要及时关闭,要不会出现异常。其详细代码见程序清单。在Oracle中查询用到的也是数据的query()方法,他用到的参数只有一个就是sql语句,sql语句的写法是sql=“select sum(字段名) as 别名 from 数据表 where 条件表达式,”例如String sql = \"select * from b_dict where name=?\"。最后要执行sql语句,用法如下set rs= conn.excute(sql),用rs(别名)表示获取统计的值。 3.2.4 服务器和客户端的连接
服务器端和客户端的连接通过URL连接到浏览器,然后客户端从浏览器端把信息解析
21
出来。此处主要的方法就是post()或者get()方法,一般用到的都是post()方法,下面简单介绍一下post()方法的参数极其参数的用法。post()方法有两个参数,第一个是url(统一资源定位符)相当于网址,第二个是封装的参数。其使用步骤是: 1 创建HttpClient对象;
2 根据实际需求创建HttpGet和HttpPost对象
3 如果需要发送参数,调用setParams方法来添加请求参数,HttpPost对象可调用setEntity 来设置。
4 调用HttpClient的execute发送请求,返回一个HttpRequest。 5 调用HttpResponse对象相关方法获取服务器的相应内容进行处理。
22
第4章 环境的搭建
本软件在线词典的设计是C/S结构的系统,因此要先搭建服务器端,利用Java EE中的servlet来提供服务,并将其部署在Tomcat下。需要解决的是创建不同的servlet来提供不同的服务。另外此软件是运行在Android平台下,所以需要搭建Android平台。
4.1关于 Android的简单介绍
任何事物要运行都要有它的环境,Android也要有它的环境才能够运行,下面介绍Android的开发环境的配置。 4.1.1 Android环境的搭建 搭建开发环境需要的软件: 操作系统:Windows XP或Linux
软件包:Android SDK(Software Development kit Java Development kit)、ADT(Android Development Tool)
IDE环境:Eclipse IDE+ADT Eclipse 3.3 以上
JDK:Java Runtime Environment 虚拟机、(JDK)Java Development kit 安装步骤如下:
第一步:安装Java虚拟机sun-java7-jdk版本
第二步:安装Eclipse3.5工具官网选择版本(图4.1)进行安装。
图4.1 Eclipse的安装版本
第三步:安装Android SDK,首先要下载SDK,可以在这个网址下载选择相应的系统进行安装。
第四步:安装Android ADT插件,运行Eclipse,选择help->install new software选择add,将会弹出一个如图3.2对话框,点击OK,选择要安装的软件,然后next,选择接受协议,直到安装成功,重启Eclipse软件,设置Android SDK Home,window->refrence在SDK location中输入SDK Tools路径:E:\\android\\android-sdk-windows点击OK这样
23
Android的环境就已经搭建成功了。
图4.2 安装ADT
4.1.2Android命令行的使用
1.创建Android Virtual Device(AVD)
使用android list target命令列出当前可用SDK版本
android create avd –n -t [-]2.模拟器Emulator的使用
启动和停止模拟器
emulator –avd 3.Android Debug Bridge(ADB)的使用
查询当前模拟器实例数量 adb devices
4.本地机器和模拟器之间相互拷贝文件
D:adb push d:\esst.txt/sdcard D:adb pull /sdcard/test.txt d:/ (1)安装apk应用程序 adb push d:\est.apk/sdcard/ adb install test.apk
(2)使用shell命令
24
在DOS命令行输adb shell 进入shell命令行 退出shell用exit
4.1.3 Android工程的简单介绍
Android系统将插件ADT集成到了Eclipse工具上,因此,一个Android程序启动
后,系统会启动一个模拟器(Emulator),该模拟器是一款手机版的样式,拥有手机硬件的基本操作,我们可以右边的键盘通过代码属性设置将其隐藏,界面的大小可自由设定,目前最大支持800*600分辨率。
1.Android的工程程序的结构:Android工程基本结构目录包括:src(源代码),gen(Android系统自动生成的常量),res(资源文件):主要是存放程序界面的布局配置(.xml)文件和图片资源。AndroidMainfes.xml是Android四大组件的驱动配置文件,有它的存在,Android程序的四大组件才可以正常的跳转。Android资源的类型和布局如表3.1所示:
25
表4.1 Android资源的类型和布局表
目录结构 res/anim res/drawable res/layout res/values 资源类型 XML动画文件 一些图片文件 XML布局文件 各种XML资源文件 arrays.xml:XML数组文件 colors.xml:XML颜色文件 dimens.xml:XML尺寸文件 style.xml:XML 样式文件 res/xml res/raw res/menu 任意的XML文件 直接拷贝到设备中的原生文件 XML菜单文件 下图4.2和4.3为电子词典代码结构和个界面的配置文件,图像资源等,其中src为java的源代码,res/drawable为词典工程程序中用到的图片资源,res/layout为词典工程中用到的布局文件,res/values为工程中用到的各种XML资源文件,res/raw为工程中离线查询时用到的数据库资源。
图4.2 电子词典工程的结构图1
图4.3 电子词典工程结构图2
2.Android工程的配置文件AndroidManifest.xml的介绍
Android系统的任何一个程序启动都需要AndroidManifest.xml来启动程序,
26
任何一个新建的工程目录都会自动生成一个AndroidManifest.xml文件,此配置文件时整个程序能够正常运行的核心,他里面包含了AndroidSDK的版本,程序运行的默认Activity,当程序中的任何一个组件触发事件后,系统都会自动的去AndroidManifest.xml中寻找标示来做出相应的操作。任何一个AndroidManifest.xml文件的格式都应为:
Android支持的编码是\"utf-8\",当程序中出现乱码是,我们须将其编码格式转化为\"utf-8\".在 AndroidManifest.xml中会在第一行声明一句:。在第二行定义了我们需要使用的架构,该架构来自
xmlns:android=\"http://schemas.android.com/apk/res/android\"xmlns(XML namespace)是一个命名空间,它就像一条河的源头一样能让我们找到系统架构,每一个配置文件必须有这个xmlns,否则程序中的所使用的所有资源将无法找到。
在application元素我们定义android:icon=\"@drawable/icon\"
android:label=\"@string/app_name\",android:icon是程序在手机中显示的图片,我们运用@drawable/icon表示了对res/drawable目录下的icon.png的引用。@string/app_name表示了对res/value目录下string.xml中定义的app_name参数的引用。
27
这是系统确定的首先要启动的Activity是DemoDectionary。在intent-filter选项中,有action和category等等属性,我们需要定义action的值为android.intent.action.MAIN,category的值为android.intent.category.LAUNCHER,它们是系统的值,程序在解析到这些常用后就可以确定首先要启动的Activity。当我们需要通过一个组件触发另一个组件时,我们将设定action和category的其它属性值,系统会根据我们设定的属性值去AndroidManifest.Xml的application 中寻找标识,任何一个Activity的action和category是唯一,所以程序在任何时候都能唯一启动一个Activity,这样,不同的Activity之间的跳转就实现了。在AndroidManifest.Xml中有一个根结点,它是我们需要定义的ADT版本,例如我们将其值设定为android:minSdkVersion=\"4\",则表示此Android工程所用的版本为1.6,Android还有1.1、1.5、1.6、2.0、2.1这几个版本。如果我们需要对网络进行访问,比如打开一个网页,刚我还需要设置一个网络访问权限uses-permission,将其的值设置为一下的形式,INTRENET为网络访问权限。android:name=\"android.permission.INTERNET,我们就可以访问网络了。当然我们的uses-permission还有很多其它的权限,例如GPS定位权限,浏览器数据存取权限为以下形式com.android.browser.permission.READ_HISTORY_BOOKMARKS等等。当程序的任何一个组件要用到时,都必须在AndroidManifest.Xml文件中声明。四大组件要使用前都需要声明,其声明方式如下:
其中声明provider时还需要声明其授权 authorities。每个组件里面还有很多的属性,会根据程序的具体需要定义不同的属性。
4.2 Java Web环境的搭建
本软件是C/S结构的系统,因此要先搭建服务器端,利用Java EE中的servlet来提供服务,并将其部署在Tomcat下。需要解决的是创建不同的servlet来提供不同的服务。Web服务的名称:DictionaryService,在myEclipse中新建一个web project,取名为DictionaryService,其结构如下图:
28
图4.4 Web结构图
com.briup.jdbc是CVM模式中的低层,数据库层,包中的类是用来连接数据库和操作数据库的,其中JDBCConnectionFactory.java用来连接数据库。
private static String url; private static String userName; private static String userPwd;
连接数据库需要这三个值,而这三个值放入到dbFile中,通过Properties来获取。然后通过连接工厂方法。Connection conn = DriverManager.getConnection(url,userName,userPwd),com.briup.service是CVM模式中的service层,为用户提供服务。com.briup.service是CVM模式中的Dao层,为service提供服务,封装对数据库的操作的方法。com.briup.servlet包中就各个不同的Servlet类,其具体情况如下:
提供模拟查询的servlet是QueryDictsServlet,重写其中的doGet()和doPost()方法,该servlet来处理模拟查询的功能,并接收要匹配的字符串,参数为name,其提供查询的servlet是QueryDictServlet, 重写其中的doGet()和doPost()方法,该servlet来处理确认查询的功能,并接收要查询的字符串,参数为name,其url为:提供删除单词的servlet是DeleteDictsServlet,重写其中的doGet()和doPost()方法,该servlet来处理删除单词的功能,并接收要删除的字符串,参数为name,其url为;提供更新单词的servlet是UpdateDictServlet, 重写其中的doGet()和doPost()方法,该servlet来处理修改单词的功能,并接收要修改单词的字符串,参数为name,其url为;提供增加单词的servlet是AddDictServlet, 重写其中的doGet()和doPost()方法,该servlet来处理增加单词的功能,并接收要增加单词的字符串,参数为name,其url为提供查询的
servlet是QueryServlet, 重写其中的doGet()和doPost()方法,该servlet来处理查询所有单 词的功能,不需要接收任何参数,其URL为:
29
要测试是否连接成功可以打开任意浏览器,输入上面的url,如果能够正确的解析出来服务器端的信息,表示连接成功。如图是输入查询的url时出现的信息:此信息是以xml的信息表示的,第一行表示xml的版本信息以及所用到的编码格式,在下面是根节点response,其中包含两个子节点message和dict,而dict中又包含了两个子节点dictName和dictInfo,需要主要的是message是对服务器端是否解析成功的标注,也可以不要此节点,但是根节点必须存在。实际上我们从浏览器解析信息的时候就是通过各个信息的节点进行解析的,此处可以使用两中解析方法,一种是SAX解析,但是此解析主要针对的是大批量的数据解析,我们这里用到的信息只是单词的基本信息,没有必要使用它。因此我们使用的是针对小批量处理的DOM解析。
图 4.5 从浏览器解析到的查询信息
如上图如果要解析出单词的英文名字(english)和中文释义(chinese),其解析方法步骤为:
第一步:创建Document的工厂实例
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); 第二部:实例化DOM解析器 parser=factory.newDocumentBuilder();
Document document = parser.parse(InputStream is); 第三步:开始解析
NodeList dict=document.getElementsByTagName(“dict”); String english = dict.item(0).getFirstChild.getNodeValue();
String Chinese = dict. dict.item(1).getFirstChild.getNodeValue();
30
第5章 具体功能模块的设计
搭建好了环境,当我们的服务器端设计好了,在开始设计客户端。在设计客户端的时候,需要注意两个方面,一个是数据库的设计,一个是各个功能的布局。客户端是在Eclipse中新建一个android project工程,工程名为Dictionary,它的结构如下图所示:
图 5.1 电子词典的工程结构图
在com.briup.Dict.util包中的MyDatabaseHelpter类和MyDatabaseServer类是用来创建数据库和封装对数据库的操作。因为sqlite是内嵌在手机中,因此是创建数据库和表的时候,可以通过来创建。在com.briup.dictionary包中是每一个界面的类都在此包中,详细情况:
DictDemo.java是主界面,该界面实现主要的布局方式。 DictionaryDelete.java是删除单词的界面。
DictionaryDialog.java是单击单词时进行选择的界面。 DictionaryEdit.java是增加单词的界面。 DictionarySearch.java是查询单词的界面。 DictionaryShow.java显示单词和单词解释的界面 DictionaryUpdate.java更新单词的界面 DictNotesListActivity.java生词本的界面
31
HelpActivity.java帮助界面 PlayActivity.java联想记忆的界面 SettingView:设置界面
在此软件中,主要分为两部分,一部分是离线查询,另一部分是在线查询。下面就这两部分的各个模块功能的设计进行详细的分析。
5.1 查询模块的设计
查询功能就是要查询的单词的中文释义显示到界面上。它分为在线查询和离线查询。离线查询就是在不借助网络的情况下,直接从手机的SQLite数据库当中读取单词文件,从而显示在界面上。而在线查询需要我们借助于网络,从服务器端的数据库当中把数据解析出来从而显示在界面上。 5.1.1 离线查询
在离线查询时,我们首先要解决前面提出的主要技术问题,即如何将保存英文单词信息的数据库文件随程序(apk文件)一起发布;发布后如何打开数据库;如何在输入前几个字母后,在AutoCompleteTextView组件提示列表中显示以所输入字符串开头的所有单词。下面我们将逐一的解决这些问题。
1如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
在此软件中我们使用的是以将dictionary.db文件复制到Eclipse Android工程中的res/raw 目录中,所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。
2如何将res/raw中的数据库文件打开?
在Android中不能直接打开res/raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res/raw目录中资源的InputStream对象,然后将InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用 SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
在本软件中实现的英文词典中使用openDatabase方法来打开数据库文件(该文件在SD卡的dictionary目录中,因此,要想运行本文实现的英文词典,需要在手机或模拟器中需要安装SD卡)。如果该文件不存在,系统会自动创建/sdcard/dictionary目录,并将res/raw目录中的dictionary.db文件复制到/sdcard/dictionary目录中。其具体代码如程序清单所示。
3.如果在AutoCompleteTextView组件中输入两个及以上字母时显示以所输入字符串开头的所有单词列表?
32
AutoCompleteTextView所使用的Adapter是一个自定义的Adapter类。要注意的
是,不能将整个数据库中的单词都查出,然后生成一个Adapter对象再使用setAdapter方法来设置AutoCompleteTextView组件的Adapter对象。AutoCompleteTextView组件不会为我们筛选以某个字符串开头的单词。这些工作需要通过编码来实现。基本思路是在AutoCompleteTextView类的afterTextChanged事件中监视AutoCompleteTextView组件中字符的输入情况,每当输入一个字符时就生成一个Adapter对象,然后将新生成的Adapter对象与AutoCompleteTextView关联。显示以输入字符串开头的单词列表的效果如图5.2所示。
图 5.2 单词列表效果图
图 5.3 显示单词效果图
此软件的核心就是查找英文单词的中文意思。在查找中文意思之前,首先需要使用openDatabase方法在Main类的onCreate方法中打开SQLite数据库,代码如下:database = openDatabase();其中database是在Main类中定义的SQLiteDatabase类型变量。然后在查找按钮的单击事件中添加如下的代码来查找英文单词,并显示中文意思。说到这里我们应该了解dictionary.db中的t_words表的结果,该表只有两个字段:english和chinese。分别表示单词的英文和中文描述。如果要获得单词的中文描述,只需要查找chinese字段即可。如onClick方法中的代码所示。查询单词的效果如图5.3所示。 5.1.2 在线查询
查询模块的功能就是把查询到单词的中文解释在界面中显示出来。在屏幕中单击要查询
33
的单词或输入要查询的单词,另一个界面中显示出单词和单词的中文解释。实现过程:每次输入框的改变都向服务器端发送一次请求来进行模拟查询,在listView中显示模拟查询出的单词,如图5.4所示:
图 5.4 模糊查询图
图5.5 显示单词含义图
当在输入框输入字母时,会进行模糊查询,当点击查询按钮,也向服务器端发送一次请求来进行确认查询,将会显示该单词的信息,如图5.5所示。当单击listView中的单词时,会进入到另外一个界面,如下图5.6所示,下面对图5.5和5.6做一个简短的说明。
在图5.5中,第一个为加入到单词本,当点击时该按钮时,选中的单词就会被添加到单词本,按钮图案上得“+”好就会变为“-”,表示添加成功;第二个按钮为发音,当点击该按钮时,就会读出选中单词的英文读音。
在图5.6中,第一个为显示单词的按钮,当点击时,就会出现如图5.5所示的界面;第二个按钮为修改单词的中文释义,点击进入后就会出现如图5.10所示的界面;第三个按钮是删除按钮,当点击该按钮时,就会出现如图5.9所示的界面。
34
图 5.6 点击单词跳出的对话框
5.2 添加单词模块
该模块就是将在控件中填写的单词和单词信息传到服务器端,由服务器端向数据库中添加单词信息,界面如图5.7所示:添加成功后会提示添加成功是否还要继续添加,其显示界面如图5.8所示。此模块只针对在线查询。下面对图5.7和图5.8做一个简短的说明。在图5.7中按照相应的提示输入英文单词和他的中文释义,第一个按钮为添加输入的相应单词和其中文释义,当点击此按钮时,会出现如图5.8所示的界面。第二个按钮表示的返回主界面。在图5.8中,当点击OK时继续添加单词,当点击NO时,表示不再添加单词返回主界面。
注意:此处添加的单词在服务器端的oracle数据中,也就是说如果要是查询单词还是要从服务器端通过上面讲述的方法读取出来。所有使用的方法是insertWord(),此方法有一个参数,此参数是word,也就是说要加入的数据的库为单词。
35
图5.7 添加单词界面
图5.8 添加成功界面
5.3 删除单词模块
该模块是将某个单词传入到服务器端,由服务器端完成对单词的删除,它的界面就是弹
出一个对话框。对话框中显示要删除的单词,对话框中两个按钮,一个确定删除,一个是不要删除。单击不同的按钮会有不同的效果。此模块只是针对在线查询。其界面如图5.9所示,此处主要用的是数据库操作的deleteNote()方法,它有一个参数为name,表示根据单词名字来删除单词,其中用到的sql语句是String sql = “delete from where word = ?”。
36
图 5.9 删除单词模块的界面
5.4 修改单词模块
该模块完成单词信息的更新,不能修改单词,可以修改单词的含义,它的界面同添加单词的界面相同。此模块只针对在线词典。此处用到的方法主要是数据库的update()方法,此方法有三个参数。第一个参数是数据库的名字;第二个参数封装的是要改变的列的信息;第三个参数是where子句。例如:此处用到的是update((DATABASE_TABLE,values, KEY_WORD+\"=?\)。需要主要的是此方法的返回值是一个整型的行数的值,并不是所要修改的参数。其功能效果图和更新成功地效果图分别如图5.10和5.11所示,下面对5.10做个简短的说明。在图5.10中根据界面的提示输入所要修改的单词的中文释义,然后按第一个按钮,就会出现如图5.11的界面表示更新成功,当点击第二个按钮时,就会返回主界面。
37
图 5.10 修改效果图 图 5.11 修改成功效果图
5.5 菜单模块的实现
当前Activity在查询单词的界面单击menu按钮,会出现菜单栏的选项,其中有增加单词,
删除单词,更新单词,帮助界面,退出界面,设置界面等菜单选项。其具体的代码如程序清单所示。 创建新的菜单的方法为onCreateOptionsMenu(Menu menu),其中添加菜单项的方法为menu.add(),此方法有四个参数。第一个参数int groupId表示要添加的组的id;第二个参数int itemId表示要添加的菜单项的id,需要注意的是这个id必须是唯一的;第三个参数int order 表示添加的菜单项的排序;第四个参数int titleRes表示的是菜单项的名称。如果要为菜单项设置图标用的方法是setIcon(int iconRes) 其中的参数表示添加的菜单项的图片的名称。例如:menu.add(0,0,0,”帮助”).setIcon(R.drawable.help);
menu.add(0,1,0,”设置”).setIcon(R.drawable.set).
以上的例子是添加了两个菜单项,帮助菜单项的id为0,设置菜单项的id为1,同时还
为它们添加了图标。其效果图如图5.12所示:
38
图 5.12 菜单模块的效果图
(1)菜单模块中的添加功能的实现
该功能是向数据库中增加单词,单击此选项,会跳到增加单词的界面,其效果图如图5.7
和5.8。其中用到的主要方法是onOptionsItemSelected(MenuItem item),此方法为点击的菜单时就会被触动,从而产生事件流。在此处我们对事件的处理会跳转到另外一个页面去实现,我们需要跳转的页面是DictionaryEdit.class。其具体的实现代码见程序清单。 (2) 菜单中删除模块的实现
该模块是删除数据库中的单词,当点击delete菜单会跳到删除单词的界面,其中用到的主要方法是onOptionsItemSelected(MenuItem item),此方法为点击的菜单时就会被触动,从而产生事件流。在此处我们对事件的处理会跳转到另外一个页面去实现,我们需要跳转的页面是DictionaryDelete.class。其实现的效果图如图5.10所示。其具体实现的代码和基本上添加功能的代码相同。只是需要把需要跳转的界面改为DictionaryDelete.class。 (3)菜单模块中帮助功能的实现
该模块提示用户如何使用该软件。当单击help菜单时,会跳出帮助界面,其中用到的主要方法是onOptionsItemSelected(MenuItem item),此方法为点击的菜单时就会被触动,从而产
39
生事件流。在此处我们对事件的处理会跳转到另外一个页面去实现,我们需要跳转的页面是HelpActivity.class。其实现的方法也是基本上添加功能的代码类似,只需要把跳转的页面改为HelpActivity.class 。其实现的效果图如图5.13所示:
图 5.13 帮助功能的效果图
(4) 菜单中更新功能的实现
该模块是对单词的信息进行更新,当单击update时会跳到更新单词的界面,其中用到的主要方法是onOptionsItemSelected(MenuItem item),此方法为点击的菜单时就会被触动,从而产生事件流。在此处我们对事件的处理会跳转到另外一个页面去实现,我们需要跳转的页面是DictionaryUpdate.class。其实现的方法也是基本上添加功能的代码类似,只需要把跳转的页面改为DictionaryUpdate.class 。其实现的效果图如图5.11和5.12所示,当点击update时会跳到更新单词的页面,它不会改变选择的单词,只是对选中的单词的释义进行修改。 (5) 菜单模块中设置模块的设计
该模块是对系统的设置,当单击setting菜单时,会跳转到设置界面,他是通过
PreferenceActivity来实现的,将里面的设置通过Shared Perferences来保存到文件中。当里面的值发生变化时,会调用响应的方法。这里我们主要介绍一下Shared Perferences。Android提供给我们的一个共享的文件的类Shared Perferences。它有一个方法getSharedPreferences(参数1,参数2),参数1为写进时的标记,便于在从其中读取出来的标记;参数2为读取模式,有只写
40
模式(MODE_WORLD_WORITEABLE)和只读模式(MODE_WORLD_READABLE),在写之前将其置入编辑状态,用静态方法SharedPreferences.Editor editor = sp.edit();然后对象editor可以存入一个HashMap类型的键值,即putString(key,values),这样,我们可以将List中的对象转化成一样长的字符放进配置文件中。当写入成功时,Android系统会自动在目录data/data/工程包名/shared prefs/目录下生成一个配置文件。下面就说说怎么读取.xml文件,同样共享文件SharedPreferences通过方法getSharedPreferences(“SET_MSG,MODE_WORLD_READABLE”),并且是只读方式获得.xml文件的内容SharedPreferences的对象调用方法getString(\"sigle_Play\,返回一个String类型的值,即使我们以前存储进去的String的值。此方法当该标记不存在时会默认返回一个null值。获得成功后我们就可以运用当前的值再对程序进行操作了。如图5.14和5.15所示:
图 5.14 设置界面
5.15 字体设置的界面
(6)菜单模块的退出功能的设计
该模块是退出程序的时候,用于提示用户的,用于显示该系统的友好用户界面,如果用户是不小心点击退出的按钮或者非正常退出程序,程序可以通过不退出来返回之前的界面,如果用户是确定要退出程序,就选择ok,就能正常的退出程序。该界面会弹出一个对话框,对话框的显示的内容是提示用户是否退出,对话框上有两个按钮,一个是确定退出,一个取消退出。其实现效果图如图5.16所示
41
图 5.16 退出功能的效果图
5.6 生词本模块的设计
在主界面中单击选项卡中的单词本,就会跳转到单词本的界面,该界面会显示从生词本中的数据库查询出来的第一个单词的信息,然后可以通过上一个,下一个按钮翻阅所有被添加到单词本中的单词,当按下播放按钮时,就会自动播放添加到单词本的所有单词。单词本中的单词是利用手机自带的SQLite数据库存储的。其实现该模块的代码见程序清单。其效果图如图5.17和5.18所示:
42
图 5.17 单词本模块的界面 图5.18 单词本的播放功能的界面
说明:当点击5.17中的返回时,单词本返回到默认的主界面,即离线的单词查询界面,当点击上一个时,就会在界面显示单词本的上一个单词,当点击下一个按钮时,就会在界面上显示单词本的下一个单词,当点击播放按钮时,就是自动播放添加到单词本的所有单词,其效果如图5.18所示。
43
第6章 系统测试与性能分析
6.1测试
在进行测试之前我们首先要调试所要运行的环境,其步骤为: 第一步:打开oracle数据库。
第二步:在web服务器tomcat上发布我们的服务器,然后启动tomcat。启动的方法为在命令终端输入startup.bat。其前置条件是我们必须要配置好jdk以及tomcat的环境变量。
第三步:运行程序。 下面是各个模块的测试情况:
精确查询单词测试:进入到系统主界面后,在单词的输入框中输入你要查询的单词,点击查询按钮后,如果数据库中不存在这样的单词,将会到另外一个界面,告诉你不存在这样的单词。如果数据库中存在这样的单词,将会在下面显示该单词,点击该单词,会有三个选择(显示该单词的解释,更新该单词,删除该单词)。
模糊查询单词测试:进入到系统主界面后,在单词的输入框中输入你要查询的单词,每次输入框的改变,下面显示的单词也会跟着你输入的字母进行改变,进行一种模糊匹配。但点击显示出来的单词时,会跳出三个选择(显示该单词的解释,更新该单词,删除该单词)
菜单测试:在主界面时,单击menu按钮会显示菜单项,但单击不同的菜单项会到不同的界面去。
单词朗读测试:当查询出一个单词时,进入到显示该单词的界面,单击朗读按钮,可以让其朗读出该单词。如果没有朗读该单词,说明该部分测试失败。
单词添加或移除生词本测试:当查询出一个单词时,进入到显示该单词的界面,如果该单词已经在生词本中了,就显示从生词本中移除的按钮,如果该单词不存在生词本中,就显示添加到生词本的按钮,在不同情况下,该按钮的功能不同。
生词本测试:单击生词本的选项卡,会到生词本的界面,该界面会显示用户添加到生词本中的单词,当单击下一个时,会显示生词本中的下一个单词,同样单词上一个时,会显示生词本中的上一个单词。当单击播放按钮时,会把生词本中的单词进行联想记忆,像放电影一样,一个一个单词进行播放,当单击返回按钮时,会跳转到单词界面。
数据备份和恢复测试,点击备份时,提示“己将数据成功备份至SD卡”,删除现有的一条收支记录后,再点击恢复时,提示“己成功将数据恢复到软件中”,再查找被删的那条记录,
44
发现数据重新找回,说明该功能正确。
通过对软件中各模块的严格测试,并没有发现出乎意料的运行结果,所有运行的实际结果均与预期结果相吻合,说明系统的稳定性良好。
6.2 性能测试及分析
性能主要从以下两个方面进行分析: (1)可扩展性
此软件的扩展性可以从两个方面进行分析,第一个方面就是针对离线查询,我们可以从网上下载现已做好的单词的数据库资源,然后把它导入到sdcard中,同样可以查询出来其中的单词。当然也可是做好的其他的语言和中文的相互查询。另一个方面就是单词本的部分我们还可以对其做一点扩展,比如对添加进去的单词进行复习,我们设置复习的时间。 (2)可移植性
可移植性是针对软件能否移植到不同的操作系统和不同的型号的模拟器上的情况。首先Android是基于Linux 2.6内核的操作系统,我们可以把它的环境搭建到Windows平台上,当然也可以直接在Linux系统中搭建环境。其次是我们已经在不同型号的模拟器上测试成功,所以它的可移植性能良好。
对于添加单词,删除单词,更新单词只允许管理员进行该操作,并不允许普通用户执行该操作,这是因为单词库中的单词不允许随意改变,如果每个人都可以改变数据库中的数据,就会失去数据的安全性,因此规定只能是管理员才可以这些操作。
对于生词本中的数据进行删除,增加,更新熟针对单个用户的,每个用户所存储的数据不同,都具有操作各自数据的权利。 软件中对各个用户输入接口进行严格的验证,特别是对于插入、删除和修改这种具有一定风险的操作,通过对输入数据类型和格式进行规范,保证系统数据库中不会存在垃圾数据,从而保持了系统数据的合理性,保证系统的正常运行。
45
总结
从选定设计题目到完成此文档,历时几个月,几经修改终于完成了基于Android平台的电子词典软件的设计以及文档的撰写,本手机电子词典软件实现一般电子词典软件所必备的功能,并且提供了友好的用户交互界面,让用户操作起来极为方便和快捷,在这几个月里,我收获了很多,也付出了很多,从一个软件设计者的角度来说,我体会到了一个软件的设计其实不是想象的那么简单,对于用户来讲,也手许手机软件上的一个看似很小的功能,但在软件开发者看来有时却并不显得简单,有句俗话叫“牵一发而动全身”,在一个软件中有时一个小小的改动往往会牵涉到一些复杂的业务逻辑和算法,因此作为一个开发者,必须要有十足的耐心,才能将软件尽可能设计的合理,这款软件,我从设计直接和用户交互的UI层,到完成具体功能的业务逻辑层和底层数据库的设计,都花了很多时间去思考,做了很多繁琐的工作,但我认为是值得的,因为我做的大量工作换来了用户操作的简便,也为用户提供了良好的体验。
46
参考文献
[1] 张桂珠,刘丽,陈爱国Java面向对象程序设计(第2版)北京:北京邮电大学出版社2002年. [2] 毕广吉.Java程序设计实例教程[M].北京:冶金工业出版社,2007年. [3] 王保罗.Java面向对象程序设计[M].北京:清华大学出版社,2003年.
[4] 高林,周海燕.Jsp网上书店系统与案例分析[M].北京:人民邮电出版社,2004年. [5] 刘腾红,孙细明.信息系统分析与设计[M].北京:科学出版社,2003年. [6] 郭宏志.Android应用开发详解[M].北京:电子工业出版社,2010年. [7] 张孝祥.java就业培训教程[M].北京:清华大学出版社,2007年.
[8] 余志龙.Google Android SDK开发范例大全[M].北京:人民邮电出版社,2009-7-1.
[9] E2ECloud工作室.深入浅出Google Android应用开发详解[M].北京:人民邮电出版社,2009-8-1年. [10] 高昂.支持动态语言的Android平台[M].北京:人民邮电出版社,2009-05-07.
[11] 高焕堂.Android应用框架原理与程式设计(第三版)[M].北京:清华大学出版社,2008-10-03. [12] 杨丰盛.Android应用开发揭密[M].西安:机械工业出版社,2010-01-25.
[13]Teach Yourself PL/SQL in 21 Days. Tom Luers, Timothy Atwood, and Jonathan Gennick .SAMS出版社. [14]Developing Personal Oracle7 for Windows 95 Applications. Jesse Liberty. Sams 出版社. [15] 余志龙编著.Google Android SDK开发范例大全[M].北京:人民邮电出版社,2009-7-1. [16] E2ECloud工作室著.深入浅出Google Android[M].北京:人民邮电出版社,2009-08-1. [17] 靳岩 姚尚朗著.Google Android开发入门与实战[M].北京:清华大学出版社,2009-07-01. [18] 高昂著.支持动态语言的Android平台[M].北京:人民邮电出版社,2009-05-07. [19] Android API文档..2010-04-10. [20] JavaEye论坛. 2010-04-15.
47
附录一:英文翻译原文
Abstract
With the development of the mobile phone market,3G mobile phone system development has also become popular on the maket. This paper introduces some basic applications of the Android system about a part of the Application Fundamentas book translation, so that more learners can easily learn about the development and application of the Android system. Translation about this paper is my personal understanding of the Application Fundaments, there are some similarities and differences with the original, and if you would like to know more about or more detailed about basic application of Android system,please read the original article referenced this article, this paper only introduces basic application of the Android system about applicated component,close component,manifest file,the Intent filter.
Key word: application components, closed components , Intent filter, manifest files, activity, Service, Broadcast receiver , Content provider
48
Android applications are written in the Java programming language. The compiled Java code — along with any data and resource files required by the application — is bundled by the aapt tool into an Android package, an archive file marked by an .apk suffix. This file is the vehicle for distributing the application and installing it on mobile devices; it's the file users download to their devices. All the code in a single .apk file is considered to be one application. In many ways, each Android application lives in its own world:
1. By default, every application runs in its own Linux process. Android starts the process when any of the application's code needs to be executed, and shuts down the process when it's no longer needed and system resources are required by other applications.
2. Each process has its own virtual machine (VM), so application code runs in isolation from the code of all other applications.
3. By default, each application is assigned a unique Linux user ID. Permissions are set so that the application's files are visible only to that user and only to the application itself — although there are ways to export them to other applications as well.
It's possible to arrange for two applications to share the same user ID, in which case they will be able to see each other's files. To conserve system resources, applications with the same ID can also arrange to run in the same Linux process, sharing the same VM. Application Components
A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it). For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.
For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main() function, for example). Rather, they have essential components that the system can instantiate and run as needed. There are four types of components: Activities
An activity presents a visual user interface for one focused endeavor the user can undertake. For
49
example, an activity might present a list of menu items users can choose from or it might display Photographs along with their captions. A text messaging application might have one activity that shows a list of contacts to send messages to, a second activity to write the message to the chosen contact, and other activities to review old messages or change settings. Though they work together to form a cohesive user interface, each activity is independent of the others. Each one is implemented as a subclass of the Activity base class.
An application might consist of just one activity or, like the text messaging application just mentioned, it may contain several. What the activities are, and how many there are depends, of course, on the application and its design. Typically, one of the activities is marked as the first one that should be presented to the user when the application is launched. Moving from one activity to another is accomplished by having the current activity start the next one.
Each activity is given a default window to draw in. Typically, the window fills the screen, but it might be smaller than the screen and float on top of other windows. An activity can also make use of additional windows — for example, a pop-up dialog that calls for a user response in the midst of the activity, or a window that presents users with vital information when they select a particular item on-screen.
The visual content of the window is provided by a hierarchy of views — objects derived from the base View class. Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place.
For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views that you can use — including buttons, text fields, scroll bars, menu items, check boxes, and more.
A view hierarchy is placed within an activity's window by the Activity.setContentView() method. The content view is the View object at the root of the hierarchy. (See the separate User Interface document for more information on views and the hierarchy.) Services
A service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to
50
activities that need it. Each service extends the Service base class.
A prime example is a media player playing songs from a play list. The player application would probably have one or more activities that allow the user to choose songs and start playing them. However, the music playback itself would not be handled by an activity because users will expect the music to keep playing even after they leave the player and begin something different. To keep the music going, the media player activity could start a service to run in the background. The system would then keep the music playback service running even after the activity that started it leaves the screen.
It's possible to connect to (bind to) an ongoing service (and start the service if it's not already running). While connected, you can communicate with the service through an interface that the service exposes. For the music service, this interface might allow users to pause, rewind, stop, and restart the playback.
Like activities and the other components, services run in the main thread of the application process. So that they won't block other components or the user interface, they often spawn another thread for time-consuming tasks (like music playback). See Processes and Threads, later. Broadcast receivers
A broadcast receiver is a component that does nothing but receive and react to broadcast announcements. Many broadcasts originate in system code — for example, announcements that the timezone has changed, that the battery is low, that a picture has been taken, or that the user changed a language preference. Applications can also initiate broadcasts — for example, to let other applications know that some data has been downloaded to the device and is available for them to use.
An application can have any number of broadcast receivers to respond to any announcements it considers important. All receivers extend the BroadcastReceiver base class.
Broadcast receivers do not display a user interface. However, they may start an activity in response to the information they receive, or they may use the NotificationManager to alert the user. Notifications can get the user's attention in various ways — flashing the backlight, vibrating the device, playing a sound, and so on. They typically place a persistent icon in the status bar, which users can open to get the message. Content providers
A content provider makes a specific set of the application's data available to other applications.
51
The data can be stored in the file system, in an SQLite database, or in any other manner that makes sense. The content provider extends the ContentProvider base class to implement a standard set of methods that enable other applications to retrieve and store data of the type it controls. However, applications do not call these methods directly. Rather they use a ContentResolver object and call its methods instead. A ContentResolver can talk to any content provider; it cooperates with the provider to manage any interprocess communication that's involved.
See the separate Content Providers document for more information on using content providers. Whenever there's a request that should be handled by a particular component, Android makes sure that the application process of the component is running, starting it if necessary, and that an appropriate instance of the component is available, creating the instance if necessary. Activating components: intents
Content providers are activated when they're targeted by a request from a ContentResolver. The other three components — activities, services, and broadcast receivers — are activated by asynchronous messages called intents. An intent is an Intent object that holds the content of the message. For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text. For broadcast receivers, the Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.
There are separate methods for activating each type of component:
1. An activity is launched (or given something new to do) by passing an Intent object to
Context.startActivity() or Activity.startActivityForResult(). The responding activity can look at the initial intent that caused it to be launched by calling its getIntent() method. Android calls the activity's onNewIntent() method to pass it any subsequent intents. One activity often starts the next one. If it expects a result back from the activity it's starting, it calls startActivityForResult() instead of startActivity(). For example, if it starts an activity that lets the user pick a photo, it might expect to be returned the chosen photo. The result is returned in an Intent object that's passed to the calling activity's onActivityResult() method.
2. A service is started (or new instructions are given to an ongoing service) by passing an Intent object to Context.startService(). Android calls the service's onStart() method and passes it the Intent object. Similarly, an intent can be passed to Context.bindService() to establish an ongoing
52
connection between the calling component and a target service. The service receives the Intent object in an onBind() call. (If the service is not already running, bindService() can optionally start it.) For example, an activity might establish a connection with the music playback service mentioned earlier so that it can provide the user with the means (a user interface) for controlling the playback. The activity would call bindService() to set up that connection, and then call methods defined by the service to affect the playback.
A later section, Remote procedure calls, has more details about binding to a service.
3. An application can initiate a broadcast by passing an Intent object to methods like Context.sendBroadcast(), Context.sendOrderedBroadcast(), and Context.sendStickyBroadcast() in any of their variations.
Android delivers the intent to all interested broadcast receivers by calling their onReceive() methods. For more on intent messages, see the separate article, Intents and Intent Filters. Shutting down components
A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.
Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way: Context.stopService().
Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail. The manifest file
Before Android can start an application component, it must learn that the component exists. Therefore, applications declare their components in a manifest file that's bundled into the Android package, the .apk file that also holds the application's code, files, and resources.
The manifest is a structured XML file and is always named AndroidManifest.xml for all applications. It does a number of things in addition to declaring the application's components, such as naming any libraries the application needs to be linked against (besides the default Android library) and identifying any permissions the application expects to be granted.
53
But the principal task of the manifest is to inform Android about the application's components. For example, an activity might be declared as follows:
Figure 1 the struck of Activity
The name attribute of the element names the Activity subclass that implements the activity. The icon and label attributes point to resource files containing an icon and label that can be displayed to users to represent the activity.The other components are declared in a similar way — elements for services, elements for broadcast receivers, and elements for content providers. Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling Context.registerReceiver().For more on how to structure a manifest file for your application, see The Android Manifest.xml File.
Intent filters
An Intent object can explicitly name a target component. If it does, Android finds that component (based on the declarations in the manifest file) and activates it. But if a target is not explicitly named, Android must locate the best component to respond to the intent. It does so by comparing the Intent object to the intent filters of potential targets. A component's intent filters inform Android of the kinds of intents the component is able to handle. Like other essential information about the component, they're declared in the manifest file. Here's an extension of the previous example that adds two intent filters to the activity
Figure 2 the struck of the Intent
The first filter in the example — the combination of the action \"android.intent.action.MAIN\" and the category \"android.intent.category.LAUNCHER\" — is a common one. It marks the activity as one that should be represented in the application launcher, the screen listing applications users can launch on the device. In other words, the activity is the entry point for the application, the initial one users would see when they choose the application in the launcher.
The second filter declares an action that the activity can perform on a particular type of data. A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.
For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an Intent Filter object. All other filters are set up in the manifest. For more on intent filters, see a separate document, Intents and Intent Filters.
55
附录二:英文翻译译文
摘要
随着手机市场的发展,3G手机逐渐占领手机市场,3G手机系统开发也成为市场上的热门技术。本论文主要介绍android系统的一些基本应用程序,是对Application Fundamentals这本书的部分翻译,让更多的学习者可以轻松的学习了解android系统的开发和应用。论文中的翻译内容是本人对Application Fundamentals的个人理解,与原著存在一些异同,想了解更多关于或更详细android系统应用基础可以参考本文阅读原著,本文只对android系统应用基础中的应用组件、关闭组件、manifest文件、Intent过滤器进行简单的描述介绍。
关键字:应用组件、关闭组件、manifest文件、Intent过滤器、activity、Service、Broadcast receiver、Content provider
56
Android应用程序使用Java编程语言开发。aapt工具把编译后的Java代码连同应用程序所需的其他数据和资源文件一起打包到一个Android包文件中,这个文件使用.apk作为扩展名。此文件是分发并安装应用程序到移动设备的载体;是用户下载到他们的设备的文件。单一.apk文件中的所有代码被认为是一个应用程序。
从多个角度来看,每个Android应用程序都存在于它自己的世界之中:
1 默认情况下,每个应用程序均运行于它自己的Linux进程中。当应用程序中的任何代码需要被执行时,Android启动此进程,而当不再需要此进程并且其它应用程序又请求系统资源时,则关闭这个进程。
2 每个进程都有其独有的虚拟机(VM),所以应用程序代码与所有其它应用程序代码是隔离运行的。
3 默认情况下,每个应用程序均被赋予一个唯一的Linux用户ID,并加以权限设置,使得应用程序的文件仅对此用户及此应用程序可见——尽管也有其它的方法使得这些文件同样能为其他应用程序所访问。
1 应用程序组件
Android的一个核心特性就是一个应用程序可以使用其它应用程序的元素(如果那个应用程序允许的话)。例如,如果你的应用程序需要显示一个图片卷动列表,而另一个应用程序已经开发了一个合用的而又允许别的应用程序使用的话,你可以直接调用那个卷动列表来完成工作,而不用自己再开发一个。你的应用程序并没有吸纳或链接其它应用程序的代码。它只是在有需求的时候启动了其它应用程序的那个功能部分。 为达到这个目的,系统必须能够在一个应用程序的任何一部分被需要时启动一个此应用程序的进程,并将那个部分的Java对象实例化。因此,不像其它大多数系统上的应用程序,Android应用程序并没有为应用程序提供一个单独的入口点(比如说,没有main()函数),而是为系统提供了可以实例化和运行所需的必备组件。一共有四种组件类型:
1 Activity
activity是为用户操作而展示的可视化用户界面。例如,一个activity可以展示一个菜单项列表供用户选择,戒者显示一些包含说明文字的照片。一个短消息应用程序可以包括一个用于显示要发送消息到的联系人列表的activity,一个给选定的联系人写短信的activity。以及翻阅以前的短信或改变设置的其他activity。尽管它们一起组成了一个内聚的用户界面,但其中每个activity都不其它的保持。每一个都实现为以Activity类为基类的子类。
一个应用程序可以只有一个activity,戒者,如刚才提到的短信应用程序那样,包含很多个。每个activity的作用,以及有多少个activity,当然是取决于应用程序及其设计的。一般
57
情况下,总有一个应用程序被标记为用户在应用程序启动的时候第一个看到的。从一个activity转向另一个靠的是用当前的activity启动下一个。
每个activity都被给予一个默认的窗口以进行绘制。一般情况下,这个窗口是满屏的,但它也可以是一个小的位于其它窗口之上的浮动窗口。一个activity也可以使用附加窗口——例如,一个在activity运行过程中弹出的供用户响应的对话框,戒是一个当用户选择了屏幕上特定项目后显示的必要信息的窗口。
窗口显示的可视内容是由一系列层次化view构成的,这些view均继承自 View 基类。每个view均控制着窗口中一块特定的矩形区域。父级view包含并组织其子view的布局。叶节点view(位于层次结构最底端)在它们控制的矩形区域中进行绘制,并对用户直达其区域的操作做出响应。因此,view是activity与用户进行交互的界面。例如,view可以显示一个小图片,并在用户指点它的时候产生动作。Android有一些预置的view供开发者使用——包括按钮、文本域、滚动条、菜单项、复选框等等。
view层次结构是由Activity.setContentView() 方法放入activity的窗口之中的。content view是位于层次结构根位置的View对象。(参见的用户界面文档以获取关于view及层次结构的更多信息。)
2 Service
service没有可视化的用户界面,而是在一段时间内在后台运行。例如,一个service可以在用户做其它事情的时候在后台播放背景音乐、从网络上获取数据或者计算一些东西并提供给需要这个运算结果的activity使用。每个service都继承自Service基类。
一个媒体播放器播放播放列表中的曲目是一个不错的例子。播放器应用程序可能有一个或多个activity来给用户选择歌曲并进行播放。然而,音乐播放这个任务本身丌应该由任何activity来处理,因为用户期望即使在他们离开播放器应用程序而开始做别的事情时,音乐仍在继续播放。为达到这个目的,媒体播放器activity可以启动一个运行于后台的service。系统将在这个activity不再显示于屏幕乀后,仍维持音乐播放service的运行。
连接至(绑定到)一个正在运行的service(如果service没有运行,则启动之)是可能的。连接之后,你可以通过那个service暴露出来的接口不service进行通讯。对于音乐service来说,这个接口可以允许用户暂停、回退、停止以及重新开始播放。
如同activity和其它组件一样,service运行于应用程序进程的主线程内。所以它不会对其它组件或用户界面有任何妨碍,它们一般会派生一个新线程来执行一些时间消耗型任务(比如音乐回放)。参见稍后的进程和线程。
3 Broadcast receiver
58
broadcast receiver是一个与注于接收广播通知信息,并做出相应处理的组件。许多广播是由系统代码产生的——例如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以发起广播——例如,通知其它应用程序一些数据已经下载到设备上并处于可用状态。
一个应用程序可以拥有任意数量的broadcast receiver,以对所有它认为重要的通知信息予以响应。所有的receiver均继承自BroadcastReceiver基类。
broadcast receiver没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者也可以使用NotificationManager来通知用户。通知可以用多种方式来吸引用户的注意力──闪动背光灯、震动设备、播放声音等等。通知一般是在状态栏上放一个持丽的图标,用户可以打开它并获取消息。
4 Content provider
content provider将一些特定的应用程序数据供给其它应用程序使用。数据可以存储于文件系统、SQLite数据库或其它有意丿的方式。content provider继承于ContentProvider 基类,实现了一套使得其他应用程序能够检索和存储它所管理的类型数据的标准方法。然而,应用程序并不直接调用返些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任何content provider进行会话;与其合作对任何相关的进程间通讯进行管理。
参阅的Content Providers文档以获得更多关于使用content provider的信息。 每当出现一个需要被特定组件处理的请求时,Android会确保那个组件的应用程序进程处于运行状态,必要时会启动它,并确保那个组件的一个合适的实例可用,必要时会创建那个实例。
1.1激活组件:intent
当接收到ContentResolver发出的请求后,content provider被激活。而其它三种组件——activity、service和broadcast receiver,被一种叫做intent的异步消息所激活。intent是一个保存着消息内容的Intent对象。对于activity和service来说,它指明了所请求的操作名称,并指定了用来操作的数据的URI和其它一些信息。例如,它可以承载一个对一个activity的请求,让它为用户显示一张图片,或者让用户编辑一些文本。而对于broadcast receiver来说,Intent对象指明了所通报的操作。例如,它可以对所有感兴趣的对象通报照相按钮被按下。 对于每种组件来说,激活的方法是不同的:
1 通过传递一IntentContext.startActivity()Activity.startActivityForResult(以启动(或指定新工作给)一个activity。相应的activity可以通过调用自身的 getIntent() 方法来查看最刜激活它
59
的intent。Android通过调用activity的onNewIntent()方法来传递给它随后的任何intent。
一个activity经常启动另一个activity。如果它期望它所启动的那个activity迒回一个结果,它会调用startActivityForResult()而不是startActivity()。例如,如果它启动了另外一个activity以使用户挑选一张照片,它也许想知道哪张照片被选中了。其结果将会被封装在一个Intent对象中,并传递给发出调用的activity的onActivityResult() 方法。
2 通过传递一个Intent对象至Context.startService()以启动一个service(或向正在运行的service给出一个新的指令)。Android调用此service的 onStart()方法并将Intent对象传递给它。
与此类似,一个intent可以被传递给 Context.bindService()以建立一个处于调用组件和目标service乀间的活动连接。此service会通过onBind() 方法的调用来获取此Intent对象(如果此service尚未运行,bindService()会先启动它)。例如,一个activity可以建立一个不前述的音乐回放service的连接,这样它就可以提供给用户一些途径(用户界面)来控制回放。这个activity可以调用 bindService()来建立此连接,然后调用service中定之的方法来控制回放。 稍后的远程方法调用一节有关于如何绑定至一个service的更多细节。
3 应用程序可以通过传递一个Intent对象至 Context.sendBroadcast() ,Context. sendOrderedBroadcast(), 以及Context.sendStickyBroadcast()和其它类似方法来发起一个广播。Android会调用所有对此广播有兴趣的broadcast receiver的 onReceive()方法,将此intent传递给它们。
1.2关闭组件
content provider仅在响应来自ContentResolver的请求时处于活动状态。而broadcast receiver仅在响应一条广播信息的时候处于活动状态。所以没有必要去显式地关闭返些组件。 而activity则不同,它提供了用户界面。只要会话依然持续,无论会话过程有无空闲,activity同用户进行长时间会话且可能一直处于活动状态。与此相似,service也会在很长一段时间内保持运行。所以Android为关闭activity和service提供了一系列有序的方法。
activity可以通过调用自身的finish()方法来关闭。一个activity可以通过调用finishActivity()方法来关闭另外一个activity(它用startActivityForResult() 启动的。service可以通过调用自身的stopSelf()方法,或调用 Context.stopService()来停止。
系统也会在组件不再被使用的时候戒者当Android必须为更多的活动组件回收内存时关闭它。稍后的组件的生命周期一节,将对返种可能性及结果进行更详细的认论。
1.3 manifest文件
当Android启动一个应用程序组件之前,它必须知道那个组件是存在的。因此,应用程序会在一个被打包到Android包中的manifest文件中声明它的组件,.apk文件还将涵括应用程序的
60
代码、文件以及其它资源。
manifest文件是一个结构化的XML文件,而且对于所有应用程序,文件名总是AndroidManifest.xml。除了声明此应用程序各个组件,它会做很多其他工作,比如指明应用程序所需链接到的库的名称(除了默认的Android库乀外)以及标出应用程序期望获得的各种权限。
但manifest文件最重要的任务是向Android报告此应用程序的各个组件。丼例说明,一个activity可能声明如下:
图 1 Activity配置结构图
元素的name属性指定了实现此activity的 Activity子类。icon和label属性指向包含展示给用户的此activity的图标和标签的资源文件。 其它组件也以类似的方法声明— 元素用于声明service, 元素用于声明broadcast receiver,而 元素用于声明content provider。未在manifest文件中进行声明的activity、service以及content provider将不为系统所见,从而也就永不会被运行。然而,broadcast receiver既可以在manifest文件中声明,也可以在代码中动态创建(为BroadcastReceiver对象),并以调用Context.registerReceiver()的方式注册至系统。1.4 Intent过滤器
一个Intent对象可以显式地指定一个目标组件。如果进行了返种指定,Android会找到这个组件(基于manifest文件中的声明)并激活它。但如果intent没有显式地指定一个目标,Android就必须找到最合适的组件来响应此intent。这个过程是通过比较Intent对象和所有潜在目标的intent过滤器完成的。组件的intent过滤器会通知Android它所能处理的intent类型。如同组件的
61
其它必要信息一样,这些intent过滤器是在manifest文件中进行声明的。返里有一个对先前例子的扩展,其中加入了针对activity的两个intent过滤器:
图 2 Intent配置结构图
示例中的第一个过滤器——action“android.intent.action.MAIN”和
category“android.intent.category.LAUNCHER”的组合——是常见的一个。它标明了此activity应该在应用程序启动器中显示,就是用户在屏幕上看到的此设备上可供启动的应用程序的列表。换句话说,这个activity是应用程序的入口点,是用户在启动器中选择运行这个应用程序后所见到的第一个activity。
第二个过滤器声明了此activity在一种特定类型的数据上可以执行的操作。
一个组件可以拥有任意数量的intent过滤器,每个都声明了一套不同的功能。如果组件 没有包含任何过滤器,它只能被显式地指明作为目标组件的intent激活。 对于在代码中创建并注册的broadcast receiver来说,intent过滤器将被直接实例化IntentFilter为对象。其它所有的过滤器都在manifest文件中设置。
62
附录三: 程序清单
(1)Android中创建数据库的程序片段
public DBHelper(Context context) {// 创建数据库 }
public void onCreate(SQLiteDatabase db) {// 创建时调用方法 db.execSQL(DATABASE_CREATE); }
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 版本更新时调用
db.execSQL(\"DROP TABLE IF EXISTS File_Table\");onCreate(db); }
@Override // 在ContextProvider运行时自动创建数据库 public boolean onCreate() {
dbOpenHelper= new DBHelper(getContext());
super(context, DATABASE_NAME, null, DATABASE_VERSION);
return true; }
(2)Android中对数据库进行的主要操作的程序片段 //打开数据库
public void openForReadable(){ }
public void openForWriteable(){ }
//向数据库中插入数据
public long insertWord(Word word){
SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy年MM月dd日\"+\"hh:mm:ss\");
63
mDb = dbHelper.getWritableDatabase();
mDb = dbHelper.getReadableDatabase();
ContentValues values = new ContentValues(); Values.put (KEY_WORD, word.getWordName()); values.put (KEY_DETAIL, word.getWordDetail()); if(word.getTime()==null){ } else{ }
System.out.println(\"time:\"+sdf.format(new Date())); long rows = mDb.insert(DATABASE_TABLE, null, values); return rows; }
values.put (KEY_TIME, word.getTime()); values.put (KEY_TIME, sdf.format(new Date()) );
// 根据单词名删除
public int deleteNote(String name) { } //更新单词
public int updateWord(Word word){
try {
mDb.execSQL(\"delete from dict where word=?\
new String[]{name});
} catch (Exception e) { } return 1;
// TODO: handle exception e.printStackTrace(); return -1;
ContentValues values = new ContentValues(); values.put(KEY_WORD, word.getWordName()); values.put(KEY_DETAIL,word.getWordDetail());
int rows = mDb.update(DATABASE_TABLE, values, KEY_WORD+\"=?\
}
new String[]{word.getWordName()});
return rows;
//关闭数据库 public void close() {
if(mDb!=null && mDb.isOpen()) }
mDb.close(); dbHelper.close();
(3)Android数据库的查询的程序片段 public Cursor fetchAllNotes() { }
(4) 将res/raw中的dictionary.db复制到sdcard中 private SQLiteDatabase openDatabase() {
try {
// 获得dictionary.db文件的绝对路径
String databaseFilename = DATABASE_PATH + \"/\" + DATABASE_FILENAME;
Cursor result= mDb.query(DATABASE_TABLE,
new String[] { KEY_ROWID, KEY_WORD, KEY_DETAIL },null,null, null,null, \"word asc\"); if(result.getCount()>0){ }
return result;
result.moveToFirst();
File dir = new File(DATABASE_PATH);
// 如果/sdcard/dictionary目录中存在,创建这个目录 if (!dir.exists())
65
}
}
dir.mkdir();
// 如果在/sdcard/dictionary目录中不存在
// dictionary.db文件,则从res/raw目录中复制这个文件到 // SD卡的目录(/sdcard/dictionary) if (!(new File(databaseFilename)).exists()) { }
// 打开/sdcard/dictionary目录中的dictionary.db文件
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
databaseFilename, null);
// 获得封装dictionary.db文件的InputStream对象 InputStream is = getResources().openRawResource(
R.raw.dictionary);
FileOutputStream fos = new FileOutputStream(databaseFilename); byte[] buffer = new byte[8192]; int count = 0;
// 开始复制dictionary.db文件 while ((count = is.read(buffer)) > 0) { } fos.close(); is.close();
fos.write(buffer, 0, count);
return database;
catch (Exception e) { }
return null;
(5)菜单模块的具体代码的程序片段
66
private static final int INSERT_ID = Menu.FIRST;
private static final int QUERY_ID = Menu.FIRST + 1; private static final int HELP_ID = Menu.FIRST + 2; private static final int EXIT_ID = Menu.FIRST + 3; private static final int SET_ID = Menu.FIRST + 4; private static final int UPDATE_ID = Menu.FIRST + 5;
public boolean onCreateOptionsMenu(Menu menu) {
System.out.println(\"onCreateOptionsMenu\"); super.onCreateOptionsMenu(menu);
INSERT_ID,0,
menu.add(0,
R.string.menu_insert).setIcon(R.drawable.mc_share_to_ico0_n);
menu.add(0,
QUERY_ID,
0,R.string.menu_delete).setIcon(R.drawable.delete002);
menu.add(0, HELP_ID, 0,R.string.menu_help).setIcon(R.drawable.help); menu.add(0, EXIT_ID, 0,R.string.menu_exit).setIcon(R.drawable.back); menu.add(0, SET_ID, 0,R.string.menu_set).setIcon(R.drawable.setting); menu.add(0,
UPDATE_ID,
0,R.string.menu_update).setIcon(R.drawable.mc_share_to_select_refresh_h);
}
(6)菜单模块中添加功能的的程序片段
public boolean onOptionsItemSelected(MenuItem item) { case INSERT_ID: }
System.out.println(\"Menu createnote\"+item.getItemId()); Intent i = new Intent(this, DictionaryEdit.class); startActivityForResult(i, 0); break;
return true;
67
(6)单词本模块的程序片段 public void fill(int id){ }
当点击最下面的第一个按钮的时候,会跳到单词界面,其实现的代码为: backBtn.setOnClickListener(new OnClickListener) {
public void onClick(View v) { }
// TODO Auto-generated method stub
Intent intent = new Intent(DictNotesListActivity.this,DictDemo.class); startActivity(intent);
ArrayList> listes = playTest(id);SimpleAdapter note = new SimpleAdapter(this, listes, R.layout.word_list,
new String[]{\"wordext1,R.id.text2});
list.setAdapter(note);
});
当点击最下面的第二个按钮的时候,会显示单词本中上一个单词,其实现的代码为: NEXTBTN.SETONCLICKLISTENER(NEW ONCLICKLISTENER) {
public void onClick(View v) {
// TODO Auto-generated method stub if(currentdex==(wrods.size()-1)){
nextBtn.setEnabled(false);
\"已经是最后一个了\
Toast.makeText(DictNotesListActivity.this,
Toast.LENGTH_LONG).show();
}
lastBtn.setEnabled(true);
if(currentdex<(wrods.size()-1)&¤tdex>=0){
lastBtn.setEnabled(true);
68
currentdex++; fill(currentdex);
}
}
});
69
致谢
在此设计完成之际想要说的感谢很多,这个设计是对我四年大学生活的一次最全面的检阅,也是我人生最重要的一次经历。从选题到设计制作到最后的论文的写作和修改的整个过程中,系统的设计与实现的过程中,我遇到很多的问题在胡莉老师的耐心鼓励指引下,我坚持下来了。现在论文已快接近尾声了,在此我要向我的老师表示最衷心的谢意,感谢他在我的论文设计提供的宝贵建议。在这几个月中,我还要感谢杰普软件科技有限公司的老师们和同学们。我在杰普学习手机安卓系统开发的课程,学习期间,我多次向杰普的老师和同学们讨教论文的设计,尤其是代码的实现过程。他们的支持和鼓励给予了我很大的信心。还有感谢我的指导老师王维芳老师对我提供了非常宝贵的修改意见。同时,我也要特别感谢各位评委在百忙中审阅本文。
70