基于Android平台的个人理财软件的设计与实
现
二级学院 专 业 班 级 学生姓名 学 号 指导教师
医药信息工程学院 计算机科学与技术 医学智能2011级(1)班
林彬健
王鹤娴
2015 年 3 月 诚 信 声 明
我声明,所呈交的毕业论文(设计)是本人在老师指导下进行的研究工作及取得的研究成果。据我查证,除了文中特别加以标注和致谢的地方外,论文(设计)中不包含其他人已经发表或撰写过的研究成果,也不包含为获得其他教育机构的学位或证书而使用过的材料。我承诺,论文(设计)中的所有内容均真实、可信。
毕业论文(设计)作者(签名):
年 月 日
基于Android平台的个人理财软件的设计与实现
【摘要】:个人理财管理系统是基于Android系统开发的一款手机应用程序。它主要是为了满足人们在快节奏的生活中可以随时记下自己的收支情
况的需求。个人理财管理系统与传统的记账方式相比,体现了它的便捷性、安全性及可扩展性。系统采用Eclipse+ Android Developer Tools作为开发工具,以SQLite为数据库。系统功能包括:用户账户的注册、用户切换、用户名密码修改、账户删除,语音识别记账,收入信息的增删改,支出信息的增删改,收入类型的增删,支出类型的增删,收入信息分类统计,支出信息分类统计,收入支出总额统计,数据还原、清空等等。系统具有界面简洁鲜明、功能便捷易用、操作人性化等特征。
【关键字】:收支管理;Android;SQLite;
Personal Financial Management System Design and
Implementation
Abstract:Personal financial management system is based on the Android system developed a mobile application.It is mainly to meet those people who want to write down their income and expenditure more quickly and conveniently in the fast-paced life. Compared with the traditional method, Personal financial management system reflects more convenience,security and scalability. Especially in this day and age, people are on the side of the phone. System uses Eclipse and Android Developer Tools as a development tool and SQLite as the database. Android technology is now very mature, we can easily develop.Personal Financial Management System of the main functional modules,including: user account registration, user switching, username password changes, account deletion, Income information
management,Expenditure information management,voice recognition accounting,Type of income management, Expenditure Type Manager, Income information classification statistics, expenditure information classification
statistics,
total
income
and
expenditure
statistics,Data reduction, data emptied and so on. The system has a simple and clear interface, easy-to-use features, user-friendly operation and other features
Keywords: Revenue and expenditure management;Android;SQLite;
目 录
1 绪论 ............................................................ 1
1.1 选题背景 .................................................. 1 1.2 课题研究的目的和意义 ...................................... 1 1.3 国内外现状和发展趋势 ...................................... 1 2设计开发所用到的工具和技术 ....................................... 2
2.1系统开发工具 ............................................... 2 2.2 Android的介绍 ............................................. 3 2.3 Eclipse的介绍 ............................................. 3 2.4 SQLite的介绍 .............................................. 4 3系统需求分析 ..................................................... 5
3.1需求分析 ................................................... 5 3.2 可行性分析 ................................................ 5
3.2.1 系统可行性 .......................................... 5 3.2.2 技术可行性 .......................................... 5 3.2.3 经济可行性 .......................................... 6 3.3系统功能模块 ............................................... 6 4系统总体设计 ..................................................... 7
4.1系统总体设计分析 ........................................... 7
4.2系统流程图 ................................................. 7 4.3 系统特点 .................................................. 7 4.4 数据库设计 ................................................ 8
4.4.1 tb_account(账户表) ............................... 90 4.4.2 tb_income(收入信息表) ............................ 90 4.4.3 tb_pay(支出信息表) ................................ 9 4.4.4 tb_ptype(支出类型表) .............................. 9 4.4.5 tb_itype(收入类型表) .............................. 9
5系统详细设计与实现 ............................... 错误!未定义书签。
5.1 主界面设计 ............................................... 10 5.2 收入/支出插入数据界面 ..................................... 12 5.3 语音记账界面 ............................................. 22 5.4 类别维护界面 ............................................. 39 5.5 收入/支出统计界面 ......................................... 39 6.论文总结 ....................................................... 47 参考文献 ......................................................... 47 致 谢 ......................................................... 48
绪论
1.1 选题背景
出门口诀“伸手要赏钱”分别代表着身份证、手机、钥匙、伞、钱。在后PC时代的今天,手机成为最重要的移动终端,是我们出门出行的必携物。以前,或许我们的手机只能为我们提供基本通信功能,而随着Android系统的诞生,我们的生活迎来了一场不亚于“工业革命”带给我们的巨大变化。基于Android系统的手机处理各类信息的能力得到了质的提升。而Android这个开源的操作系统,将享受这项优质服务的权利给了所有愿意使用它的人。
Android从08年9月的1.1版到去年的L版,一路走来,从基本走向优
化,全方面地为我们提供了出色的网络、多媒体、通讯、娱乐等功能。这匹黑马,从诞生伊始到去年7月的“全球市场占有率达81.9%”,告诉我们它的出现是多么受人们欢迎。它备受追捧的原因不外乎它完全的对第三方软件开发商和我们这些开发者的开发。我们可以在它上面实现无限自主的“自定义”。它宛如一张白纸,我们可以在上面随意画出自己想要的东西。它,贵在给予了我们自由。
1.2 课题研究的目的和意义
随着高速经济化,我们的生活节奏越来越快。我们忙东忙西,总会容易忽略忘记了一些生活细节,比如收支管理。为了更好的释放一些时间来享受我们的生活,我们期待有这么一款软件来帮助管理这些小数据。建立在Android操作系统上的个人理财系统,方便我们随时随地地记录着这些零散的数据,从此我们不必再为收支费心,清心地查看数据统计结果是我们唯一要做的事。
1.3 国内外现状和发展趋势
安卓在手机上的应用使得手机的功能有了很大改善,这使得越来越多的入主要依靠手机查询大量信息,而用户们不断提高的需求也决定了越来越多的基于安卓平台的应用软件及系统的产生。
若是基于安卓平台的个人理财系统得到广泛推广,人们能从该应用显而易见的了解到个人的财务状况,明确的使用自身钱财,了解到日常中支出比例,调整
支出,正确理财。
(1) 开放性手机平台:android是Google开发的基于Linux平台的开源手机操作系统。Google通过与运营商、设备制造商、手机公司和其他有关各方结成深层次的合作伙伴关系,希望借助建立标准化、开放式的智能手机操作系统,在移动产业内形成一个开放式的生态系统。
(2) 网络集成性很高:涵盖了生活中各个方面的网络应用,对长期使用网络、信息依赖度比较高的人群很合适。
(3) Android具备创新性自从:Google开发出Android后,许多人认为其技术可信度要比其它操作系统略胜一筹,但这并不是用户购买Android智能手机的唯一原因。人们认为Android是一种相对较新的、又较为成熟的技术,在达到巅峰之前还有很大发展空间。
(4) Android平台在数量上逐渐主宰市场:市场分析机构NPD发布的数据显示,2014年4-6月份发售的智能手机中,33%为Android手机,而RIM手机发售比例为28%,iPhone为22%...
(5) Android在其它领域的拓展:android不仅促进了手机产业的发展,它的全面计算服务和丰富的功能支持,已将应用拓展到手机以外的其他领域。Android平台的通用性可以适用于不同的屏幕、有线和无线设备。Android的系统和应用程序开发人员将更多的涉足多媒体、移动互联网设备、数字视频和家庭娱乐设备、汽车、医药、网络、监测仪器和工业管理、机顶盒等新领域。
2设计开发所用到的工具和技术
2.1系统开发工具
个人财务管理系统的开发及运行环境如下所述: 操作系统: Windows7 JDK环境:
开发工具: Eclipse version=4.2.0
Android Software Development Kit version=4.4.2
开发语言: Java、XML
数据库软件:SQLite 运行平台: Windows 虚拟机:720P(1080x720)
2.2 Android的介绍
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。
Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。
该平台由操作系统、中间件、用户界面和应用软件组成。它采用软件堆层(Software Stack,又名软件叠层)的架构,主要分为三部分。底层以Linux内核工作为基础,由C语言开发,只提供基本功能;中间层包括函数库Library和虚拟机Virtual Machine,由C++开发。最上层是各种应用软件,包括通话程序,短信程序等,应用软件则由各公司自行开发,以Java作为编写程序的一部分。不存在任何以往阻碍移动产业创新的专有权障碍,号称是首个为移动终端打造的真正开放和完整的移动软件。
android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
蓝色的代表java程序,黄色的代码为运行JAVA程序而实现的虚拟机,绿色部分为C/C++语言编写的程序库,红色的代码内核(linux内核+driver)。在Application Framework之下,由C/C++的程序库组成,通过JNI完成从JAVA到C的调用。
图2-1 Android架构
2.3 Eclipse的介绍
eclipse-galileoEclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发
环境。幸运的是,Eclipse 附带了一个标准的插件集,包括 Java 开发工具(Java Development Tools,JDT)。
Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下
一代IDE开发环境,2001年11月贡献给开源社区,现在它由非营利软件供应商联盟Eclipse基金会(Eclipse Foundation)管理。 2003年,Eclipse 3.0选择OSGi服务平台规范为运行时架构。 2007年6月,稳定版3.3发布。2008年6月发布代号为Ganymede的3.4版。2009年7月发布代号为GALILEO的3.5版。
Eclipse是着名的跨平台的自由集成开发环境(IDE)。最初主要用来Java
语言开发,但是目前亦有人通过插件使其作为其他计算机语言比如C++和Python的开发工具。Eclipse的本身只是一个框架平台,但是众多插件的支持使得Eclipse拥有其他功能相对固定的IDE软件很难具有的灵活性。许多软件开发商以Eclipse为框架开发自己的IDE。
Eclipse 最初由OTI和IBM两家公司的IDE产品开发组创建,起始于1999
年4月。IBM提供了最初的Eclipse代码基础,包括Platform、JDT 和PDE。目前由IBM牵头,围绕着Eclipse项目已经发展成为了一个庞大的Eclipse联盟,有150多家软件公司参与到Eclipse项目中,其中包括Borland、Rational Software、Red Hat及Sybase等。Eclipse是一个开发源码项目,它其实是 Visual Age for Java的替代品,其界面跟先前的Visual Age for Java差不多,但由于其开放源码,任何人都可以免费得到,并可以在此基础上开发各自的插件,因此越来越受人们关注。近期还有包括Oracle在内的许多大公司也纷纷加入了该项目,并宣称Eclipse将来能成为可进行任何语言开发的IDE集大成者,使用者只需下载各种语言的插件即可。
2.4 SQLite的介绍
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL
这两款开源的世界着名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
3系统需求分析
3.1需求分析
生活中记录日常花销、收入总是琐碎累心的。特别是纸质记录,除了携带不方便外,还很容易丢失损毁。
这个时候,若是我们身边常带的手机上有这么一款可以随时记录收入和支出的软件,因为在记录收支的同时,会有一些注意事项需要标注,比如欠钱还钱注意事项。在对各项数据进行记录后,用户会希望看到对各类数据的统计,所以需要满足基本需求的统计模块。为了保证数据安全,增设账户模块。为了区分各用户的操作习惯,所以增设收入支出类型管理模块和系统设置模块。
3.2 可行性分析
3.2.1 系统可行性
可行性分析实在目前市场己有的类似系统调查的基础上,辩证新系统的研发是否具备开发必要性和可能性,对新系统的研发从技术、经济、社会因素等多个方面进行相关的分析和研究,以避免造成不必要的投资失误,保证和提高新系统开发成功的把握。可行性研究的目的就是以最小的时间、金钱代价确定疑难问题是否能够妥善解决。
3.2.2 技术可行性
此系统需要在Android手机操作系统上运行,用Eclipse进行开发,数据库我选用轻量级的SqLite。开发所需的软件技术成熟稳定,且支持Android系统的手机也分布广泛,可以完全满足所以的开发需求。
至于自己在Android方面虽然没有基础,鉴于之前有Java编程经验且时间充裕,有足够时间来学习空白的知识。
3.2.3 经济可行性
从市场经济来看,近年来,国人生活品质提升,逐渐重视生活品质,手机应用便成了人们生活的一部分。当今社会己步入了一个全新的信息时代,人类的每个活动都和“信息”紧密的联系在一起,小至个人的衣食住行,大及国家大事新闻发布,都依与信息的传播与发布,而社会中最活跃的,在市场经济高速发展的现在,手机应用普遍化,生活化,低端化成了不可阻挡的趋势。
从技术经济来看,由于SQLite数据库和Android SDK都是开源的免费的开发学习工具,而且本系统使用灵活方便,技术也不是很复杂,开发周期较短,因此开发成本较低。市场前景非常看好,所以说技术经济方面来看,本项目也是可行的。由此可以看出本系统开发所产生的效益将大于投入,所以开发本项目是可行的、必要的。
综上所述,个人理财系统充分利用了软硬件资源,技术成熟,成本低廉,操作简单,管理方便,使理财记账摆脱空间的限制,实现自动化处理和信息化管理,因此,本系统的实施是可行的。
3.3系统功能模块
(1)用户管理:可以设置当前用户
(2)类别维护:用户可以添加日常收入、日常支出的类别,并且可以删除相应的类别,填写类别详细。
(3)日常收入:用户可以按照日常收入日期、金额、类别、备注进行数据的增添
(4)日常支出:用户可以按照日常支出日期、金额、类别、备注进行数据的增添
(5)收入支出统计:按照一定的数据查询条件,用户可以对数据进行统计。
个人理财
图3-1 个人理财管理系统功能结构图
类别维护
收入支出插入 手
语
收入支出统计 收
支
收入支出查询 用户信息
收 支
支用
4系统总体设计
4.1系统总体设计分析
系统设计是系统开发过程中的核心,从需求出发,总体上描述系统架构应该包含的组成要素。系统总体设计尽可能模块化,描述了各个模块之间的关联。模块化是一种很重要的设计思想,把一个复杂的系统分解为一些规模较小、功能简单的、更易于建立和修改的部分。一方面,各个模块具有相对独立性,可以分别加以设计实现;另一方面,模块之间的相互关系则通过一定的方式予以说明。各模块在这些关系的约束下共同构成一个统一的整体,完成系统的功能。
总体设计的核心内容就是依据需求分析定义的功能,合理、有效地实现系统中定义的各种需求,包括模块设计、数据库设计等。
4.2系统流程图
根据系统分析以及功能需求,系统的基本流程可以描述为:主界面→选择各子功能模块,如下图所示:
类别管理模块 图4-1 系统流程图 个 4.3 系统特点 用户登录模块 收/支数据查询 人 (1)目的明确:理财就是以管钱为中心,通过抓好赚钱、生钱、护钱,三个环收/支记录模块 节,管好自己手中的现金流动,让资产在保值的基础上,实现稳定持续的增长。 理 (2)功能齐全:系统覆盖了理财所需要的功能,收支,统计。 (3)适应性强:系统采用基于模型的设计思,用户的特点抽象出管理模型,根据模型进行系统设计,使系统具有很好的开放性的拓展性,能够高效率地适应各用户群体的需求。
财 密码管理模块 4.4 数据库设计
4.4.1 tb_account(账户表)
tb_account用于管理系统各个用户信息。_id为用户的唯一标识,为表的主键,也为其他表的_id相对应。Username和pwd分别代表着用户名和密码。这两个是用户后期可以修改的。
账户表中存在着一个特殊的用户:默认用户。它的用户名密码用户不可见。用户在没有登陆的情况下,数据保存在这个用户下方。
表4-1 用户账户表
字段名 _id USERNAME PWD 数据类型 Integer VARCHAR(20) VARCHAR(50) 是否主键 Y N N 描述 用户id 用户名 密码 4.4.2 tb_income(收入信息表)
TYPE_ID与tb_itype表的type_id对应。No为收入信息的编号,不同用户的收入信息存入数据库的时候,都是以no=1为起始的,进而往后递增。
表4-2 收入信息表
字段名 _id NO MONEY TIME TYPE_ID HANDLER MARK PHOTO KIND 数据类型 INTEGER INTEGER DECIMAL DATE INTEGER VARCHAR(100) VARCHAR(200) VARCHAR(200) VARCHAR(10) 是否主键 N Y N N N N N N N 描述 用户id 编号 收入金额 收入时间 收入类别 放款方 备注 照片 类别 4.4.3 tb_pay(支出信息表)
TYPE_ID与tb_ptype表的type_id对应。No为收入信息的编号,不同用户的支出信息存入数据库的时候,都是以no=1为起始的,进而往后递增。
表4-3 支出信息表
字段名 _id NO MONEY TIME TYPE_ID ADDRESS MARK PHOTO KIND 数据类型 INTEGER INTEGER DECIMAL DATE INTEGER VARCHAR(100) VARCHAR(200) VARCHAR(200) VARCHAR(10) 是否主键 N Y N N N N N N N 描述 用户id 自增 支出金额 支出时间 支出类别 消费地点 备注 照片 类别 4.4.4 tb_ptype(支出类型表)
tb_ ptype为支出类型表。由于每个用户都有对应的用户习惯,在添加支出信息时,收入类型的种类、使用频率都会有所不同。在此设计支出类型表,可以为用户提供修改支出类型的服务,根据自己的使用频率修改支出类型。
表4-4 支出类型表
字段名 _id no type_id 数据类型 INTEGER INTEGER INTEGER 是否主键 N Y N 可否为空 N N N 描述 用户id 类型编号 类型id 4.4.5 tb_itype(收入类型表)
tb_itype为收入类型表。由于每个用户都有对应的用户习惯,在添加收入信息时,收入类型的种类、使用频率都会有所不同。在此设计收入类型表,可以为用户提供修改收入类型的服务,根据自己的使用频率修改收入类型。
表4-5 收入类型表
字段名 数据类型 是否主键 可否为空 描述 _id no type_id INTEGER INTEGER INTEGER N Y N N N N 用户id 类型编号 类型id 5系统详细设计与实现
5.1 主界面设计
快速记个人记账软件主界面,有4个Fragment页面。
图5-1 为快速记主界面
主界面使用4个Fragment和PopupWindow生成,部分代码:
/**
* 显示PopupWindow弹出菜单 */
private void showPopupWindow(View parent) {
DisplayMetrics dm = parent.getResources().getDisplayMetrics(); int w_screen = dm.widthPixels; int h_screen = dm.heightPixels; // h_screen);
if (popWindow == null) { LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); // 创建一个PopuWidow对象
float radiowith = w_screen / 480.0f; float radioheight = h_screen / 800.0f; popWindow = new PopupWindow(view,
(int) (popWinLayout.getLayoutParams().width), h_screen / 4); }
// 使其聚集 ,要想监听菜单里控件的事件就必须要调用此方法 popWindow.setFocusable(true);
pop_voiceView = (LinearLayout) popWinLayout pop_quickView = (LinearLayout) popWinLayout pop_voiceView.setOnClickListener(this); pop_quickView.setOnClickListener(this); // 设置允许在外点击消失
popWindow.setOutsideTouchable(true);
// 设置背景,这个是为了点击“返回Back”也能使其消失,并且并不会影响你的背景
popWindow.setBackgroundDrawable(new BitmapDrawable()); // 设置菜单显示的位置
int xPos = (w_screen - popWinLayout.getLayoutParams().width) / 2;
popWindow.showAsDropDown(parent, xPos, 12);
// popWindow.showAsDropDown(parent, Gravity.CENTER, 0); // 监听菜单的关闭事件
popWindow.setOnDismissListener(new OnDismissListener() { @Override
public void onDismiss() {
// 改变显示的按钮图片为正常状态 changeButtonImage(); } });
// 监听触屏事件
popWindow.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { // 改变显示的按钮图片为正常状态 changeButtonImage(); }
return false; } }); } /**
* 点击了“明细”按钮 */
private void clickFriendfeedBtn() { // 实例化Fragment页面
fragmentPage1 = new FragmentPage1(); // 得到Fragment事务管理器
FragmentTransaction fragmentTransaction = this
.getSupportFragmentManager().beginTransaction(); // 替换当前的页面 // 事务管理提交
fragmentTransaction.commit(); friendfeedFl.setSelected(true); friendfeedIv.setSelected(true); myfeedFl.setSelected(false); myfeedIv.setSelected(false); homeFl.setSelected(false); homeIv.setSelected(false); moreFl.setSelected(false); moreIv.setSelected(false); }
此处省略类似的函数...
private void clickPop_voiceBtn() {
Intent intent = new Intent(MainActivity.this, AddPay.class);// 创建Intent对象
intent.putExtra(\"cwp.id\
intent.putExtra(\"cwp.voice\设置传递数据 startActivity(intent); }
private void clickPop_quickBtn() { Intent intent = new Intent(MainActivity.this, AddPay.class);// 创建Intent对象
intent.putExtra(\"cwp.id\ startActivity(intent); } /**
* 点击了中间按钮 */
private void clickToggleBtn() { showPopupWindow(plusImageView); // 改变按钮显示的图片为按下时的状态 } /**
* 改变显示的按钮图片为正常状态 */
private void changeButtonImage() { }
5.2 收入/支出插入数据界面
添加软键盘,来添加收入/支出消费记录
图5-2 收入/支出插入数据界面
添加收/支部分代码,需要判断是添加模式还是修改模式,是添加收入还是添加支出:
btnSaveButton.setOnClickListener(new OnClickListener() {// 为保存按钮设置监听事件
@SuppressLint(\"NewApi\") @Override
public void onClick(View arg0) {
if (typemode == \"add\") { // 添加模式
String
strMoney
=
txtMoney.getText().toString(); // 获取金额文本框的值
if (type == \"pay\") { // 支出
if (!strMoney.isEmpty()) {// 判断金额不
为空
// 创建InaccountDAO对象 PayDAO
payDAO
=
new
PayDAO(AddPay.this);
// 创建Tb_inaccount对象 Tb_pay tb_pay = new Tb_pay(
userid,
payDAO.getMaxNo(userid) + 1, get2Double(strMoney), setTimeFormat(null),
(spType.getSelectedItemPosition() + 1),
txtAddress.getText().toString(),
txtMark.getText().toString());
payDAO.add(tb_pay);// 添加收入信息 Toast.makeText(AddPay.this,
\"〖新增收入〗数据添加成功!\
Toast.LENGTH_SHORT)
.show();
gotoback();
收入金额!\
为空
1,
} else {
Toast.makeText(AddPay.this, \"请输入
Toast.LENGTH_SHORT).show();
}
} else { // 收入
if (!strMoney.isEmpty()) {// 判断金额不
// 创建InaccountDAO对象
IncomeDAO incomeDAO = new IncomeDAO(
AddPay.this);
// 创建Tb_inaccount对象
Tb_income tb_income = new Tb_income( userid,
incomeDAO.getMaxNo(userid) +
get2Double(strMoney),
setTimeFormat(null),
(spType.getSelectedItemPosition() + 1),
txtInhandler.getText().toString(),
txtMark.getText().toString());
+ get2Double(strMoney));
incomeDAO.add(tb_income);// 添加收
入信息
// 弹出信息提示
Toast.makeText(AddPay.this,
\"〖新增收入〗数据添加成功!\
Toast.LENGTH_SHORT)
.show();
gotoback();
} else {
Toast.makeText(AddPay.this, \"请输入
收入金额!\
}
}
Toast.LENGTH_SHORT).show();
} else { // 修改模式
if (type == \"pay\") { // 支出
if
(!txtMoney.getText().toString().isEmpty()) { // 判断金额不为空
Tb_pay tb_pay = new Tb_pay();
// 创建Tb_pay对象
tb_pay.set_id(userid); // 设置
userid
tb_pay.setNo(Integer.parseInt(strno)); // 设置编号
tb_pay.setMoney(get2Double(txtMoney
.getText().toString()));//
设置金额
tb_pay.setTime(setTimeFormat(txtTime
.getText().toString()));//
设置时间
tb_pay.setType(spType
.getSelectedItemPosition() +
1);
// 设置类别
tb_pay.setAddress(txtAddress.getText()
.toString());// 设置地点
tb_pay.setMark(txtMark.getText().toString());
// 设置备注
payDAO.update(tb_pay);// 更新支出
信息
Toast.makeText(AddPay.this, \"〖数据〗
修改成功!\
Toast.LENGTH_SHORT).show();
gotoback();
} else {
Toast.makeText(AddPay.this, \"请输入
收入金额!\
}
Toast.LENGTH_SHORT).show();
} else { // 收入
if
(!txtMoney.getText().toString().isEmpty()) { // 判断金额不为空
Tb_income
tb_income
=
new
Tb_income();
// 创建Tb_income对象 号
tb_income.set_id(userid);// 设置编
tb_income.setNo(Integer.parseInt(strno));
// 设置编号
tb_income.setMoney(get2Double(txtMoney
.getText().toString()));//
设置金额
tb_income.setTime(setTimeFormat(txtTime
.getText().toString()));//
设置时间
tb_income.setType(spType
.getSelectedItemPosition() +
1);
// 设置类别
tb_income.setHandler(txtInhandler.getText()
.toString());// 设置付款方
tb_income.setMark(txtMark.getText()
.toString());// 设置备注
incomeDAO.update(tb_income);// 更
新收入信息
Toast.makeText(AddPay.this, \"〖数据〗
修改成功!\
Toast.LENGTH_SHORT).show();
gotoback();
} else {
Toast.makeText(AddPay.this, \"请输入
收入金额!\
}
}
}
}
Toast.LENGTH_SHORT).show();
});
软键盘部分代码:
public void onKey(int primaryCode, int[] keyCodes) {
Editable editable = ed.getText();
if (typemode.equals(\"ModifyInP\")) { // 添加模式获取开始
光标 {
}
}
}
a = true;
}
int start = ed.getSelectionStart();
if (primaryCode == Keyboard.KEYCODE_DELETE) { // 删除键
if (editable != null && editable.length() > 0) {
if (start > 0) {
editable.delete(start - 1, start);
if (ed.getText().toString().indexOf(\".\") < 0)
ed.setSelection(editable.length());
} else if (primaryCode == -7) { //隐藏键盘
hideKeyboard();
} else if (primaryCode == -8) { //小数点
if (start > 0 && a) { }
editable.insert(start, \".\"); a = false;
} else if (primaryCode == -9) { //语音识别
hideKeyboard();
dialogShowUtil.dialogShow(\"rotatebottom\\"first\
\"\
} else {
editable.insert(start,
Character.toString((char)
primaryCode)); {
}
public void hideKeyboard() { }
//隐藏键盘
}
keyboardView.setVisibility(View.VISIBLE);
};
public void showKeyboard() {
//显示键盘
}
}
int visibility = keyboardView.getVisibility();
if (visibility == View.GONE || visibility == View.INVISIBLE)
int visibility = keyboardView.getVisibility(); if (visibility == View.VISIBLE) { }
keyboardView.setVisibility(View.INVISIBLE);
5.3 语音记账界面
语音记账使用了百度语音识别api,通过响应用户的触发,调用api动态生成百度自定义的dialog来进行用户语音录音。当用户录入语音后,返回语音识别的数据,然后转为字符串并进行分析判断。目前主要以金额和类别来作为关键字来进行判断,首先通过将识别字符串通过跟收入/支出类别进行对比,如果存在相关类别即标记下当前录入的类别;如果没有当前这个类别,将会弹出自定义Dialog让用户去选择即使没有匹配的类别,是否依然要录入,如果“是”,该笔类型就会默认为“语音识别”类别,并会让用户去选择当前记录是“支出”还是“收入”,再去结合当前的金额录入数据;如果用户录入的类别同时存在于“收入”和“支出”之中,那么就会让用户去选择该笔记录是“收入”还是“支出”,在去结合当前的金额录入数据。另一方面,将识别字符串与自定义的列如“一”,“二”,“元”,“钱”...去对比,然后标记下这个金额的起始和结束位置,然后截取出来,并调用工具类把这个汉字的金额转变为阿拉伯数字。最后使用方法去判断当前是“添加模式”还是“修改模式”,然后再判断是“支出”还是“收入”,然后录入数据库。
图5-3 语音记账界面
百度识别回调部分代码:
mRecognitionListener = new DialogRecognitionListener() { // 百度识别返回数据
@Override
public void onResults(Bundle results) {
ArrayList .getStringArrayList(RESULTS_RECOGNITION) : null; if (rs != null && rs.size() > 0) { Recognition(rs.get(0)); // Toast.makeText(AddPay.this, rs.get(0), }; } } // Toast.LENGTH_SHORT).show(); void VoiceRecognition() { // 百度语音识别 // mResult.setText(null); mCurrentTheme = Config.DIALOG_THEME; if (mDialog != null) { } Bundle params = new Bundle(); params.putString(BaiduASRDigitalDialog.PARAM_API_KEY, Constants.API_KEY); //百度语音api_key params.putString(BaiduASRDigitalDialog.PARAM_SECRET_KEY, Constants.SECRET_KEY); mDialog.dismiss(); params.putInt(BaiduASRDigitalDialog.PARAM_DIALOG_THEME, //百度语音主题 Config.DIALOG_THEME); mDialog = new BaiduASRDigitalDialog(this, params); mDialog.setDialogRecognitionListener(mRecognitionListener); mDialog.getParams().putInt(BaiduASRDigitalDialog.PARAM_PROP, //百度识别类别 Config.CURRENT_PROP); mDialog.getParams().putString(BaiduASRDigitalDialog.PARAM_LANGUAGE,//百度识别语言 Config.getCurrentLanguage()); mDialog.getParams().putBoolean( 别音效相关 BaiduASRDigitalDialog.PARAM_START_TONE_ENABLE, Config.PLAY_START_SOUND); mDialog.getParams().putBoolean( BaiduASRDigitalDialog.PARAM_END_TONE_ENABLE, Config.PLAY_END_SOUND); mDialog.getParams().putBoolean( BaiduASRDigitalDialog.PARAM_TIPS_TONE_ENABLE, Config.DIALOG_TIPS_SOUND); mDialog.show(); } /* * 识别结果处理函数 * * @param VoiceSave[0] 收入类别的值 * //百度识 * @param VoiceSave[1] 金额的值 * * @param VoiceSave[3] 重复类别的值,仅用于显示提醒 * * @param VoiceSave[4] 支出类别的值 * * @param VoiceSave[5] \"语音识别\"类别的值 */ private void Recognition(String t) { int mfirst = 100, mend = 0, temp = 0; Boolean ismoney = false, intype = false, outtype = false; String w = \"\spdatalist = ptypeDAO.getPtypeName(userid); spdatalist2 = itypeDAO.getItypeName(userid); VoiceSave[2] = t; for (int i = 0; i < spdatalist.size(); i++) { // 判断是否包含 支出 if (t.indexOf(spdatalist.get(i).toString()) > -1) { type = \"pay\"; intype = true; inname = spdatalist.get(i).toString(); VoiceSave[0] = Integer.toString(i); // VoiceSave[0]为收 入类别的值 } for (int i = 0; i < spdatalist2.size(); i++) { // 判断是否包 } 含收入 if (t.indexOf(spdatalist2.get(i).toString()) > -1) { type = \"income\"; outtype = true; outname = spdatalist2.get(i).toString(); VoiceSave[4] = Integer.toString(i); // VoiceSave[4]为支 出类别的值 } for (int i = 0; i < number.length; i++) { // 判断是否包含金额, } 获得开头 } if (t.indexOf(number[i]) > -1) { } temp = t.indexOf(number[i]); if (temp < mfirst) { } mfirst = temp; for (int i = 0; i < money.length; i++) { // 判断是否包含金额, 获得结尾 } for (int i = 0; i < money2.length; i++) { // 判断是否包含金额, if (t.indexOf(money[i]) > -1) { } temp = t.indexOf(money[i]); if (temp > -1 && temp >= mend) { } mend = temp; 获得结尾 } if (!(mfirst == 100 || mend == 0)) { // 转换为阿拉伯数字 ismoney = true; strmoney = t.substring(mfirst, mend); if (t.indexOf(money2[i]) > -1) { } temp = t.indexOf(money2[i]); if (temp > -1 && temp >= mend) { } mend = mend + 1; mend = temp; DigitUtil Util = new DigitUtil(); VoiceSave[1] = Integer.toString(Util.parse(strmoney)); // 调用工具类处理汉字的金额 } if (intype && outtype) { // 如果含金额 if (outname.equals(inname)) { if (ismoney) { VoiceSave[3] = outname; // VoiceSave[3]为重复类别的 值,仅用于显示提醒 dialogShowUtil.dialogShow(\"shake\\"judge, w); // 如果含有金额 } else { } w = \"提示:\\n你的话中没有包含消费或开支的<金额>\\n\"; dialogShowUtil.dialogShow(\"shake\ } else { w = \"**提示:\\n一次只能记录一条记录哦\\n\"; // 如果含有 收入并且支出的类别 } dialogShowUtil.dialogShow(\"shake\ } else { if (!((intype || outtype) || ismoney)) { // 如果不含金额 w = \"**提示:\\n你的话中没有包含<类别>(\" + listToString(spdatalist, ',') + \",\" + listToString(spdatalist2, ',') + \")\\n\\n**提示:\\n你的话中没有包含消费或开支的< 金额>\"; dialogShowUtil.dialogShow(\"shake\ } else if ((intype || outtype) && (!ismoney)) { w = \"提示:\\n你的话中没有包含消费或开支的<金额>\\n\"; dialogShowUtil.dialogShow(\"shake\ } else if ((!(intype || outtype)) && ismoney) { for (int i = 0; i < spdatalist.size(); i++) { // 判断是 否包含支出 if (\" 语 音 识 别 \".indexOf(spdatalist.get(i).toString()) > -1) { } w = \"**提示:\\n你的话中没有包含<(默认)类别>(\" + } VoiceSave[5] = Integer.toString(i); VoiceSave[3] = \"语音识别\"; listToString(spdatalist, ',') + \")\\n\\n\\n将会记录为<语音识别>类别,是否依然记 录?\\n\"; } } dialogShowUtil.dialogShow(\"shake\ } else { } dialogShowUtil.dialogShow(\"rotatebottom\ Dialog部分处理代码: public void dialogShow(String showtype, String style, final String context1, String context2) { switch (showtype) { case \"rotatebottom\": effect = Effectstype.RotateBottom; break; case \"shake\": effect = Effectstype.Shake; break; } switch (style) { case \"first\": dialogBuilder.withTitle(\"语音记账\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage(\"语音格式:\\n早餐在餐厅食了20元。\\n\\n\") // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def |// // isCancelable(true) .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"取消\") // def gone .withButton2Text(\"开始语音\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { dialogBuilder.dismiss(); ((AddPay) act).VoiceRecognition(); } }).show(); break; case \"notype\": dialogBuilder.withTitle(\"识别成功\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage(\"你刚刚说了“ \" + context1 + \"”\\n\\n\" + context2) // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def |// .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"取消\") // def gone .withButton2Text(\"是\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { dialogBuilder.dismiss(); } }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { dialogBuilder.dismiss(); VoiceDefault = \"notype\"; VoiceSave[3]=VoiceSave[3]; dialogShow(\"shake\ } }).show(); break; case \"wrong\": dialogBuilder .withTitle(\"识别失败\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage( \"你刚刚说了“ \" + context1 + \"”不符合格式,请再试 一次\\n\\n\" + context2) // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def | // isCancelable(true) .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"取消\") // def gone .withButton2Text(\"再次语音\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); ((AddPay) act).VoiceRecognition(); }).show(); break; case \"OK\": dialogBuilder.withTitle(\"识别成功\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage(\"成功!\\n你刚刚说了“\" + context1 + \"”,\\n 是否确定要记录这条数据?\") // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def | // isCancelable(true) .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"取消\") // def gone .withButton2Text(\"确定\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); ((AddPay) act).VoiceSuccess(); }).show(); break; case \"judge\": dialogBuilder .withTitle(\"识别成功\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage( \"成功!\\n你刚刚说了“\" + context1 + \"”,\\n<\" + VoiceSave[3] + \">类别需要你请确认该笔是<开支>还是<收 入>?\\n\") // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def | // isCancelable(true) .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"开支\") // def gone .withButton2Text(\"收入\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); type = \"pay\"; ((AddPay) act).VoiceSuccess(); }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); type = \"income\"; ((AddPay) act).VoiceSuccess(); }).show(); break; case \"quit\": dialogBuilder.withTitle(\"退出程序\") // .withTitle(null) no title .withTitleColor(\"#FFFFFF\") // def // def .withMessage(\"是否要退出程序?\\n\\n\") // .withMessage(null) no Msg .withMessageColor(\"#FFFFFF\") // def .isCancelableOnTouchOutside(false) // def | // isCancelable(true) .withDuration(700) // def .withEffect(effect) // def Effectstype.Slidetop .withButton1Text(\"取消\") // def gone .withButton2Text(\"退出\") // def gone .setButton1Click(new View.OnClickListener() { @Override public void onClick(View v) { } dialogBuilder.dismiss(); }).setButton2Click(new View.OnClickListener() { @Override public void onClick(View v) { } SysApplication.getInstance().exit(); }).show(); break; } } 5.4 类别维护界面 增加或删除收入/支出类别,并判断类别是否重复是否为空。 图5-4 类别维护界面 部分代码: private void inputTitleDialog() { final EditText inputServer = new EditText(InPtypeManager.this); inputServer.setFocusable(true); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(\"添加类型\").setView(inputServer) .setNegativeButton(\"取消\ builder.setPositiveButton(\"确定\ public void onClick(DialogInterface dialog, int which) { inputStr = inputServer.getText().toString(); int i = (int) itypeDAO.getCount(userid) + 1; if (inputStr.trim().equals(\"\")) { Toast.makeText(InPtypeManager.this, \"输入内容不能为空!\ Toast.LENGTH_LONG).show(); refresh(); } else{ if(flag){ Toast.makeText(InPtypeManager.this, \"不可以重复插入!\ Toast.LENGTH_LONG).show(); }else{ } } }); builder.show(); } refresh(); if (type == 0) { itypeDAO.add(new Tb_itype(userid, i, inputStr)); } else { ptypeDAO.add(new Tb_ptype(userid, i, inputStr)); } 5.5 收入/支出统计界面 收入支出统计页面,通过使用第三方开发的图表显示控件,通过从SQLite获取的数据和计算所占总数的百分比,去初始化图表显示,然后通过线程更新当前的UI。左右的按钮是调用上一个月和下一个月的数据,然后重新调用该activity来显示。另外我还添加了侧滑菜单来让用户选择是“收入图表”和“支出图表”,另外用户还能选择指定的日期范围,数据也是调用该页面显示。 图5-5 收入/支出统计界面 public void initView() { time = new Time(\"GMT+8\"); time.setToNow(); defaultMonth = time.month + 1;// 设置默认月份 defaultYear = time.year; intentr = getIntent(); defaultMonth = intentr.getIntExtra(\"default\defaultYear = intentr.getIntExtra(\"defaultyype = intentr.getIntExtra(\"type\为0,选择上下月,为 1,选择任意时间 textView.setOnClickListener(this); example_left.setOnClickListener(this); example_right.setOnClickListener(this); example_center.setText(String.valueOf(defaultYear) + \"年 - \" + String.valueOf(defaultMonth) + \"月\"); //获取数据 if (type == 0) { KindDatap = payDAO.getKDataOnMonth(userid, defaultYear, defaultMonth); } else { } initItem(); //初始化数据 //当获取到数据时 date1 = intentr.getStringExtra(\"date1\"); date2 = intentr.getStringExtra(\"date2\"); KindDatap = payDAO.getKDataOnDay(userid, date1, date2); if (!(KindDatap.size() == 0)) { } Message msg = new Message(); msg.obj = pieView.getCurrentChartProp(); handler.sendMessage(msg); //发送消息,更新UI pieView.setChartPropChangeListener(new ChartPropChangeListener() { } @Override public void getChartProp(ChartProp chartProp) { } Message msg = new Message(); msg.obj = chartProp; handler.sendMessage(msg); //发送消息,更新UI }); pieView.start(); public Handler handler = new Handler() { }; /** * * Description:初始化转盘的颜色 * */ }; //创建线程 ChartProp chartProp = (ChartProp) msg.obj; myButton.setBackgroundPaintColor(chartProp.getColor()); textView.setText(chartProp.getName()); textView2.setText(chartProp.getName2()); textView.setTextColor(chartProp.getColor()); public void initItem() { int i = 0; int fivecolor[] = new int[] { Color.rgb(56, 220, 244), Color.GREEN, Color.RED, Color.YELLOW, Color.CYAN }; // 没有数据的情况 // 无数据下总数的提示文字 // 获取数据的情况 if (KindDatap.size() == 0) { amount = \"暂无数据\"; } else { double sum = 0.00; for (KindData kp : KindDatap) { } // 初始化数组 String names[] = new String[i]; float percent[] = new float[i]; String names2[] = new String[i]; int color[] = new int[i]; i = 0; for (KindData kp : KindDatap) { names[i] = ptypeDAO.getOneName(userid, sum += kp.getAmount();// 取得总和 i++; kp.getKindname()); if (i < fivecolor.length) { color[i] = fivecolor[i]; // 使用自定义颜色 } else { color[i] = getRandomColor(); // 使用随机生成的 颜色 } .getPercentInstance(); percentFormat.setMaximumFractionDigits(2); // 最大小数 位数 // 自动转换成百分比显示. names2[i] = percentFormat.format(kp.getAmount() / sum) + \":¥\" + kp.getAmount(); // 计 percent[i] = (float) (kp.getAmount() / sum); 算所占百分比 } amount = Double.toString(sum); // 总数的费用 // 创建图表 ArrayList for (int k = 0; k < size; k++) { // 把数据传入图表 i++; } } } ChartProp chartProp = acps.get(k); chartProp.setColor(color[k]); chartProp.setPercent(percent[k]); chartProp.setName(names[k]); chartProp.setName2(names2[k]); pieView.initPercents(); private int getRandomColor() {// 分别产生RBG数值 } public static String getamount() { } @Override public void onClick(View v) { switch (v.getId()) { return amount; Random random = new Random(); int R = random.nextInt(255); int G = random.nextInt(255); int B = random.nextInt(255); return Color.rgb(R, G, B); // 上一个月的按键 if (defaultMonth != 1) defaultMonth = defaultMonth - 1; else { } Intent intentl = new Intent(PayChart.this, PayChart.class); intentl.putExtra(\"defaulty\intentl.putExtra(\"default\intentl.putExtra(\"cwp.id\startActivity(intentl); break; // 下一个月的按键 defaultMonth = 12; defaultYear = defaultYear - 1; if (defaultMonth != 12) defaultMonth = defaultMonth + 1; else { } Intent intentr = new Intent(PayChart.this, PayChart.class); intentr.putExtra(\"defaulty\ defaultMonth = 1; defaultYear = defaultYear + 1; } } intentr.putExtra(\"default\intentr.putExtra(\"cwp.id\startActivity(intentr); break; 6.论文总结 从一月开始,经过这三个月的学习奋斗,毕业设计到现在终于基本上已经完成了。在这段日子里从系统的需求分析开始,然后到对系统功能 进行详细设计,最后到系统的编码实现,最后到论文的完成,我通过查阅大量的图书与文献自学相关知识,同时也诚心请教同学和老师,通过与他们的交流我学到了很多专业知识和经验,让我受益匪浅,对相关专业知识有了一个新的认识,当遇到有不认识或未曾遇到过的错误,上网寻找资料,解决难题,让我懂得网上的资源是十分之多,令我获益良多,这些锻炼了我坚强的意志,同时也使我的专业知识更加扎实,让我在以后的人生职业道路上可以更加的自信和顽强。 毕设做到现在,算是告一段落。谈起为什么选Android,我只能说感兴趣,而又没毅力。在没有压力的情况下,让我去专研一门不懂的东西可行性太低。只能说很了解自己的性子。我想通过这种方式逼自己,幸好没让自己失望。虽然此次的毕设没有很有技术含量,但还是算勉强够凑合吧。 希望经过后期的维护肯定能达到使用要求,更好完善自己系统的功能。 参考文献 [1]FrankAbleson.Introductionto development[J].developerWorks,2009,10(7). [2] Ed Burnett, Hello, Android: Introducing Google’s Mobile Development Android Platform[J]. PRAGMATIC BOOKSHELF,2010.7:10-11. [3] 徐娜子.Android江湖 [M].电子工业出版社.2011.11 [4] 郭志宏. Android应用开发详解[M].电子工业出版社. 2010. [5] 明日科技.Android从入门到精通 [M].清华大学出版社.2012.9 [6] 杨丰盛.Android应用开发揭秘[M]. 机械工业出版社. 2010. [7] 孙宏明.Android手机程序设计入门、运用到精通 [M].中国水利水电出版社.2012.3 [8] 张仕成.基于Google Android平台的应用程序开发与研究[j].电脑知识与技,术2009.(5) [9] 靳岩,姚尚朗. Google Android开发入门与sss实践[M].人民邮电出版社. 2009 [10] 姚永明,吕建平. 基于Android平台的用户管理软件的设计与实现[J]. 西安文理学院学报(自然科学版),2013,01:79-83. [11] 武玉坤.基于Android移动学习平台的设计[J]. 计算机光盘软件与应用,2013,01:20-21+47. [12] 姜海岚.基于Android的多功能手机相册设计与实现[J]. 电脑知识与技术,2013,15:3614-3616. [13] 李刚.疯狂Android讲义 [M].电子工业出版社.2011.6 [14] 李宁.Android应用开发实战[M].第2版. 机械工业出版社.2013 致 谢 经过几个月来的忙碌学习和工作,本次毕业设计已经接近尾声,作为一个本科生的毕业设计,由于经验的匮乏,难免有许多考虑不周全的地方,但有导师的督促指导,最后这个设计将顺利完成,成为第一个完成并可以成功使用的系统。 衷心感谢导师王鹤娴老师的严格要求和悉心指导,她严谨的治学态度将使我终生受益。尤其是在论文写作期间,她百忙之中给予我的指导和帮助,我将铭记 于心。 感谢医药信息工程学院全体老师和我的母校广东药学院四年来对我的大力栽培。 最后,对百忙之中审阅我论文的各位老师,以及参加答辩会的各位老师和同学表示深深的谢意。最后是感谢信息工程学院的全体老师,感谢你们辛勤的栽培。 因篇幅问题不能全部显示,请点此查看更多更全内容