分 类 号:TP311
学校代码:11460
学 号:10130920
本科生毕业论文
基于android平台的语音机器人服务娱乐系统
Robot Entertainment Service System Based on Android Platform
所在系(院):
学 生:
指 导 教 师:
研究起止日期:
学位论文独创性声明
本人郑重声明:
1. 坚持以“求实、创新”的科学精神从事论文写作工作。
2. 本论文是我个人在导师指导下进行的研究工作和取得的研究成果。
3. 本论文中除引文外,所有实验数据和有关材料均是自己研究完成。
4. 本论文中除引文和致谢的内容外,本论文没有抄袭,剽窃他人已经发表的研究成果。
5. 其他同学和导师对本文研究所做的贡献均已在论文中作了声明并表示了谢意。
作者签名:刘倩
2013年 4 月 15 日
摘 要
随着科学技术的发展,人们已不再满足当前人机交换信息的方式,而希望能用自然语言直接进行信息传递,以便大大的提高人的工作效率,语音识别是建立计算机听觉系统的基础,而目前,很大一部分应用都是基于移动互联网技术,也是目前几年国家一直推崇发展的,而近几年移动平台上有关语音识别的应用非常火爆,国内有像挖财和UC浏览器等推出的语音输入和控制功能,在助手类应用中,语音识别更是作为一种必不可少的主流技术,比如现在主流的GPS语音导航系统,基于Android平台的语音播报器等,不仅能增强较完美的用户体验,还能给客户增加不少趣味性,但是目前基于安卓移动平台的机器人大多数都以文字输入形式和机器人进行沟通聊天,内容形式比较单一,缺乏趣味性,现在流行的simsimi小黄鸡中文版是一款运行在Android平台上的安卓手机聊天机器人,虽然拥有庞大的数据库,但是不支持语音聊天,不智能化,因为语音识别是近几年手机开发的主流,所以我想能够开发一款基于Android平台的语音机器人娱乐系统,能够语音和我们的机器人进行聊天,还可以通过语音进行天气的查询,它一样拥有庞大的数据库,而且会越来越智能,越聪明。
关键词:android;java;语音功能;智能;开源系统;数据库;
Abstract
With the development of science and technology, people are no longer satisfied with the current human ways to exchange information, hope can directlycommunicate with natural language, so as to greatly improve people's working efficiency, speech recognition is the foundation, establishing computer auditory system at present, a large part of the application is based on mobile Internettechnology, is currently a few the state has always promoted development, in recent years, the mobile platform application on speech recognition is very hot,there are like the speech input and control function to dig property and a UC browser launched, in a helper class applications, speech recognition is anecessary mainstream technology, such as the current mainstream GPS voice navigation system based on the Android platform, voice broadcast device, can not only enhance the perfect user experience, can increase the number ofinterest to the customer, but the Android mobile platform robot most on text input form and robot communication based on content, form is single, lack of interest,Chinese version of simsimi chicken is popular now a run on the Android platformAndroid mobile phone chat robot, though With a large database, but does not support the voice chat, not intelligence, because speech recognition is the mainstream of the mobile phone development in recent years, so I want to be able to develop a speech robot entertainment system based on Android platform,capable of speech and our robot to chat, also can be the weather by voicequery, it has the same the large database, and will be more and more intelligent,more clever.
Key Words: Android;java; SQLite database; SQLite database; open source system; smart; Voice function;
目录
目录66
1 绪 论11
1.1 研究背景及现状11
1.2语音识别基本原理11语音识别基本原理1
1.3科大讯飞介绍22科大讯飞介绍2
2语音机器人服务娱乐系统的研究分析33
2.1市场可行性33
2.2研究目的44
2.3 Android介绍44
2.3.1 Android平台架构44
2.3.2 Android应用程序构成77
2.4 Eclipse简介88
2.4.1 Eclipse的优点88
3语音机器人服务娱乐系统的需求分析99
3.1 功能需求99
3.2 需求分析99
4语音识别应用系统的设计及相关技术1010
4.1 功能框架1010
4.2 系统实现流程图1212
4.3 用户界面设计1313
4.4 数据存储设计1313
4.5 系统关键技术设计1818
4.5.1 Android用户界面设计问题1818
4.5.2 主界面按钮选择问题2020
5语音机器人服务娱乐应用系统的功能的具体实现2525
5.1 用户登录界面的具体实现2525
5.2 语音聊天功能的实现2828
5.2.1 语音记事本主界面的实现2828
5.3 天气预报功能的实现3232
5.3.1 天气功能的实现3232
5.4 系统设计难点4040
总 结4242
参考文献4343
致 谢4444
1 绪 论
1.1 研究背景及现状
早在计算机发明之前,自动语音识别的设想就已经被提上了议事日程,早期的声码器可被视作语音识别及合成的雏形。而1920年代生产的"Radio Rex"玩具狗可能是最早的语音识别器,当这只狗的名字被呼唤的时候,它能够从底座上弹出来,这就是第一代语音机器人的诞生。
随着现代技术的发展,人们对移动终端的依赖性和期望是越来越大。短信发送,语音通讯,手机小游戏等都已经无法满足人们对移动终端的需求,这些移动终端也开始失去了市场。人们现在都想要各种机器能听懂人类的语言,并且能做到人说什么,机器就会按照人说的话,去执行命令,从而实现人机的语言交流。随着计算机科技的发展,人们的这一想法终于可以实现,这是由于语音识别技术的出现,使得机器通过识别和理解,然后把人的语音信号转变成机器相对应的命令。语音识别技术的应用已经成为当今社会上具有竞争价值的新兴高科技加高技术的产业。它在人机交互中占的比列将会越来越大。所以本课题的研究也正是致力于开发出一款基于android手机平台的语音娱乐服务机器人,除了可以正常的和用户进行语音交流外,还可以实现一些用户生活上的帮助功能,来满足用户的使用和需求,比如查询天气等。
1.2语音识别基本原理
语音识别过程与人对语音识别处理的过程基本上是一致的。它实际上是一种模式识别系统,和常规的模式系统一样,有特征提取、模式匹配、参考模式库等三个基本单元。
语音识别系统的基本结构如图1-1所示。它分为三个步骤:
(1) 前端处理:从语音信号中提取有效的特征参数来代表语音特征,具有很好的区分性。
(2) 声学模型与模式匹配:声学模型通常将获取的语音特征通过学习算法产生,在识别时将输入的语音特征与声学模型进行匹配与比较,得到最佳的识别结果。[5]
(3) 语言处理: 语言处理可以进行语法、语义分析,通过最好有高效的算法,保证语音识别的实现。
图1-1语音识别的原理框图
Android手机上实现语音识别的原理:android手机先将用户语音输入的信号,送至科大讯飞的云端,借助于云端技术可以识别用户的语音输入,云端搜索完毕后,将返回打印数据。
1.3科大讯飞介绍
科大讯飞作为中国最大的智能语音技术提供商,在智能语音技术领域有着长期的研究积累,并在中文语音合成、语音识别、口语评测等多项技术上拥有国际领先的成果。基于拥有自主知识产权的世界领先智能语音技术,科大讯飞已推出从大型电信级应用到小型嵌入式应用,从电信、金融等行业到企业和家庭用户,从PC到手机到MP3/MP4/PMP和玩具,能够满足不同应用环境的多种产品。科大讯飞占有中文语音技术市场70%以上市场份额,语音合成产品市场份额达到70%以上,在电信、金融、电力、社保等主流行业的份额更达80%以上,开发伙伴超过10000家,以讯飞为核心的中文语音产业链已初具规模。
要实现语音机器人的对话功能,必须要用到一下两种技术
语音合成技术
语音合成和语音识别技术是实现人机语音通信,建立一个有听和讲能力的口语系统所必需的两项关键技术。使电脑具有类似于人一样的说话能力,是当今时代信息产业的重要竞争市场。和语音识别相比,语音合成的技术相对说来要成熟一些,并已开始向产业化方向成功迈进,大规模应用指日可待。
语音识别技术
自动语音识别技术(Auto Speech Recognize,简称ASR)所要解决的问题是让计算机能够“听懂”人类的语音,将语音中包含的文字信息“提取”出来。ASR技术在“能听会说”的智能计算机系统中扮演着重要角色,相当于给计算机系统安装上“耳朵”,使其具备“能听”的功能,进而实现信息时代利用“语音”这一最自然、最便捷的手段进行人机通信和交互。
2语音机器人服务娱乐系统的研究分析
本文系统设计采用的开发环境为Windows下的Google Android开发平台。
所需软件如下:
Eclipse 3.3.2
JAVA JDK SE 1.6
Google Android SDK
ADT
2.1市场可行性
随着现今科技技术的发展,3G技术的发展带来了3G手机的到来,基于Android操作系统的手机市场逐步发展壮大,愈来愈多的人开始选择谷歌的Android手机,因此这个市场的商业价值很高,所以我们选择了开发基于Android平台的语音识别应用系统。由于科学技术的不断发展,让各种机器能听懂人类的语言并能按人的命令来行动,从而实现了人类与机器的语言交流。而Android自带的语音功能却很少被开发和应用,没能给人们带来快捷和便利,正因为如此,我决定开发此语音机器人服务娱乐系统,不仅可以和机器人进行简单的聊天交流,同时还可以通过语音来查询天气,并且加入动画增加趣味性,因此我希望我的研发不仅可以成为人们生活的好伙伴,还可以作为儿童们的玩具,而目前正缺少这种带有趣味性,类似汤姆猫,功能也比较多的机器人服务娱乐系统了,它会让你觉得有一个真正的伙伴站你的面前,和你轻松交谈,所以从市场角度来看,十分有必要开发基于Android的机器人服务娱乐系统。
2.2研究目的
随着一批又一批的移动应用不断发布的今天,开发一个具有对话功能的语音机器人服务娱乐系统,会受到大部分小朋友,学生以及年轻上班族的青睐,并且该系统必须具备操作简单,功能俱全,可扩展性好,娱乐性丰富,不单一等特点,现在市场已经有类似的语音机器人,如汤姆猫等,但玩法大多比较单一,对话简单,而这款具有对话功能的语音机器人服务娱乐系统,玩法多样化,能真正的实现智能语音对话的功能,让它成为你工作,娱乐,生活中的好伙伴另外。
通过此次设计,能够掌握android软件开发,掌握控件、数据库SQLite和多线程编程技术。 能够在实践中了解语音识别技术,掌握android语音播报天气等功能,因为语音机器人可不断的完善的功能很多,所以可以涉及到很多android的应用功能,所以希望自己在程序开发的过程中,不断的总结错误,提高自己的实践能力。
2.3 Android介绍
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。
2.3.1 Android平台架构
图2-1 Android的架构流程图
应用程序层(Applications)
该层主要有移动终端常常自带的一些手机软件,如:email客户端,SMS 短消息程序,日历,地图,浏览器,联系人管理程序等。这些应用主要的开发语言是JAVA语言。因此使得熟悉JAVA开发的开发者,能很快的过渡到android系统软件的开发中。开发者开发的软件也是应用在该层上面。
应用程序框架 (Application Framework)
开发人员通过API框架来了解核心应用技术。任何应用程序可以通过发布它的功能块同时任何其它的应用程序都能够使用其所发布的功能块(不过得遵循框架的安全性限制)。同样,任何应用程序重用机制都可以使用户方便的替换程序组件。
隐藏在每个应用程序后面的是一系列的服务系统, 其中包括:
视图(Views)——可以用来创建应用程序,它包括:列表(lists),文本框(text boxes),按钮(buttons),网格(grids)。
内容提供器(Content Providers)——它使应用程序能够访问另一个应用程序的数据,或者分享他们已有的资源。
资源管理器(Resource Manager)——提供了访问资源并且非代码的形式,例如图形,字符串,和一些布局文件(layout files)。
活动管理器(Activity Manager)——专门管理一些程序的生命周期同时提供了常用的导航返回功能。
通知管理器 (Notification Manager)——它让应用程序在显示框中可以显示出自己定义的一些提示信息。
程序库(Libraries)
Android 包含了C/C++库,这些程序库能被Android的系统不同的组件使用。这些组件可以通过Android的程序框架来为开发者提供已设置的服务。以下是已有的核心库:
系统C库——一个继承了BSD而来的标准 C系统的函数库(libc),这是专门为基于嵌入式linux的设备而定制的。
媒体库——该库支持了多种最常用的关于音频、视频的回放和录制,同时还支持静态的图像文件。编码格式包括MP3、JPG、AAC、PNG、AMR。
Surface Manager——它是专门管理显示的子系统,而且应用程序还可以将2D和3D的图层的融合起来。
SGL——底层2D的图形驱动引擎。
3D libraries——图形库,该库使用了3D的硬件和软件加速。
FreeType——位图和矢量,显示字体。
SQLite——任何开发程序都能使用,功能非常好的轻型数据库。
Android 运行库层(Android Runtime)
Android中有自己的核心库,此核心库给予了大多数JAVA编程中的核心库拥有语言功能。所有Android开发程序都是自己在进程中各自运行,它们都有自己的虚拟机实例。JAVA虚拟机被专门设计成专有设备,它能够运行多个虚拟系统。
Android包含一个c/c++的集合,当开发者使用android应用程序架构时,android系统会通过这些集合来支持对开发者使用的各个组件,下面是一些库:
Surface Manager
管理多个程序执行时候的相互存取和显示,同时也负责对2D与3D的绘图进行合成显示。
Media Framework
中文是多媒体库,支持多种常用的视频,音频格式的播放和录制,比如:MPEG4、MP3、H.264、AAC、ARM等。
SQLite
这是相对于Oracle、mysql、sqlserver等一些数据库还小的小型数据库,它是关系型数据引擎。
OpenGL|ES
是根据OpenGL ES API的标准实现的3D绘图函数库。
FreeType
提供矢量和位图。
WebKit
Web浏览引擎。
每个android应用程序都是采用Java语言编写的而且,它都运行在Dalvik虚拟机上,而Dalvik虚拟机只执行“.dex”的文件,Java程序通过编译时,还需要通过android的SDK中的“dx”工具将其转化为“.dex”的后缀文件,才能正常的运行。
Linux 内核(Linux kernel)
Android的核心系统的服务依是基于 Linux的内核,如安全性,内存管理,进程管理,网络的协议栈和驱动模型。
2.3.2 Android应用程序构成
对一个Android应用程序而言,一般是由下面4大组件构造而成:
Activity(活动)
Broadcast Receiver(广播接收器)
Service(服务)
Content Provider(内容提供器)
Activity
应用程序的每个界面都将是Activity类的扩展。Acitvities用视图(View)构成GUI来显示信息、响应用户操作。就桌面开发而言,一个活动(Activity)相当于一个窗体(Form)。
Intent Receiver
应用程序消息传递框架,它是各个组件之间的桥梁,它可以在给特定的服务传播消息来执行你的意图。
Service
Service组件在后台运行,更新你的数据源和可见的Activities,触发通知(Notification)。在应用程序的Activities不激活或不可见时,用于执行依然需要继续的长期处理。
Content Provider
Content Providers用于管理和共享应用程序数据库。是跨应用程序边界数据共享的优先方式。
2.4 Eclipse简介
Eclipse是一种可扩展的开放源代码IDE。2001年11月,IBM公司捐出价值4,000万美元的源代码组建了Eclipse联盟,并由该联盟负责这种工具的后续开发。集成开发环境(IDE)经常将其应用范围限定在“开发、构建和调试”的周期之中。为了帮助集成开发环境(IDE)克服目前的局限性,业界厂商合作创建了Eclipse平台。Eclipse允许在同一IDE中集成来自不同供应商的工具,并实现了工具之间的互操作性,从而显著改变了项目工作流程,使开发者可以专注在实际的嵌入式目标上。
Eclipse框架的这种灵活性来源于其扩展点。它们是在XML中定义的已知接口,并充当插件的耦合点。扩展点的范围包括从用在常规表述过滤器中的简单字符串,到一个Java类的描述。任何Eclipse插件定义的扩展点都能够被其它插件使用,反之,任何Eclipse插件也可以遵从其它插件定义的扩展点。除了解由扩展点定义的接口外,插件不知道它们通过扩展点提供的服务将如何被使用。
2.4.1 Eclipse的优点
Eclipse的最大特点是它能接受由Java开发者自己编写的开放源代码插件,这类似于微软公司的Visual Studio和Sun 微系统公司的NetBeans平台。Eclipse为工具开发商提供了更好的灵活性,使他们能更好地控制自己的软件技术。Eclipse 联盟已经宣布将在2004年中期发布其3.0版软件。这是一款非常受欢迎的java开发工具,这国内的用户越来越多,实际上实用它java开发人员是最多的。缺点就是较复杂,对初学者来说,理解起来比较困难。
3语音机器人服务娱乐系统的需求分析
3.1 功能需求
基于android平台的语音机器人服务娱乐系统,是通过语音与手机交换讲话娱乐的系统,通过系统能够输入对话的信息并语音阅读出来,实现了通过手机象对语音机器人一样讲话服务娱乐的功能。以下是语音识别应用系统具备的功能:
能够和机器人进语音进行聊天,可以由软件开发者修改数据库里的对话内容
设有语音查询天气功能
3.2 需求分析
在软件设计之前,我们需要做的就是在市场针对这一类型的软件进行调查,看是否能够满足于大部分人生活的需要,我们要做的工作就是对语音识别应用系统实现的流程、操作等做出详细的调查,从而了解系统需要实现的功能。系统在开发的过程中,经过了较长时间的设计阶段,需要不断的优化和完善,
4语音识别应用系统的设计及相关技术
4.1 功能框架
本系统旨在建立Android手机,主要有如下几个核心功能模块,如图4-1所示:
Android语音控制系统
图4.1 系统功能框架
功能选择
语音记事本
控制电灯
添加
删除
通过按钮控制电灯开关
通过语音控制电灯开关
添加标题
添加的内容存储到数据库中
删除对应在数据库的内容
图4-1 软件功能模块流程图
各个模块具体功能如下:
语音记事本:
添加模块
点击menu后点击添加进入新的记事本,输入标题和添加记录内容,点击确定BUTTON,保存到数据库中
删除模块
点击menu后,点击删除按钮,即可删除记录
控制电灯:
按钮控制模块
通过开/关Button,来控制灯的开关
语音控制模块
通过按下语音Button,当说开灯/关灯时来控制灯的开/关
4.2 系统实现流程图
启动模拟器后,首先进入的是登录界面,输入用户名和密码后,进入主界面,然后通过两个下面的Button来选择功能界面,并且进行不同的操作,整个流程如图4-2所示:
开始
主界面
功能选择
功能选择
返回
返回
yes
no
说笑话
退出
查询地理位置
系统帮助
图4-2系统实现流程图
4.3 用户界面设计
用户登录界面
用户登录界面是系统运行之后进入的第一个显示界面,用来完成用户的用户名和密码登录,确认以后进入主界面。
主界面
一进入主界面通过按发音按钮,可以和语音机器人进行简单的语音聊天,可以通过发出“北京”等,查询各个城市的天气,并且由语音机器人进行语音播报
通过一个BUTTON按钮,散开式样的风格进行不同的功能选择。
说笑话,可以让机器人语音说笑话
查询地址位置,当选择进入语音记事本后,将进入地理位置功能,将定位你目前的地理位置,自动播报你当前的所在位置。
系统帮助界面,可以显示机器人服务娱乐系统的玩法。
退出,退出系统
4.4 数据存储设计
数据存储方式。可分为:SharePreference、SQLite、Content Provider和File。作为一个完整的应用程序,数据存储操作是不能缺少的。因此,Android系统一共提供了四种数据存储方式。
SQLite: SQLite是一个拥有强大功能的轻量级数据库,支持基本SQL语法,是常被使用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。
SharedPreference: 除了SQLite数据库以外,另一种经常被使用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置。
File: 即常说的文件(I/O)存储方法,常用存储大数量的数据,但是缺点是在更新数据时效率低。
ContentProvider: Android系统中用来实现所有应用程序共享的一种数据存储方式,由于数据通常在各自应用间的是互相私密的,因而此存储方式使用比较少,但是其又是必不可少的一种存储方式。例如音频,视频,通讯录,一般都可以使用此存储方式。每个Content Provider都会对外提供一个公共的URI,当有应用程序有数据需要共享时,就需要使用Content Provider为这些数据定义一个URI,之后其他的应用程序就可以通过Content Provider传入这个URI来对数据进行操作。
本文使用了SQLite数据库来保存语音聊天的对话信息。系统保存了语音主人的问题和机器人的回答,通过SQLite数据库中的保存的主人问题和TTS返回的resultString进行模糊查询。如果匹配成功,则返回机器人的回答,机器人的回答就是SQLite里保存的constant.ANS字段,当然,实现这样一个语音对话需要解决一系列技术问题。比如谷歌的语音包是不支持中文的,为了很快的进行服务器的语音数据提取,目前最主流的语音包是来自科大讯飞的TTS语音包,支持中文,还有就是,数据库如何创建;该数据库包含哪些操作;接下来对数据库的一些操作性的问题做个简单的解答:
SQLite数据库如何创建?
解答:我们都知道Android编程用的也是Java语言,传统的数据库创建和操作是基于一块操作的,那么我们在做JAVA编程的时候就要很好地利用JAVA面向对象的特点,首先我们写一个初始化的类,用来进行数据库和数据表的初始化,创建一个类constants,这个类专门对数据库进行初始化。这样做的目的就是为了方便以后直接利用这个对象进行数据库的操作,这个类如图4-3所示:
图4-3 数据库的操作类图
代码如下:
public class constants extends Activity{
//这里的代码很重要,用来进行数据库的初始化工作
public static final String DATABASE_NAME = "chat.db";
public static final int DATABASE_VERSION = 1;
public static final String CHAT_TABLE_NAME = "chat_table";//对话表名
public static final String ANS = "ans";//对话问题 问题字段名
public static final String QUS= "qus";//对话答案 答案字段名
public static SQLiteDatabase db;
public static final int ACTIVITY_CREATE = 0;
public static final int ACTIVITY_EDIT = 1;
}
如上代码所示,创建一个constants类来初始化数据,在这里数据名为chat.db,数据表为chat_table,有两个字段ans(主人的问题)和qus(机器人的回答).
2.系统应用到的数据库主要就是查询,事先就应该将对话的数据全部写进去,在昨晚数据信息的初始化以后,下一步要做的就是继承SQLiteOpenHelper来创建数据库和数据表,在public void Oncreate(SQLiteDatabase db)中进行数据添加,
代码如下:
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, constants.DATABASE_NAME, null,
constants.DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String sql = "CREATE TABLE " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + " text not null, " + constants.ANS
+ " text not null " + ");";
Log.i("chenggong:createDB=", sql);
db.execSQL(sql);
String sql1 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS + ") values('你好','你好');";
String sql2 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('你是大笨蛋','本机器人不是大笨蛋');";
String sql3 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('你最讨厌什么','写文档');";
String sql4 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('你开心吗?', '我很开心');";
String sql5 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('快点吃饭吧', '嗯,好的');";
String sql6 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('上班咯', '好好工作吧');";
String sql7 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('你能不能给我唱一首歌', '不行,我唱的不好听');";
String sql8 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('谷歌', '谷歌威武');";
String sql9 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('刘倩大笨蛋', '她姐姐才是大笨蛋');";
String sql10 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('你妹', '你妹是刘倩');";
String sql11 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('滚蛋', '为什么');";
String sql12 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('去死吧', '我又没惹你,干吗去死');";
String sql13 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('去死', '为什么');";
String sql14 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('吃饭了', '好吧');";
String sql15 = "insert into " + constants.CHAT_TABLE_NAME + " ("
+ constants.QUS + ", " + constants.ANS
+ ") values('吵死了', '其实我一点也不吵');";
db.execSQL(sql1);
db.execSQL(sql2);
db.execSQL(sql3);
db.execSQL(sql4);
db.execSQL(sql5);
db.execSQL(sql6);
db.execSQL(sql7);
db.execSQL(sql8);
db.execSQL(sql9);
db.execSQL(sql10);
db.execSQL(sql11);
db.execSQL(sql12);
db.execSQL(sql13);
db.execSQL(sql14);
db.execSQL(sql15);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
4.5 系统关键技术设计
4.5.1 Android用户界面设计问题
不去思考Android应用程序的开发过程,对于用户来说最直观的就是Android界面的美化,它直接的影响了用户体验,美工占据程序开发的一个很大一个部分的比重,因此对于Android应用程序的界面布局来说是很重要的。ndroid有三种方式来生成用户的界面:xml配置生成,通过用户自己来生成界面接口,通过用代码来直接生成。依据MVC的原则,界面与程序的逻辑应该互相分离开来,所以xml配置生成界面的方式是最好的。下面主要介绍一下Android界面的布局问题:
FrameLayout(框架布局)
FrameLayout是布局中最为简单的一个布局对象。它为你屏幕上定制一个空白备用区域,然后你就可以在其中填充一个单一对象 ,比如一张你要发布的图片。但是你不能为FrameLayout中的一个子元素指定一个位置,因为它会把其他元素中的一部份或全部挡住。
LinearLayout(线性布局)
LinearLayout是自上而下或者自左向右来进行排列。所有的子元素都会被排放在其它元素的后面,所以一个垂直的列表每行只有一个元素,不管他们宽度有多少。而每个水平方向的列表只会有一个行高。LinearLayout将会保持子元素之间的间隔以及互相对齐。
LinearLayout同时还支持为单独的子元素来指定weight。优点就是允许子元素可以填充屏幕中的剩余空间。当子元素被指定一个weight 值,剩余的空间就会按这些子元素所被指定的weight比例来分配给这些子元素。默认的weight值为0。
AbsoluteLayout(绝对布局)
AbsoluteLayout可以让子元素按照x/y坐标值来显示在屏幕上。其中(0, 0)为左上角,当向下或向右移动时,坐标值将会变大。AbsoluteLayout布局中没有页边框,因此允许元素之间互相重叠。
RelativeLayout(相对布局)
RelativeLayout允许子元素来指定他们自己相对于其它元素的位置(通过ID指定)。因此,你可以通过对齐方式,或置于屏幕中央的形式来对两个元素进行排列。其中元素是按顺序排列,因此如果第一个元素是在屏幕的中央,那么相对于这个元素的其它元素会以屏幕中央的位置来进行排列。
TableLayout(表格布局)
TableLayout按表格的行列来指定位置。其中一个TableLayout是由很多的TableRow来组成,每个TableRow 自己都会定义一个row。TableLayout容器是不显示边框线的。每个row都会拥有0个或多个的cell;每个cell都将拥有一个View对象。而表格是由列和行来组成单元格的。
4.5.2 主界面按钮选择问题
在主界面中,想做到如果有特色的将按钮一次性分布在主界面里,但是发现那样做占据了空间,于是利用Animation动画实现了发散式按钮的设计,主要代码如下:
private void initialButton() // 加载个性按钮的方法
{
// TODO Auto-generated method stub
Display display = getWindowManager().getDefaultDisplay();
height = display.getHeight();
width = display.getWidth();
Log.v("width & height is:",
String.valueOf(width) + ", " + String.valueOf(height));
params.height = 50;
params.width = 50;
// 设置边距 (int left, int top, int right, int bottom)
params.setMargins(10, height - 98, 0, 0);
buttonSleep = (Button) findViewById(R.id.button_composer_sleep);
buttonSleep.setLayoutParams(params);
buttonThought = (Button) findViewById(R.id.button_composer_thought);
buttonThought.setLayoutParams(params);
buttonPlace = (Button) findViewById(R.id.button_composer_place);
buttonPlace.setLayoutParams(params);
buttonWith = (Button) findViewById(R.id.button_composer_with);
buttonWith.setLayoutParams(params);
buttonDelete = (Button) findViewById(R.id.button_friends_delete);
buttonDelete.setLayoutParams(params);
buttonDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (isClick == false) {
isClick = true;
buttonDelete
.startAnimation(animRotate(-45.0f, 0.5f, 0.45f));
buttonWith.startAnimation(animTranslate(30.0f, -150.0f, 60,
height - 230, buttonWith, 100));
buttonPlace.startAnimation(animTranslate(70.0f, -120.0f,
110, height - 210, buttonPlace, 120));
buttonThought.startAnimation(animTranslate(90.0f, -90.0f,
140, height - 170, buttonThought, 140));
buttonSleep.startAnimation(animTranslate(120.0f, -60.0f,
170, height - 130, buttonSleep, 160));
} else {
isClick = false;
buttonDelete.startAnimation(animRotate(90.0f, 0.5f, 0.45f));
buttonWith.startAnimation(animTranslate(-50.0f, 130.0f, 10,
height - 98, buttonWith, 160));
buttonPlace.startAnimation(animTranslate(-100.0f, 110.0f,
10, height - 98, buttonPlace, 140));
buttonThought.startAnimation(animTranslate(-160.0f, 40.0f,
10, height - 98, buttonThought, 80));
buttonSleep.startAnimation(animTranslate(-170.0f, 0.0f, 10,
height - 98, buttonSleep, 50));
}
}
});
buttonSleep.startAnimation(animTranslate(120.0f, -60.0f,170, height - 130, buttonSleep, 160));的API是这样的TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
在这里fromXdelta和from toXdelta都是按钮的初始横坐标与纵坐标的位置, TDelta和Delta都是后面的结束位置,实现的方法如下:
protected Animation animTranslate(float toX, float toY, final int lastX,
final int lastY, final Button button, long durationMillis) {
// TODO Auto-generated method stub
animationTranslate = new TranslateAnimation(0, toX, 0, toY);
animationTranslate.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
params = new LayoutParams(0, 0);
params.height = 50;
params.width = 50;
params.setMargins(lastX, lastY, 0, 0);
button.setLayoutParams(params);
button.clearAnimation();
}
});
animationTranslate.setDuration(durationMillis);
return animationTranslate;
}
protected Animation animRotate(float toDegrees, float pivotXValue,
float pivotYValue) {
// TODO Auto-generated method stub
animationRotate = new RotateAnimation(0, toDegrees,
Animation.RELATIVE_TO_SELF, pivotXValue,
Animation.RELATIVE_TO_SELF, pivotYValue);
animationRotate.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
animationRotate.setFillAfter(true);
}
});
return animationRotate;
}
实现的效果如下图:
点击前:
点击后:
5语音机器人服务娱乐应用系统的功能的具体实现
5.1 用户登录界面的具体实现
系统运行后首先进入用户登录界面图(图5-1):
图5-1 用户登录界面图
用户登录界面中用了可爱的风格,用了固定的用户名和密码登录的方式,判断用户名和密码是否正确,如果正确,则进入系统主界面。
代码实现如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
//得到登录按钮对象
login = (Button)findViewById(R.id.signin_button);
//给登录按钮设置监听器
login.setOnClickListener(lq);
MyApplication.getInstance().addActivity(this);
}
//创建登录按钮监听器对象
OnClickListener lq = new OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//得到用户名和密码的编辑框
username = (EditText)findViewById(R.id.username_edit);
password = (EditText)findViewById(R.id.password_edit);
//判断用户输入的用户名和密码是否与设置的值相同,必须要有toString()
if("liuqian".equals(username.getText().toString())&&
"123456".equals(password.getText().toString())){
System.out.println("你点击了按钮");
//创建Intent对象,传入源Activity和目的Activity的类对象
intent = new Intent(StartActivity.this, MainActivity.class);
//启动Activity
startActivity(intent);
}else{
//登录信息错误,通过Toast显示提示信息
Toast.makeText(StartActivity.this,"用户登录信息错误" , Toast.LENGTH_SHORT).show();
}
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
5.2 语音聊天功能的实现
5.2.1 语音记事本主界面的实现
图5-2 语音聊天的主界面图
如上图5-2所示,为语音聊天的主界面,点击语音,就可以和机器人进行语音聊天,如果单纯是用谷歌的TTS的话,是不支持中文发音的,在网上查找了相关资料,找到了科大讯飞的语音包和TTS程序,首先要做的就是让用户说话,进行语音搜索,代码如下:
speakButton.setOnTouchListener(new Button.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
// 按下按钮先执行一次searchvoice方法
case MotionEvent.ACTION_DOWN:
searchvoice();
}
return false;
}
});
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
protected void searchvoice() {// searchvoice的方法
try {
tts.speak("start speaking!", TextToSpeech.QUEUE_ADD, null);
// 通过Intent传递语音识别的模式,开启语音
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// 语言模式和自由模式的语音识别
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
// 提示语音开始
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "开始语音");
// 开始语音识别
startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "找不到语音设备", 1).show();
}
}
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
id = "";// 天气编号89757
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
} else {
// missing data, install it
Intent installIntent = new Intent();
installIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
最后用返回的resultString和数据库中的字段进行模糊匹配,能够达到查询的目的,再用tts.speak(text, queueMode, params);用来语音朗读出返回的字段,注意这里的字段必须是String类型的,这也是开发中遇到的一个关于怎么样将数据库里的字段转换为String的问题,代码如下:
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
} else {
// missing data, install it
Intent installIntent = new Intent();
installIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
// 回调获取从谷歌得到的数据
if (requestCode == VOICE_RECOGNITION_REQUEST_CODE
&& resultCode == RESULT_OK) {
results = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);// 取得语音的字符
for (int i = 0; i < results.size(); i++) {
resultString = results.get(0);
Log.e("resultString" + i, resultString);
}
Cursor c = dbhelper.getWritableDatabase().rawQuery(
"select * from chat_table where qus like ? ",
new String[] { "%" + resultString + "%" });
// 模糊匹配的时候要加 两个 %,很重要的一句话
if (c == null) {
Log.i("cuolecuolecuolecuole", resultString);
} else {
if (c.moveToFirst()) {
System.out.println(c.toString());
Log.i("duile对了对了对了", c.toString());
tts.speak(c.getString(c.getColumnIndex("ans")),
TextToSpeech.QUEUE_ADD, null);
// tts.speak("对哈对哈对哈", TextToSpeech.QUEUE_ADD, null);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}
下面是关于在Android中使用模糊查询的三种方法:
//1.使用这种query方法%号前不能加' ;
Cursor c_test = mDatabase.query(tab_name, new String[]{tab_field02}, tab_field02+" LIKE ? ",
new String[] { "%" + str[0] + "%" }, null, null, null);
//2.使用这种query方法%号前必须加' ;
// Cursor c_test=mDatabase.query(tab_name, new String[]{tab_field02},tab_field02+" like '%" + str[0] + "%'", null, null, null, null);
//3.使用这种方式必须在%号前加' ;
String current_sql_sel = "SELECT * FROM "+tab_name +" where "+tab_field02+" like '%"+str[0]+"%'";
//Cursor c_test = mDatabase.rawQuery(current_sql_sel, null);
5.3 天气预报功能的实现
5.3.1 天气功能的实现
天气预报,是现在每个安卓用户比不可少的一个应用,它是通过从利用服务器上抓取JSON数据,获得天气信息,并且允许转化为对象。我们在这个设计中,将它转化成String型,用TTS读出。方便懒人没时间看天气,说出“北京”等城市即可,能够有效地查询当日的天气情况,查看是否需要添加衣服等,谷歌的天气预报已经停用,我们利用最有名的中国气象网,从那个网站抓取JSON数据,那么,手机客户端是怎么抓取数据的呢?
看看中国中央气象局的天气数据该如何获取?通过一个链接即可获取到该城市地区的天气数据信息,例如获取扬州的数据可使用http://m.weather.com.cn/data/101190601.html,来获取,101190601是扬州的城市ID,我们通过这个ID用来查询中国中央气象局里的城市天气,这个ID用来区别全国34个省市及地区的唯一标识,就像是我们的身份证号一样,来区别我们每一个人,我们要获取该城市地区的天气数据必须要通过他的ID号来获取,不同于其他的一些天气服务API,例如有的可直接通过汉语拼音来获取,这些相对于ID来说方便一些,至少我们不用去查该城市地区的ID号,这也是中国中央气象局API使用的一个局限性的地方。虽然麻烦一点,但是我们使用别人的东西当然要遵守别人的规则。
城市ID,目前我收录到一份有两千多个城市地区的ID号。如图5-3-1
图5-3-1 城市ID
控制电灯的开关,是android手机通过蓝牙发送信号才能控制,因此,在操控时必须开启蓝牙,连接蓝牙才能操控电灯的开关。
android蓝牙的操作分4步骤:建立本地蓝牙;获取远方蓝牙设备;连接蓝牙;发送socket通信。
首先我们将citycode.txt保存在项目目录的assets下,如图5-3-2所示.
我们定义String类型的id,用于将这个id发送到中国天气网的服务器上,用于通过这个id抓取天气数据
代码如下:
id = findId(resultString);
if (null == id || "".equals(id)) {
Toast.makeText(MainActivity.this, "在集合中,没有找到对应城市id", 1).show();
} else {
// tts.speak(id.toString(), TextToSpeech.QUEUE_ADD, null);
queryWeather();
}
findId的方法的实现代码如下:
private String findId(String cityname) {
if (null == cityname || "".equals(cityname))
return null;
try {
InputStreamReader inputReader = new InputStreamReader(
getResources().getAssets().open("citycode.txt"));
BufferedReader bufReader = new BufferedReader(inputReader);
String line = "";
String[] str = new String[2];
while ((line = bufReader.readLine()) != null) {
str = line.split("=");
if (str.length == 2 && null != str[1] && !"".equals(str[1])
&& cityname.equals(str[1])) {
// 返回对应编号
return str[0];
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
这是Android中以数据流读取assets文件夹中的文件内容的方法,BufferedReader常用于读取中文字符
JAVA开发是先整体,再局部,接着通过ID读取从服务器抓取的天气信息,实现代码如下:
private void queryWeather() {
thread = new Thread() {
public void run() {
super.run();
WeatherForm[] WF = new WeatherForm[3];
WeatherQueryManager WQM = new WeaterQueryManageImpl();
// 查询天气,返回3天的天气信息
WF = WQM.weatherquery(id);// 写到这里不会写了,嗷呜
StringBuffer sb = new StringBuffer();
sb.append("主人,你要查询的天气是:");
sb.append(WF[0].getName());
sb.append("今日温度");
sb.append(WF[0].getTemp() + "度");
sb.append("今天风向");
sb.append(WF[0].getWind());
sb.append("风力指数");
sb.append(WF[0].getWs());
String str = sb.toString();
tts.speak(str, TextToSpeech.QUEUE_ADD, null);
}
};
thread.start();
}
WeatherForm, JAVA Bean对象,如果关系到从服务区获取或传输数据,通常都要用到JAVA Bean,代码如下:
public class WeatherForm {
/**城市名*/
private String name;
/**城市编号*/
private String id;
/**温度*/
private String temp;
/**天气描述*/
private String weather;
/**风力*/
private String wind;
/**风向*/
private String ws;
public WeatherForm(){
}
/**
* 构造方法
* @param name
@param wind
* @param temp
@param time
@param ws
*/
public WeatherForm(String name, String id, String ddate, String week,
String temp, String weather, String wind, String fx,String time,String ws) {
super();
this.name = name;
this.id = id;
this.temp = temp;
this.ws= ws;
//this.weather = weather;
this.wind = wind;
//this.fx = fx;*/
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getWind() {
return wind;
}
public void setWind(String wind) {
this.wind = wind;
}
public String getWs() {
return ws;
}
public void setWs(String ws) {
http://this.ws = ws;
}
public String toString() {
return "WeatherForm [name=" + name + ", temp=" + temp + ",wind=" + wind + ",ws=" + ws + "]";
}
}
那么,客户端又是怎么样从服务器端获取数据的呢?这里用到了json数据的传输
public class WeaterQueryManageImpl implements WeatherQueryManager {
private final String TAG = "message";
public String Weather_result;
@Override
public WeatherForm[] weatherquery(String CityId) {
// TODO Auto-generated method stub
WeatherForm[] WF = new WeatherForm[1];
// http://m.weather.com.cn/data/101070101.html
String URL = "http://www.weather.com.cn/data/sk/" + CityId + ".html";
Weather_result = "";
HttpGet httpRequest = new HttpGet(URL);
// 获得HttpResponse对象
try {
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = httpClient.execute(httpRequest);
if
(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
// 取得返回的数据
Weather_result=EntityUtils.toString(httpResponse.getEntity());
}
} catch (Exception e) {
Log.i(TAG, e.toString());
WF[0] = new WeatherForm();
return WF;
}
// 以下是对返回JSON数据的解析
if (null != Weather_result && !"".equals(Weather_result)) {
try {
JSONObject JO = new JSONObject(Weather_result).getJSONObject("weatherinfo");
for (int i = 0; i < WF.length; i++) {
WeatherForm weaf = new WeatherForm();
// 3个日期暂时都存放一天的
weaf.setName(JO.getString("city"));
String city=JO.getString("city");
Log.i("fdsafdasfdsfsafdsffffffff",city);
/*weaf.setDdate(JO.getString("date_y"));
weaf.setWeek(JO.getString("week"));*/
weaf.setTemp(JO.getString("temp"));
String temp=JO.getString("temp");
Log.i("fdsafdasfdsfsafdsffffffff",temp);
weaf.setWind(JO.getString("WD"));
//weaf.setWeather(JO.getString("weather" + (i + 1)));
String wind=JO.getString("WD");
Log.i("fdsafdasfdsfsafdsffffffff",wind);
weaf.setWs(JO.getString("WS"));
WF[0] = weaf;
Log.i("强制一下咯",WF[0].toString());
}
} catch (JSONException e) {
Log.i(TAG, e.toString());
WF[0] = new WeatherForm();
return WF;
}
}
return WF;
}
}
这样,就实现通过Http的Get方法获取到了JSON数据,从而实现了语音播报天气的功能
5.4 系统设计难点
动画的实现
如何根据在TTS发音的同时,设计的动画也跟着运动,在Android中的动画是由anim.xml来制作的,通过一帧一帧的图片形成动画,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/duola" android:duration="800"></item>
<item android:drawable="@drawable/duola2" android:duration="400"/>
<item android:drawable="@drawable/duola" android:duration="800"></item>
</animation-list>
利用一帧一帧的图片形成了动画的效果,如图5-4-1所示
图5-4-1 动画
在开发过程中,首先定义private AnimationDrawable background;
background = (AnimationDrawable) imageView.getBackground();
发现在OnActivityResult用
background.stop();
background.start();
并不能实现根据讲话才播放动画
解决方案如下:
总 结
本系统阐述了基于android平台的语音机器人服务娱乐系统。设计中显示出了Android平台的优势,分析Android的功能特征、架构分析以及应用程序的构成。探讨了本系统的需求分析、具体的功能模块和界面的设计,实现了语音聊天,语音查询天气,包括按钮控制和语音控制,并且提供了一些具体功能的实现过程,很好地增强了用户和使用者的体验
在开发中也遇到一些调试错误的问题,在老师的帮助下,及时的得到了解决。
经过测试本系统基本实现了语音识别的基本功能,通过本次系统的开发,了解了语音识别以及语音合成的原理,能够满足用户的基本需求。但是由于时间紧迫和本人的能力有限,本系统中还存在着一些不足之处,需要进一步的完善和改进。如果要进一步继续完善开发,今后将会从下面几个方面进行功能的扩展:提高语音机器人的智能性,增加趣味性,界面做的更加人性,美观。希望在我以后的学习和工作生涯中继续研究,继续完善。
纸上得来终觉浅,绝知此事要躬行,时间是检验真理的唯一标准,总的来说,这次的课程设计对我来说是一次非常难得的锻炼和动手实践机会。使我对所学的专业课知识得到了融会贯通,得到了比任何一门课都大的提高和进步。
我认为毕业设计对于我们来说不是一次应付学校,应付老师的作业,而是作为计算机专业的学生在大学这几年的学习成果的最佳展现
参考文献
[1]胡光锐,语音处理与识别,上海科学技术文献出版社,1994.
[2]深入浅出Google Android/E2Ecloud 工作室编著。—北京:人民邮电出版2009.8
[3] Google Android开发入门与实战/靳岩,姚尚朗编著。—北京:人民邮电出版社,2009.7
[4] Google Android SDK开发范例大全/余志龙等编著;王世江改编。—北京:人民邮电出版社,2009.7(2009.8重印)
[5] 周迪伟.计算机语音处理[M].北京:国防工业出版社,1987,130-146
[6] 王炳锡,屈丹,彭煊,实用语音识别基础[M].北京:国防工业出版社,2005
[7] 拉宾纳 L,Rabiner Lawrence,阮平望, Juang Biing-Hwang, 语音识别基本原理, 清华大学出版社, 1999
致 谢
我希望时间慢点过,因为总觉得还有很多东西需要我们认真学习,回想起以前的大学生活,觉得来到了学校不虚此行,在大学里,我遇到了很多优秀的老师和同学,在我最迷茫的时候,是老师们给了我鼓励,指引了我前进的方向,在我最失意的时候,是同学给了我支持,让我坚持我自己想走的路,感谢他们对我的帮助.
此次的毕业设计的顺利完成,在这里我要感谢我的指导老师:包依勤老师,从选题到设计制作到最后的论文的写作和修改的整个过程中,包老师给了我很多指导,让我坚持将这个毕业设计完成了下来,让我们能够真正的做到,实践是检验真理的唯一标准,现在论文已快接近尾声,在这里,我要对包老师表示最衷心的感谢,感谢他在我的开发过程中给予的帮助和鼓励,是他引领了进入了实验室,感受了编程开发的快乐,也是他带我们走进了android的世界,在下课之余,老师也不厌其烦的回答我们各种在编程中遇到的问题,同时包老师严谨的治学态度和刻苦的敬业精神给我留下了深刻的印象,他对编程的热爱同时也感染了我们这些学生.谢谢你,老师
此次毕业设计能够顺利完成,是在老师的指导下,让我更加了解到了软件开发的整个流程,让我养成了治学严谨的态度,这对我以后走出校园,进入工作当中是非常有益的.
希望在我以后的工作和学习生活当中,能够像老师一样,认真对待生活中的每一件事.