基于Android平台开发生活小助手-毕业论文 - 图文

更新时间:2024-04-30 15:58:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

毕业设计(论文)

题 目:基于Android平台的手机应用开发-生活小助手 学 院: 专 业: 学生姓名: 班级/学号: 指导老师/督导老师:

起止时间:

摘要

摘 要

Android是基于Linux平台的开源手机操作系统,该平台由操作系统、中间件、用户界面和应用软件组成,是第一个为移动终端打造的真正开放的、完整的移动平台。Android 平台正在被越来越多的开发者和使用者接受。

本设计以任务书要求为标准、以智能手机用户常用功能为主,确定了生活小助手软件的功能和框架。本设计首先要安装JAVA JDK、Eclipse和 Android,配置Android开发环境。在Android开发环境搭建完成后,依照求分析、软件设计、软件实现以及最终测试的步骤开发生活小助手,实现了天气预报、食谱、列车时刻表三大功能。此外,本软件的天气预报和列车时刻表的功能在联网情况下才能使用,而食谱则无需联网,直接通过访问本地数据库获取数据。

关键词:安卓;Web Service;数据库;

I

Abstract

Abstract

Android is an open source phone operating system based on Linux platform. It consists of the operating system, middleware, user interface and core application software. It is the first to create real mobile terminal open and complete mobile software. Android platform is being more and more developers and users to accept.

The design takes task book requirements as standard and focus on functions which smartphone users usually use. Firstly, the design uses the installation of JAVA JDK, Eclipse and Android, installation and configuration of Android development environment. After setting up an Android development environment, develop the life assistant system in accordance with requirements analysis, system design, system implementation and test. This software implements the weather forecast, train schedule and recipes. In addition, weather forecast and train schedule can function under the network environment. However, Recipe directly obtains data by accessing the local database without the network.

Keywords: Android; Web Service; SQLite;

II

目录

目 录

摘要(中文) ................................................................... I 摘要(英文) .................................................................. II 第一章 概述 .................................................................... 1

1.1 1.2 1.3 2.1 2.2 2.3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 4.1 4.2 4.3 5.1 5.2 5.3 5.4 6.1 6.2

开发背景 ...................................................................... 1 课题的目的与设计步骤 .......................................................... 1 论文组织结构 .................................................................. 2 功能需求 ...................................................................... 3 UI需求 ........................................................................ 4 数据需求 ...................................................................... 4 Intent .......................................................................... 5 BroadcastReceiver ............................................................... 5 Service ........................................................................ 7 SQLite ......................................................................... 8 Web Service ................................................................... 10 SOAP协议 ..................................................................... 10 HTTP POST请求 ............................................................... 11 SAX解析 ..................................................................... 13 软件结构设计 ................................................................. 16 系统界面设计 ................................................................. 16 系统数据库模型设计 ........................................................... 17 主界面 ....................................................................... 20 食谱功能模块 ................................................................. 21 列车时刻功能模块 ............................................................. 27 天气预报功能模块 ............................................................. 32 测试过程 ..................................................................... 37 测试总结 ..................................................................... 41

第二章 需求分析 ................................................................ 3

第三章 关键技术介绍 ............................................................ 5

第四章 生活小助手软件设计 ..................................................... 16

第五章 生活小助手软件实现 ..................................................... 20

第六章 生活小助手软件测试 ..................................................... 37

结束语 ........................................................................ 42 参考文献 ...................................................................... 43

III

正文

第一章 概述

1.1 开发背景

智能手机是目前大家用的最多的移动终端设备,我们的生活也与之息息相关。随着3G、4G网络的发展,智能手机市场也随之变化。下面对三大操作系统(Android, IOS, Windows Phone)进行介绍。

IOS是苹果公司开发的操作系统。它的系统架构分为核心服务层 、核心操作系统层 、可轻触层和媒体层。操作系统的大小大约512M。IOS存在一些缺点,如:严格的第三方软件审查、高昂的价格、难以安装软件。

Windows phone是微软公司开发的手机操作系统,具有一系列超前的操作体检,如:可拖拽的图标、可自定义的桌面、滑动控制等。Windows phone的电子邮件体验相对良好,其定制服务具有多样性,Windows Live体验增强。它的缺点是不支持存储卡,无法在手机上管理文件等。

Android是Google推出的开源手机操作系统,基于Linux平台。该平台由四层组组成,分别是操作系统、中间件、用户界面和应用软件。Android系统平台具有五大特点,分别是:不受运营商约束、开放性、不受任何开发商的限制、可供选择的硬件较为丰富、无缝结合的Google应用。垃圾软件太多是其主要缺点。

IOS的界面设计超酷、用户体验良好、可支持的第三方软件相当多。IOS的硬件成本随着其不断升级也在不断降低,与此同时,IOS的用户也随着增多。Window phone虽然具有超酷的用户体验,以及便捷的OFFICE办公软件,但是与IOS和Android相比,它的功能不够强大,也没有良好的增长空间。与IOS相比,在界面设计、软件支持、网络等方面,Android毫不逊色。并且Android是开源的,任何移动厂商都可以免费使用,因此,从价格方面而言,Android更具优势,其市场份额也将不断增加。

1.2 课题的目的与设计步骤

本软件目的是为广大Android智能手机用户,提供一个便利的信息获取渠道。本软件实现的功能是以任务书的要求为标准、用户使用频繁的工具为主,其中包括:食谱、天气预报、列车时刻。

一个软件就可以满足用户查询食谱、天气预报和列车时刻表的功能,这避免用户为了各个获取信息不断切换应用程序,在极大程度上节省了时间,同时也降低了硬件资源的浪费。

本软件的设计步骤如下图:

根据任务书确定实现的功能设计UI界面,进行UI布局确定设计的目标、相关技术草拟UI界面,收集相关图标、背景等素材了解用户使用习惯,进行需求分析画出功能模块图编写各个功能模块的代码设计SQLite数据库进行系统功能测试,完善功能,优化界面 图1-1 设计流程图

1

正文

1.3 论文组织结构

此次毕业设计主要是对生活小助手软件的UI界面设计和各模块程序代码的编写。主要工作包括:设计每一个功能显示界面,设置界面中每一个控件的布局,设计界面背景图片,控制按钮的点击效果,创建并使用本地数据库,从Web Service获取天气信息和列车时刻信息并存储等等。

经过近13周的努力,基本上完成了此次软件开发的任务。本文总结了生活小助手软件开发过程,全文内容共六章,具体安排如下:

第一章概括了开发背景、课题意义。

第二章是需求分析,主要针对此软件进行了功需求、UI需求和数据需求等各方面的分析。

第三章是关键技术介绍,主要介绍了开发中所涉及到的相关技术,主要包括:Intent、BroadcastReceiver、Service、Web Service、SOAP协议、HTTP POST请求、SAX解析。并摘取部分软件代码作为示例代码。

第四章是系统设计,主要介绍了系统结构设计、界面设计和数据库设计,给出了系统结构模型图,主要界面的设计草图(用PhotoShop软件设计),以及各个数据库表的设计情况。

第五章是系统实现,介绍系统的各个功能,并呈现了核心代码。

第六章是系统测试,展示出来的是列车时刻表模块的测试过程,其它模块不予展示。 最后是总结全文。

2

正文

第二章 需求分析

在生活小助手软件开发之前,要做好充分的需求分析。首先进行功能需求分析,根据生活小助手软件的三大模块:天气预报、食谱、列车时刻表,分析每个模块要实现的具体功能,了解最终达到的目的。其次,进行UI需求分析,对于此软件开发,UI界面必不可少,分析用户的使用习惯,确定UI界面设计需要的图片和按钮。最后,则进行数据需求分析,用户使用软件的最终目的是获取数据信息,分析本软件开发需要的数据,从而确定数据来源并收集相关数据信息。

2.1 功能需求

2.2.1 主界面功能需求

系统主要实现三大功能:天气预报,食谱,列车时刻表。为了便于用户的操作,该软件中各个功能之间的切换是通过主界面的按钮点击事件实现的,因此需要在主界面中设计四个按钮供玩家选择,分别是“天气”、“食谱”、“列车”。这样的设置让用户一目了然,各具体功能如下:

? 天气:点击跳转到天气界面,开始查询默认城市的天气,并可以添加、删除城市

? 食谱:点击跳转到食谱界面,可以查询、浏览食谱信息、存储食谱信息、并且可以自制食谱。 ? 列车:点击跳转到列车界面,可以通过站站、车次查询列车信息,可以把查询到的列车信息存储

在本地,以便在无网络的情况下使用。

2.2.2 事件响应需求

系统的事件响应主要是按钮响应和图片响应,根据不同动作做出不同响应,依据这些事件响应实现界面的跳转、对话框的显示等等。具体功能如下图:

添加城市天气信息显示城市刷新天气首页天气信息食谱推荐列车首页保存站站查询车次查询提醒我自制菜谱我的收藏 图 2-1 系统功能模块图

3

正文

2.2 UI需求

一个软件是否受欢迎,取决于它的功能和观赏性,越来越多的Android软件出现使用户的要求越来越高,所以软件的界面优化和图形设计时至关重要的。具有以下美工需求:

? 背景:项目要实现三大功能,不可避免的要分为很多界面,每个界面需要不同的图片和图形元素。

这些界面有的只需要一个背景图片,但有时候则需要多张背景图片叠加构成。

? 按钮:本项目对按钮要求较高,按钮的使用方便了触屏的操作,每个界面都不可缺少按钮。 为了满足用户对UI的要求,计划采用下载网上素材和设计两种方式,用Photoshop图片处理软件处理图片、设计按钮等从而达到简洁美观的效果

2.3 数据需求

该项目对于数据信息的处理较多。食谱信息是存储在本地,可以直接通过对数据库查找读取信息。天气预报和列车时刻信息则需要通过调用Web Service获取数据。具体信息输入输出情况如表2-1:

表2-1 信息输入输出 信息输入 选择食谱名称 输入天气预报城市 信息处理 软件通过数据库查询相应的食谱信息 软件通过联网获取该城市信息后筛选出有用信息 信息输出 显示食谱信息 输出有用信息 输出该车次信息 输出车次信息列表 刷新收藏的食谱信息列表 刷新收藏的城市信息列表 刷新收藏的列车信息列表 用户输入列车车次 软件通过联网获取该车次的始发站、时间、路程信息 输入列车始终站 收藏食谱信息 收藏城市信息 收藏列车信息

软件通过联网获取相关车次、时间等信息 对数据库的食谱信息管理 对数据库的城市信息管理 对数据库的列车信息管理 4

正文

第三章 关键技术介绍

根据对生活小助手软件的功能需求分析,可以确定此次开发所涉及的关键技术。Intent在Android软件开发中几乎是必不可少的,在此次开发中,其主要是用于activity之间的数据传递以及activity间的跳转。BroadcastReceiver、service与SOAP协议这三项技术主要是通过访问Web Service获得天气预报数据怒。本软件通过HTTP POST请求获取列车时刻表的数据流,然后通过SX解析获得所需要的信息。SQLite数据库主要实现数据添加、删除和查询功能。

3.1 Intent

Intent翻译为意图,使用它可以给其他的Activity或Service组件传递数据,Intent相当于组件间通信的桥梁。通俗地说就是告诉系统我们要干什么,Intent有显式和隐式之分,显示的Intent是根据组件的名称直接启动要启动的组件,如Service或者Activity;隐式的Intent通过配置的action,category,data来找到匹配的组件并启动。

在显式Intent中,如果程序已经明确了目标组件,那么就可以通过显式意图的调用方式直接启动。在Android中通过Intent对象来传递数据给另一个Activity。可以传递的数据类型包括:byte、byte[]、char、char[]、boolean、boolean[]、short、short[]、int、int[]、long、long[]、float、float[]、double、double[]、String、String[]。

示例说明如下: FoodHomeActivity.java

//通过传递Intent对象传递数据

Intent intent =new Intent(FoodHomeActivity.this, FoodSearchActivity.class);

FoodSearchActivity.java:

//获得从FoodHomeActivity中获得食谱名

Intent intent=this.getIntent();

foodname=intent.getStringExtra(\

intent.putExtra(\startActivity(intent);

显式Intent的目的性比较明确,而隐式Intent则不同。在隐式Intent中,没有明确的目标组件名称,所以系统需要帮助应用程序寻找组件,该组件要与Intent请求意图相匹配。在IntentFilter中包含了系统所有可能的待选组件,Android将Intent的请求内容和IntentFilter过滤器比较。如果隐式Intent请求的内与IntentFilter中的某一组件相匹配,那么Android就选择该组件作为该隐式Intent的目标组件。

3.2 BroadcastReceiver

Broadcast是一种广泛应用在应用程序之间传输信息的机制,而BroadcastReceiver主要作用是对发送出

5

正文

来的Broadcast进行过滤接收。BroadcastReceiver自身并不是实现用户界面,但是当它接收到某个Broadcast后,BroadcastReceiver可以启动Activity作为响应,或者启动Service等。

BroadcastReceiver的生命周期只有一个onReceive()方法,在BroadcastReceiver接收到Broadcast时执行,而用户可以做出相应的处理,往往需要对接收到的所有Broadcast进行过滤,只对一种或者一类进行处理。在需要发送信息的地方,用Intent对象装载要发送的信息和用户过滤的信息,然后调用sendBroadcast()、sendOrderBroadcast()等方法,把Intent对象以广播方式发送出去。

代码说明如下: WeatherMainActivity.java:

//为BroadcastReceiver指定action,

private final String BROADCAST_ACTION = \private MyBroadcastRecever myBroadcastRecever; //定义广播接收器

//注册广播接收器

IntentFilter filter = new IntentFilter();

//初始化广播接收器

myBroadcastRecever = new MyBroadcastRecever(); //接收同action的广播

filter.addAction(BROADCAST_ACTION); //注册广播接收器

registerReceiver(myBroadcastRecever, filter);

//定义一个广播接收器,用于接收Service获得的天气信息

class MyBroadcastRecever extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

String[] weatherInfo = intent.getStringArrayExtra(\if(weatherInfo==null){ }else if(weatherInfo.length==1){

//即weatherInfo = new String[]{\

Toast.makeText(WeatherMainActivity.this, \连接超时,请检查网络\

}

}

}else{ }

showWeather(weatherInfo);

Toast.makeText(WeatherMainActivity.this, \没有当前城市的天气信息\

6

正文

3.3 Service

Service组件和Activity的地位是并列的,只是它没有可视化的用户界面,也没有Activity的使用频率高。Service运行于应用程序的主线程中,因此它不会阻塞其他组件和用户界面。

Service启动或停止服务有以下3种方式:

? 调用context.startService()启动,调用context.stopService()结束。 ? 调用service.stopSelf()或service.stopSelfResult()来停止。

? 调用context.bindService()建立,调用context.unbindService()关闭。 服务的生命周期方法只有3个,而且都是public属性

采用onstartService()启动服务。在服务未被创建时,系统调用服务的生命周期方法是:onCreate()->用onStart()->onDestroy()。如果服务在调用startService()方法前已经被创建,多次调用startService()方法不会导致服务被多次创建,但onStart()方法会被多次调用。

void onCreate() //当Service创建时执行,不能直接调用 void onStart(Intent intent) //在oncreate()之后,开始启动Service void onBind(Intent intent) //在oncreate()之后,绑定服务到组件 void OnUnbind(Intent intent) //在onDestroy()之前,先解除绑定,再退出 void onDestroy() //Service被销毁的时候执行

采用bindService()启动服务。在服务未被创建时,,系统调用服务的生命周期方法是onCreate()->onBind()->onDestroy()。如果服务在调用bindService()方法前已经被绑定, bindService()方法的多次调用并不会导致服务被多次创建及绑定,

代码说明如下: WeatherWebService.java:

public class WeatherWebService extends Service{ /**此处要与MainActivity一致*/

@Override

private final String BROADCAST_ACTION = \private String city;

public IBinder onBind(Intent intent) { }

public void onStart(final Intent intent, int startId) {

new Thread(new Runnable() {

@Override public void run() {

//调用全局变量

7

return null;

@Override

正文

}

} }

}

Lifegloabl gloablcity=(Lifegloabl)getApplicationContext(); city=gloablcity.getcityname(); String[] weather = null; try { }

Intent i = new Intent(); i.putExtra(\i.setAction(BROADCAST_ACTION); sendBroadcast(i);

weather = getWeather();

//发生超时,返回值区别于null与正常信息 weather = new String[]{\e.printStackTrace(); } catch (Exception e) {

}).start();

super.onStart(intent, startId);

private String[] getWeather() throws IOException, XmlPullParserException{

return WeatherUtil.getWeather(city);

3.4 SQLite

SQLite是一个使用C语言编写的轻量级开源数据库,它占用的资源非常少,已广泛用于嵌入式产品中。在实际应用中,为了能够更好地管理和维护数据库,将封装一个继承自SQLiteOpenHelper类的数据库操作类,用于完成数据库的创建、升级等操作。

SQLiteOpenHelper是一个抽样类,在该类中有如下两个抽象方法。 public abstract void onCreate(SQLiteDatabase db)

public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) SQLiteOpenHelper的子类必须继承这两个方法。

SQLiteOpenHelper会自动检测数据库文件是否存在。如果存在,则直接打开这个数据库,并不会再创建数据库文件。如果不存在,SQLiteOpenHelper先创建一个数据库文件,然后打开这个数据库,最后调用onCreate方法。

SQLite支持的常用SQL如下。 ? 创建表

create table if not exists user(_id integer primary key autoincreament,name text)

8

正文

? 查询数据 select * from user

select user_name from user where user_id=’1002’ ? 删除数据

Delete from user where user_id=’1002’

实例代码如下 LifeSqlite.java

public class LifeSqlite extends SQLiteOpenHelper{ private SQLiteDatabase database;

public LifeSqlite(Context context, String name, CursorFactory factory, }

/**FOOD列表添加数据**/

9

} }

int version) {

super(context, name, factory, version); // TODO Auto-generated constructor stub

public void openMyDatabse(){

database=getWritableDatabase();//获取数据库对象

@Override

public void onCreate(SQLiteDatabase db) {

//创建表CITY

String create_cityTable=\

+ CITY_ID + \+ CITY_NAME + \

db.execSQL(create_cityTable);

public void insertFOOD(String foodname,String foodmaking,String foodmaterial,int foodimage){ }

String insert_food=\

TABLE_FOOD_NAME +

\FOOD_MAKING + \foodname + \foodmaking + \ + \

database.execSQL(insert_food);//执行插入数据操作

正文

@Override }

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }

// TODO Auto-generated method stub

3.5 Web Service

Web Service是为了支持垮网络的机器间相互操作交互而设计的一种跨编程语言和跨操作系统平台的远程调用技术,当用户需要一种能够在不同计算机间的不同语言编写的应用程序系统中通过网络通信实现函数和方法调用的能力时就需要Web Service。

任何一个平台都有各自的数据表示方法和类型数据库,为了保证每个平台都能够使用Web Service,Web service平台需要一套协议来实现分布式应用程序的创建。要实现互操作性,Web Service平台必须提供一套标准的类型系统,用于沟通不同平台、编程语言和组件模型中的不同类型系统。目前这些协议有:XML和XSD、SOAP、WSDL、UDDI。

3.6 SOAP协议

SOAP是指简单对象访问协议,它是一种轻量的、简单的、易于扩展的、与平台和编程语言无关的基于XML的消息通信格式,用于在网络上、不同平台、不同语言的应用程序间的通信。

下面介绍一下SOAP的基本语法。在用于表示 SOAP消息的XML文档中,有一些必需和可选的元素。其中Envelope和Body元素是必需的。

? Envelope元素:它是SOAP消息文档根元素,用于表示一条SOAP消息。

? Header元素:表示该SOAP消息包含的头部消息标签,必须是Envelope元素的子元素。 ? Body元素:包含所有的调用和响应的主体信息的标签,该元素包含传递消息的内容。

? Fault元素:表示错误信息标签,必须是Body的子元素,且在一条SOAP消息中只能出现一次。 (1) 指定Web Service的命名空间、调用方法、URL /** 命名空间 */

10

private static final String NAMESPACE = \/** 获取天气的WebServiceURL */

private static String URL = \/** 调用方法 */

private static final String METHOD_NAME = \/** 命名空间+方法名 */

private static String SOAP_ACTION = \通过城市名字获

取天气

正文

(2) SoapObject对象的创建,它是SOAP协议的BODY。

// 实例化SoapObject对象

SoapObject soapObject = new SoapObject(NAMESPACE, METHOD_NAME); // 2.如果方法需要参数,设置参数

soapObject.addProperty(\

(3) 创建HTTPTransportsSE对象,指定超时时间

int timeout = 20000;

// 设置超时为20秒。即如果没有网络或者网络不好时,超过10秒则会出异常

MyAndroidHttpTransport httpTransportSE = new MyAndroidHttpTransport(URL, timeout); httpTransportSE.debug = true;

(4) 生成调用Web Service方法的SOAP请求信息,指定SOAP Version

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); envelope.bodyOut = soapObject; envelope.dotNet = true;

envelope.setOutputSoapObject(soapObject);

(5) 使用call()方法调用Web Service()方法

httpTransportSE.call(SOAP_ACTION, envelope);

(6) 获取返回的结果

// 保存获取到的信息

SoapObject detail = null;

detail = (SoapObject) envelope.getResponse();// 获取详细天气信息

(7) 解析返回值

String[] weather = new String[12];// 一共有12组数据 String date=detail.getProperty(6).toString(); weather[0]=date.split(\ weather[1]=detail.getProperty(5).toString();//11/10 weather[2]=date.split(\阵雨转阴

weather[3]=detail.getProperty(7).toString();//无持续风向微风 weather[4]=detail.getProperty(8).toString();//2.gif

weather[5]=detail.getProperty(11).toString();//穿衣指数

3.7 HTTP POST请求

HTTP是Internet中广泛使用的协议,自然,Android SDK拥有强大的HTTP访问能力。在Android SDK中可以采用多种方式使用HTTP,如HttpURLConnection、HttpGet、HttpPost等。

HttpPost用来提交HTTP POST请求。使用HttpPost必须通过如下3步来访问HTTP资源。

11

正文

示例代码如下:

/** 获取天气的WebServiceURL */

String url

= \ + \//使用HTTPPOST=对象提交数据

HttpPost httpRequest=new HttpPost(url); //超时设置

HttpParams params=new BasicHttpParams(); //从连接池获取连接的超时时间

ConnManagerParams.setTimeout(params, 1000); //通过网路与服务器建立连接的超时时间

HttpConnectionParams.setConnectionTimeout(params, 3000); //读响应数据的超时间

HttpConnectionParams.setSoTimeout(params, 5000); //设计请求参数

httpRequest.setParams(params); //传递请求参数

List paramsList= new ArrayList();

paramsList.add(new BasicNameValuePair(\paramsList.add(new BasicNameValuePair(\paramsList.add(new BasicNameValuePair(\ UrlEncodedFormEntity murlEncodedFormEntity= new UrlEncodedFormEntity(paramsList,HTTP.UTF_8); httpRequest.setEntity(murlEncodedFormEntity);

HttpResponse httpResponse=new DefaultHttpClient().execute(httpRequest); //使用GetEntity方法获得返回结果

final int ret=httpResponse.getStatusLine().getStatusCode(); if (ret==HttpStatus.SC_OK) {

inputStream=httpResponse.getEntity().getContent(); }

12

正文

3.8 SAX解析

SAX解析采用了基本事件的模型,解析快、占内存少。它是按顺序解析XML文档,在解析过程中触发一系列回调方法执行,从而获取到我们关注 的内容。

SAX API中主要有四种处理事件的接口:ContentHandler,DTDHandler, EntityResolver 和 startDocument() 在文档开始时调用这个方法 endDocument() 当文档结束的时候,调用这个方法

startElement(String namespaceURI, String localName, String qName, Attributes atts) 当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签。通过atts可以得到所有的属性名和相应的值。

?

ErrorHandler。本设计中使用的是ContentHandler接口,下面是一些ContentHandler接口常用的方法:

? ? ?

endElement(String uri, String localName, String name)这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。

characters(char[] ch, int start, int length) 这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。

因为ContentHandler是一个接口,在使用的时候可能会有些不方便,因此,SAX还为其制定了一个Helper

?

类:DefaultHandler,它实现了这个接口,但是其所有的方法体都为空,在实现的时候,只需要继承这个类,然后重载相应的方法即可

示例代码如下: TrainHomeActivity.java:

public static List readXML(InputStream inputStream){

List train = null; try {

//创建SAXParserFactory对象

SAXParserFactory spf = SAXParserFactory.newInstance(); //返回一个SAXParser解析器

SAXParser parser = spf.newSAXParser();

//根据SAXParser解析器获取XMLREADE事件源 XMLReader xmlReader=parser.getXMLReader(); //实例化一个DefaultHandler对象 TrainHandler handler=new TrainHandler(); //设置处理器

xmlReader.setContentHandler(handler); //解析文档

xmlReader.parse(new InputSource(inputStream)); train=handler.trains;

13

} catch (Exception e) {

正文

}

e.printStackTrace();}

return train;

TrainHandler.java

public class TrainHandler extends DefaultHandler{

private static final String TAG=\private static final boolean D=true; //定义返回的列表

public List trains; //当前读到的数据 private TrainMessagae train; private StringBuffer buffer=null; boolean buffering=false;

//设置一个可以定位文件内容、时间、事件发生位置的定位对象 public void setDocumentLocator(Locator locator) { }

//文档解析开始时间 @Override

public void startDocument() throws SAXException { }

//文档结束事件 @Override

public void endDocument() throws SAXException { }

@Override

public void startElement(String namespaceURI, String localName, String qName,

Attributes atts) throws SAXException {

if(D)Log.d(TAG, \buffer.delete(0, buffer.length());

if (localName.equals(\

trains=new ArrayList(); }else if (localName.equals(\

14

buffer=new StringBuffer();

正文

}

}

train=new TrainMessagae();

@Override

public void endElement(String namespaceURI, String localName, String qName) }

@Override

public void characters(char[] ch, int start, int length) }}

throws SAXException { buffer.append(ch,start,length);

if (localName.equals(\ } if (D) { }

Log.d(TAG, \trains.add(train);

train.setTrainCode(buffer.toString().trim()); train.setStartStation(buffer.toString().trim()); train.setStartTime(buffer.toString().trim()); train.setArriveStation(buffer.toString().trim()); train.setArriveTime(buffer.toString().trim()); train.setUseDate(buffer.toString().trim());

} else if (localName.equals(\} else if (localName.equals(\} else if (localName.equals(\} else if (localName.equals(\}else if (localName.equals(\}else if (localName.equals(\

throws SAXException {

15

正文

第四章 生活小助手软件设计

根据软件的预期目标进行软件系统设计,这对开发工作有很大的帮助,同时也会使后期测试工作容易进行。软件设计主要包括软件结构设计、UI界面设计和数据库设计。根据要实现的具体功能确定软件框架结构,绘制UI界面草图,根据数据需求设计数据库。

4.1 软件结构设计

本软件设计首先确定分为3大模块:天气、列车、食谱。在这3个大模块的基础上再分为小的功能模块,然后在对各个小的功能模块进行详细功能设计、UI界面设计和代码编写。采用这种层层细化的模块化管理方式可以使系统结构更清晰,便于他人理解和阅读。本软件分为以下几个功能模块。打开软件进入欢迎界面,在第一次打开软件时,则创建数据库,添加食谱数据信息,欢迎界面持续2-3秒钟进入到主界面。主界面有连接三大模块的按钮,通过这三个按钮进入三大模块。食谱模块主要分为三大界面,通过这三大界面实现食谱查询、保存、删除和创建的功能。同样,列车模块也分为三大界面,实现站站查询、车次查询和保存的功能。天气预报模块主要有两部分功能:天气查询和城市管理。框架结构如图4-1。

欢迎界面主界面食谱列车天气首页推荐我首页保存提醒未来三天天气城市管理收藏自制食谱站站查询车次查询 图4-1 框架结构图

4.2 系统界面设计

根据系统需求,可知至少创建三个界面:天气预报界面、食谱界面和列车时刻界面,系统和用户交互依赖于直观的图形化界面,UI设计必不可少。以下是个主要UI界面的设计草图。

1. 主界面设置食谱、列车和天气三个按钮,这三个按钮是进入三大功能模块的通道。如图4-2所示

16

正文

图4-2 主界面

2. 食谱功能模块含有三个界面,分别是首页界面、推荐界面、我界面。如图4-3、4-4、4-5所示

图 4-3 食谱首页界面 图4-4 食谱推荐界面 图4-5 食谱我界面

3. 列车功能模块含有首页、保存和提醒界面。如图4-6,4-7,4-8所示

图 4-6 列车首页界面 图4-7 列车保存界面 图4-8 列车提醒界面

4. 天气功能模块主要是天气显示界面,如图4-9所示。

图4-9 天气界面

4.3 系统数据库模型设计

4.3.1

E-R图

17

正文

E-R图即实体-联系图。它是描述现实世界概念结构模型的有效方法。构成E-R图的基本要素是实体型、属性和联系。

? 实体型(Entity):具有相同属性的实体具有相同的特征和性质,用实体名及其属性名集合来抽象和

刻画同类实体;在E-R图中用矩形表示,矩形框内写明实体名。

? 属性(Attribute):实体所具有的某一特性,一个实体可由若干个属性来刻画。在E-R图中用椭圆形

表示,并用无向边将其与相应的实体连接起来

? 联系(Relationship):联系也称关系,信息世界中反映实体内部或实体之间的联系。在E-R图中用菱

形表示,菱形框内写明联系名 1. 食谱数据E-R图:

2. 收藏的食谱数据E-R图3. 列车时刻数据E-R图

4. 城市数据E-R图

食谱名食谱图片食谱食谱制作过程食谱材料 图4-10 食谱实体图

食谱名收藏食谱食谱材料食谱制作过程 图4-11 收藏食谱实体图

始终站车次列车开始到达时间历时

图4-12 列车实体图

18

正文

城市名城市 图4-13 城市实体图

4.3.2 数据库设计

本软件建立了数据库life.db,该数据库共包含四个数据库表:FOOD,CITY,COLLECT,TRAIN。 1. 表4-2为食谱信息表FOOD,该表记录了食谱的信息

表4-1 食谱信息表

列名 foodid foodname foodimg foodmaking foodmaterail 数据类型 允许空 integer text text text text N Y Y Y Y 说明 主键,递增 食谱名 食谱图片 食谱制作过程 食谱材料 2. 表4-3为食谱收藏信息表COLLECT,该表记录了收藏的食谱信息

表4-2 食谱收藏信息表

列名 foodid foodname foodmaking foodmaterail 数据类型 允许空 integer text text text N Y Y Y 说明 主键,递增 收藏的食谱名 收藏的食谱制作过程 收藏的食谱材料 3. 表4-4为天气城市信息表CITY,该表记录了城市的信息

表4-3 城市信息表

列名 cityid cityname 数据类型 允许空 integer text N Y 说明 主键,递增 城市名 4. 表4-5为列车时刻信息表TRAIN,该表记录了列车时刻查询后保存的信息

表4-4 列车信息表

列名 trainid traincode trainstation traintime usetime 数据类型 允许空 integer text text text text N Y Y Y Y 说明 主键,递增 列车车次 列车起始站 列车起始时间 列车历时时间 19

正文

第五章 生活小助手软件实现

本章主要介绍生活小助手软件的具体实现的功能。分别从主界面、食谱功能模块、列车时刻功能模块、天气预报功能模块介绍,介绍了每个功能模块的主要界面,以及每个界面之间的联系,同时也介绍了核心代码。

5.1 主界面

主界面是一个系统的开始,主界面主要功能是实现各个功能模块的切换。程序打开后首先进入欢迎界面,持续1-2秒后进入主界面。在主界面中,通过点击食谱、天气、列车按钮,分别进入到食谱界面,天气预报界面,列车时刻界面。主界面对应的程序名为com.bxy.helperoflife包下的MainActivity。欢迎界面、主界面如下:

图5-1 欢迎界面 图5-2 主界面

核心代码如下:

foodbutton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Intent intent=new Intent();

intent.setClass(MainActivity.this, FoodMainActivity.class); startActivity(intent);

20

正文

}

}); //点击食谱按钮跳转到食谱界面

weatherbutton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) { }

Intent intent1=new Intent();

intent1.setClass(MainActivity.this, WeatherMainActivity.class); startActivity(intent1);

}); //点击天气按钮跳转到天气界面 trainbutton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) { }

Intent intent2=new Intent();

intent2.setClass(MainActivity.this, TrainMainActivity.class); startActivity(intent2);

}); //点击列车按钮跳转到列车界面

5.2 食谱功能模块

在主界面点击食谱按钮后进入食谱界面。食谱功能又分为三个模块:首页、推荐和我。

首页模块提供了食谱的分类查询和通过食谱名直接查询。通过食谱名查询,如果失败则会跳出对话框,选择是否自制食谱,选择是则会跳转到自制食谱界面;如果查询成功则显示该食谱的制作方法,在显示界面上可以选择收藏该食谱。点击食谱的分类图标(荤菜、素菜、海鲜、汤、粥),就可以跳转到分类界面,以列表显示各菜谱。

推荐模块通过列表显示常用且好吃的食谱,可以直接点击某个食谱,显示该食谱的制作方法。在显示界面上可以选择收藏该食谱,收藏后跳转到收藏界面。

我模块包括我的收藏和自制食谱两个功能。通过点击我的收藏按钮跳转到收藏界面,点击收藏列表的条目就可以查询到收藏的菜谱的具体制作方法,长按收藏列表的条目可以实现删除的功能。点击自制食谱跳转到自制食谱界面,在自制食谱界面可以选择保存自制的食谱。

三个主要具体页面如下:

21

正文

5-3 食谱首页 图5-4 推荐 图5-5 我

1. “首页”实现的功能

图5-6 首页功能图

22

正文

2.“推荐”实现的功能图如下:

图5-7 推荐功能图

23

正文

3.“我”实现的功能图如下:

图5-8 我功能图

核心代码:

1. 实现在推荐界面点击某菜谱后,通过Intent传递菜谱名,跳转到显示界面。代码如下:

//Item点击事件

recommaList.setOnItemClickListener(new OnItemClickListener() {

@Override

public void onItemClick(AdapterView parent, View view,

int position, long id) {

=new Intent(FoodRecommandActivity.this,FoodSearchActivity.class);

}

intent.putExtra(\startActivity(intent);

Intent intent

});

2. 实现删除收藏的菜谱,代码如下:

24

正文

//collectlist长按点击监听事件

colleListView.setOnItemLongClickListener(new OnItemLongClickListener() {

@Override

int position, long id) {

public boolean onItemLongClick(AdapterView parent, android.view.View view,

// TODO Auto-generated method stub

collectid=(Integer) collectlist.get(position).get(\ new AlertDialog.Builder(FoodCollect.this)

.setTitle(\温馨提示\ .setMessage(\是否删除\

.setPositiveButton(\确定\

@Override

public void onClick(DialogInterface dialog, int which) { }

// TODO Auto-generated method stub collect=new LifeSqlite(FoodCollect.this); collect.openMyDatabse(); collect.deletecollect(collectid); collectlist=collect.selectcollect(); //初始化适配器collect();

listAdapter=new CollectListAdapter(FoodCollect.this, collectlist); //绑定适配器

colleListView.setAdapter(listAdapter); collect.close();

})

.setNegativeButton(\取消\ .create() .show();

});

}

return true;

数据库的删除语句:

//删除COLLECT列表 public void deletecollect(int id) { }

25

String deletesql=\

database.execSQL(deletesql);

正文

3. 实现首页菜谱图片自动滑动,其适配器代码如下: public class ImageAdapter extends BaseAdapter{

//定义上下文菜单

private Context mcontext; //定义图片源

private int[] mImageId={

R.drawable.adv_1, R.drawable.adv_2, R.drawable.adv_3, R.drawable.adv_4, };

//声明ImageAdapter

public ImageAdapter(Context mcontext){ }

this .mcontext=mcontext;

@Override

public int getCount() { } @Override

public Object getItem(int position) { } @Override

public long getItemId(int position) { } @Override

public View getView(int position, View convertView, ViewGroup parent) {

ImageView imageView=new ImageView(mcontext); //给ImageView设置资源

imageView.setImageResource(mImageId[position% mImageId.length]); //设置布局图片120*120显示

imageView.setLayoutParams(new Gallery.LayoutParams(410,250)); //设置显示比例类型

26

// 获取图片的个数 return mImageId.length;

// 获取图片在库中的位置

return position;

// 获取图片ID

return position;

正文

}

}

imageView.setScaleType(ImageView.ScaleType.FIT_XY); return imageView;

5.3 列车时刻功能模块

在主界面点击列车按钮后进入列车界面。列车功能又分为三大模块:首页、保存和提醒。

首页模块实现了站站查询和车次查询。输入始发站和终点站,点击站站查询,通过HTTP POST请求访问Web Service的获取信息,对于获得数据流通过SAX解析获得有用的信息,具体实现方法在3.7节和3.8节已经介绍。将获得有用信息在列表中显示,长按某车次信息可以实现车次信息存储。输入车次信息,点击车次查询,通过SOAP协议访问web service的getWeatherbyCityName方法获得有用信息,具体实现方法参照3.6节。

保存模块的功能是显示存储的车次信息,便于在无网络的情况下查询信息。长按列表条目会跳出“是否删除”对话框,点击“是”可以实现删除功能。

提醒模块主要是告诉用户订票电话、网站和客服电话信息。 三个主要界面如下:

1.“首页”实现的功能图如下:

图5-9 首页 图5-10保存 图5-11 提醒

27

正文

图5-12 首页功能图

2. “保存”实现的功能图如下:

图5-13 保存功能图

28

正文

核心代码:

1. 通过TabHost控件实现不同页面切换,代码如下: @Override

protected void onCreate(Bundle savedInstanceState) {

inflater=LayoutInflater.from(this); true);

//我界面

}

//radio监听事件

LocalActivityManager localAcManager=new LocalActivityManager(TrainMainActivity.this,

localAcManager.dispatchCreate(savedInstanceState); tabHost=(TabHost)findViewById(android.R.id.tabhost);

//如果通过findViewById得到TabHost 一定要调用 TabHost.setup();

tabHost.setup(localAcManager);

tabHost.addTab(tabHost.newTabSpec(\

setContent(new

Intent(TrainMainActivity.this,TrainHomeActivity.class)));//首页界面

tabHost.addTab(tabHost.newTabSpec(\

setContent(new

Intent(TrainMainActivity.this,TrainCollectActivity.class)));//推荐界面

tabHost.addTab(tabHost.newTabSpec(\

setContent(new Intent(TrainMainActivity.this,TrainSettingActivity.class)));

radioGroup=(RadioGroup)findViewById(R.id.train_tab_group);

radioGroup.setOnCheckedChangeListener( checkedChangeListener );

private OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(RadioGroup group, int checkedId) {

// TODO Auto-generated method stub switch (checkedId) { case R.id.train_home:

break;

tabHost.setCurrentTabByTag(\如果选中推荐 break;

case R.id.train_collect:

tabHost.setCurrentTabByTag(\//如果选中首页

case R.id.train_setting:

29

正文

};

}

}

tabHost.setCurrentTabByTag(\ //如果选中我 break;

2.通过站站查询获得列车信息,代码如下:

if (v.getId()==R.id.stationbutton) {

public static List readXML(InputStream inputStream){

}

startstation=Startstation.getText().toString(); endstation=Endstation.getText().toString(); TrainHttppost();

Log.e(\if(inputStream==null){

Toast.makeText(TrainHomeActivity.this, \查询失败\List trainMessagaes=new ArrayList(); trainMessagaes= readXML(inputStream); Bundle bundle=new Bundle(); bundle.putParcelableArrayList(\

(ArrayList

extends

Parcelable>)

}else {

trainMessagaes);

Intent intent =new Intent(TrainHomeActivity.this, TrainSearchActivity.class); intent.putExtras(bundle); startActivity(intent);

List train = null; try {

//创建SAXParserFactory对象

SAXParserFactory spf = SAXParserFactory.newInstance(); //返回一个SAXParser解析器

SAXParser parser = spf.newSAXParser();

//根据SAXParser解析器获取XMLREADE事件源 XMLReader xmlReader=parser.getXMLReader(); //实例化一个DefaultHandler对象 TrainHandler handler=new TrainHandler(); //设置处理器

xmlReader.setContentHandler(handler);

30

正文

}

}

//解析文档

xmlReader.parse(new InputSource(inputStream)); train=handler.trains; // TODO: handle exception e.printStackTrace();

} catch (Exception e) {

return train;

protected void TrainHttppost() {

// TODO Auto-generated method stub /** 获取天气的WebServiceURL */

String url = \

+ \

//请求参数

//String requestStr=\+ startstation + \endstation Log.e(\正在查询\

try {

//使用HTTPPOST=对象提交数据 HttpPost httpRequest=new HttpPost(url); //超时设置

HttpParams params=new BasicHttpParams(); //从连接池获取连接的超时时间

ConnManagerParams.setTimeout(params, 1000); //通过网路与服务器建立连接的超时时间

HttpConnectionParams.setConnectionTimeout(params, 3000); //读响应数据的超时间

HttpConnectionParams.setSoTimeout(params, 5000); //设计请求参数

httpRequest.setParams(params); //传递请求参数

List paramsList=

new ArrayList();

paramsList.add(new BasicNameValuePair(\Log.e(\始发站\

paramsList.add(new BasicNameValuePair(\

31

+\

正文

Log.e(\目的\

paramsList.add(new BasicNameValuePair(\

UrlEncodedFormEntity murlEncodedFormEntity=

new UrlEncodedFormEntity(paramsList,HTTP.UTF_8);

httpRequest.setEntity(murlEncodedFormEntity);

HttpResponse httpResponse=new DefaultHttpClient().execute(httpRequest); Log.e(\添加数据\ //使用GetEntity方法获得返回结果

final int ret=httpResponse.getStatusLine().getStatusCode(); if (ret==HttpStatus.SC_OK) { }

Log.e(\

inputStream=httpResponse.getEntity().getContent(); Log.e(\数据流\数据流\

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}catch (ClientProtocolException e) { e.printStackTrace(); e.printStackTrace(); }}

} catch (IOException e) {

XML解析处理器详细代码参照3.8节。

5.4 天气预报功能模块

在主界面点击天气按钮后进入天气界面,就可以呈现出默认城市(北京)的天气信息。点击城市图标就可以进入城市管理界面,在城市管理界面点击添加按钮就可以进入添加城市界面。选择省份和城市实现添加功能,点击“添加”按钮时就使该城市加入SQLite数据库中,并且显示提示是否成功。点击添加的城市跳转到主界面,就可以查询到该城市的天气信息。同时。长按列表条目可以实现删除功能。主界面的刷新按钮,点击可以获得最新的天气情况。

32

正文

天气预报主界面如下:

图5-14 主界面

33

正文

各个界面之间的联系图如下:

图5-15 天气预报功能图

34

正文

核心代码:

天气预报信息查询功能代码参照3.6节 1. 实现城市添加功能,代码如下: //确定按钮点击事件 //省份

private void initprovince() {

Province=(Spinner)findViewById(R.id.province); //将ARRAY.XML读取为数组

//设置适配器

ProvinceAdapter=ArrayAdapter.createFromResource(this,

//设置样式

CitySure.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) { }});

city=new LifeSqlite(WeatherCitySetting.this); city.openMyDatabse(); city.insertCITY(CityName); city.close();

Intent intent =new Intent(WeatherCitySetting.this, WeatherCityActivity.class); startActivity(intent);

ArrayAdapter

R.array.province,android.R.layout.simple_spinner_item);

ProvinceAdapter.setDropDownViewResource Province.setAdapter(ProvinceAdapter);

Province.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){ });

Province.setVisibility(View.VISIBLE);

35

(android.R.layout.simple_spinner_dropdown_item);

@Override

public void onItemSelected(AdapterView parent, View view, } @Override

public void onNothingSelected(AdapterView parent) { }

int position, long id) { initcity(position);

parent.setVisibility(View.VISIBLE);

正文

}

//城市

private void initcity(int code) {

// TODO Auto-generated method stub City=(Spinner)findViewById(R.id.city); int[] cityarray={R.array.zhejiang, R.array.hubei,

R.array.hunan, R.array.beijing, R.array.shanghai, R.array.tianjing, R.array.chongqing, R.array.heilongjiang, R.array.jilin, R.array.liaoning, R.array.neimenggu, R.array.hebei, R.array.shanxi, R.array.shangxi, R.array.shandong, R.array.xinjiang, R.array.xizang, R.array.qinghai, R.array.gansu, R.array.ningxia, R.array.henan, R.array.jiangsu, R.array.anhui, R.array.fujian, R.array.jiangxi, R.array.guizhou, R.array.sichuan, R.array.guangdong, R.array.yunnan, R.array.guangxi, R.array.hainan, R.array.xianggang, R.array.aomen, R.array.taiwan,

};

//设置适配器

ArrayAdapter CityAdapter =

ArrayAdapter.createFromResource(this, cityarray[code], }

36

}

android.R.layout.simple_spinner_item);

//设置样式

CityAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); City.setAdapter(CityAdapter);

City.setOnItemSelectedListener(new OnItemSelectedListener() { });

City.setVisibility(View.VISIBLE);

@Override

public void onItemSelected(AdapterView parent, View view, } @Override

public void onNothingSelected(AdapterView arg0) { }

int position, long id) {

// TODO Auto-generated method stub

CityName = (String) City.getItemAtPosition(position); parent.setVisibility(View.VISIBLE);

本文来源:https://www.bwwdw.com/article/0ylg.html

Top