目 录
1 概论 1
1.1 研究现状 1
1.2 系统开发意义 1
1.3 系统开发背景 2
2 开发环境以及相关技术 5
2.1 Eclipse 5
2.2 Adroid 5
2.2.1 基本概念 5
2.2.2 简介 6
2.2.3 系统架构 6
2.2.4 四大组件 7
2.3 Java语言 7
2.4 SQLite 7
2.4.1 简介 7
2.4.2 架构 7
2.4.3 特点 8
2.5 FastJson 8
2.5.1 简介 8
2.5.2 FastJson解析JSON步骤 9
3 需求分析 13
3.1 可行性分析 13
3.1.1 技术可行性 13
3.1.2 经济可行性 13
3.1.3 社会可行性 13
3.2 功能需求分析 14
3.3 特性需求分析 14
4 概要设计 16
4.1 系统总体功能结构 16
4.2 系统总体架构 17
5 详细设计与实现 18
5.1 系统总体功能设计 18
5.1.1 服务器端说明 18
5.1.2 客户端说明 18
5.2 系统的实现 19
5.2.1 活动模块 19
5.2.2 游记模块 20
5.2.3 导航模块 23
5.2.4 我的模块 25
5.3 实现的技术点 26
5.3.1 界面布局的实现 26
5.3.2 代码中所用到的技术 31
6 软件测试 37
6.1 软件测试的重要性 37
6.2 测试实例的研究与选择 37
6.3 系统运行情况 38
6.4 系统评价 41
7 总结 43
参考文献 44
致 谢 45
外文原文 46
中文翻译 57
3 需求分析
系统分析的真正含义就是对系统,从技术可行性、经济可行性以及操作可行性来进行分析。
3.1 可行性分析
在这里就依次从技术的、经济的、社会的可行性三个方面来对本旅游导航APP进行深入的分析和研究。
3.1.1 技术可行性
该软件是基于Java语言、并以SQLite为后台数据库。硬件、软件的性能要求、环境条件等各项条件均良好。利用现有技术条件预计完全可以达到该软件的功能目标。时间安排相对比较充裕,预计完成没有问题。
由以上分析可以知道:本设计是具有技术可行性的。
3.1.2 经济可行性
本设计采用的开发软件都是开源的,不需用额外花费费用,这样削减很多的精力和资源,起到减少成本的作用,因此在经济上具有可行性。
由以上分析可以知道:本设计具有经济的可行性。
3.1.3 社会可行性
本设计的社会可行性主要需要从法律因素、用户使用可行性这两方面进行研究。
1.法律因素
本设计是根据80、90的青年人旅行的实际情况开发研制的,是通过大量的调研得出的,系统的软件设计是在独立的环境下完成的,无可供抄袭的软件产品。
2.用户使用可行性
本设计对用户的要求,除了需要具备移动设备以及第三方账号外,并不需要特别的技术能力。使用系统的管理员,需要具备对java语言及Android开发环境的使用能力,在投入使用前,无需对操作系统的人员进行培训。这样减少了投入成本简化了操作环节。
由以上分析可以知道:本设计完全具有社会的可行性。
3.2 功能需求分析
Android系统目前在市场上占有很大的份额,从2010前Android就已经呈现出很强劲的发展势头,而且到目前为止,还处于不断的上升阶段。无论你走在大街上、校园里、地铁上亦或是公交上,总能看到人们拿着智能手机专心致志的做自己的事情,而且不难发现,绝大多数都是Android手机,人们低头聚精会神的玩游戏、看小说、刷刷微博等等。手机中安装的各种App可以丰富并且满足人们对业余生活的要求以及期望,其中的游戏娱乐、在线购物也是极大的刺激着整个社会的消费水平。随着时代的不断发展,兼娱乐与通信功能的手机越发的流行,成为人们的一种新的追求。因而,这就更进一步的促进激发着手机软件App研发人员的热情与积极性。
综上,本设计是为了实现一个方便用户出行,并可以推荐旅游景点的目标。用户可以通过浏览驴友们在野外徒步旅行是的场景,全方位的了解自己想要去的景点。通过展示的信息,用户可以方便的了解一个景点的人文特色,最近是否有活动,是否拥有优惠价,以及根据时间分类,可以准确的推荐最近一段时间的旅游团动向,并附有旅游团的联系方式,方便用户直接用电话进行咨询,从而来确定是否参加本次活动;并且在此基础上,根据数据源的数据结构以及字段分析,把旅游的信息按地点进行一些分类,每个城市的旅游信息就可以直观的展现在用户的面前,并且将旅游的类型进行了汇总,冒险类、休闲类、娱乐类等丰富的信息以供用户选择,此外也考虑到了用户的经济承受能力,还实现了根据本次旅游的价格信息进行进一步的整合,可以让用户更加直观并且很快的找见适合自己经济承受能力的旅游景点。当然,光有这些信息是远远不够的,用户之间最好能够进行互动,互相交流旅游心得,欣赏了解对方去过的地方,还可以进行点赞,要想实现这个功能,当然是离不开第三方登陆的,微博、QQ可以任意选择,因而就要求用户必须要拥有一个属于自己的第三方的账号,在登陆成功后可以对个人信息进行查看。
3.3 特性需求分析
一个较好的软件应该具有以下特性:
1、易操作和功能简单明确。一个好的旅游导航系统应该功能明确,用户可以很快的熟悉使用流程,而不是看到界面不知道应该如何的操作,即操作要简单,界面友好易懂。
2、软件功能流畅。软件运行时候不会发生崩溃和卡顿等问题,整个界面操作起来快捷流畅。
3、软件易维护性。系统各个设计模块明确,核心代码要有必要的注释,方便软件的后期维护。
/*
* Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lidroid.xutils;
import android.app.Activity;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.view.EventListenerManager;
import com.lidroid.xutils.view.ResLoader;
import com.lidroid.xutils.view.ViewFinder;
import com.lidroid.xutils.view.ViewInjectInfo;
import com.lidroid.xutils.view.annotation.ContentView;
import com.lidroid.xutils.view.annotation.PreferenceInject;
import com.lidroid.xutils.view.annotation.ResInject;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.lidroid.xutils.view.annotation.event.EventBase;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ViewUtils {
private ViewUtils() {
}
public static void inject(View view) {
injectObject(view, new ViewFinder(view));
}
public static void inject(Activity activity) {
injectObject(activity, new ViewFinder(activity));
}
public static void inject(PreferenceActivity preferenceActivity) {
injectObject(preferenceActivity, new ViewFinder(preferenceActivity));
}
public static void inject(Object handler, View view) {
injectObject(handler, new ViewFinder(view));
}
public static void inject(Object handler, Activity activity) {
injectObject(handler, new ViewFinder(activity));
}
public static void inject(Object handler, PreferenceGroup preferenceGroup) {
injectObject(handler, new ViewFinder(preferenceGroup));
}
public static void inject(Object handler, PreferenceActivity preferenceActivity) {
injectObject(handler, new ViewFinder(preferenceActivity));
}
private static void injectObject(Object handler, ViewFinder finder) {
Class<?> handlerType = handler.getClass();
// inject ContentView
ContentView contentView = handlerType.getAnnotation(ContentView.class);
if (contentView != null) {
try {
Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
setContentViewMethod.invoke(handler, contentView.value());
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
// inject view
Field[] fields = handlerType.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
try {
View view = finder.findViewById(viewInject.value(), viewInject.parentId());
if (view != null) {
field.setAccessible(true);
field.set(handler, view);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
} else {
ResInject resInject = field.getAnnotation(ResInject.class);
if (resInject != null) {
try {
Object res = ResLoader.loadRes(
resInject.type(), finder.getContext(), resInject.id());
if (res != null) {
field.setAccessible(true);
field.set(handler, res);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
} else {
PreferenceInject preferenceInject = field.getAnnotation(PreferenceInject.class);
if (preferenceInject != null) {
try {
Preference preference = finder.findPreference(preferenceInject.value());
if (preference != null) {
field.setAccessible(true);
field.set(handler, preference);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
}
}
}
}
// inject event
Method[] methods = handlerType.getDeclaredMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
Annotation[] annotations = method.getDeclaredAnnotations();
if (annotations != null && annotations.length > 0) {
for (Annotation annotation : annotations) {
Class<?> annType = annotation.annotationType();
if (annType.getAnnotation(EventBase.class) != null) {
method.setAccessible(true);
try {
// ProGuard:-keep class * extends java.lang.annotation.Annotation { *; }
Method valueMethod = annType.getDeclaredMethod("value");
Method parentIdMethod = null;
try {
parentIdMethod = annType.getDeclaredMethod("parentId");
} catch (Throwable e) {
}
Object values = valueMethod.invoke(annotation);
Object parentIds = parentIdMethod == null ? null : parentIdMethod.invoke(annotation);
int parentIdsLen = parentIds == null ? 0 : Array.getLength(parentIds);
int len = Array.getLength(values);
for (int i = 0; i < len; i++) {
ViewInjectInfo info = new ViewInjectInfo();
info.value = Array.get(values, i);
info.parentId = parentIdsLen > i ? (Integer) Array.get(parentIds, i) : 0;
EventListenerManager.addEventMethod(finder, info, annotation, handler, method);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
}
}
}
}
}
}