Y angtze University College of Arts and Science
学生课程设计报告
系部:机电与信息工程系
专业:计算机科学与技术
班级:计科5131
姓名:来超
学号: 201241136
课程名称:移动平台数据库综合开发
指导教师:王腾
实习时间:2016年6月20日至2016年6月27日
学生课程设计报告 0
1.开发背景 (3)
2.软件需求分析 (4)
2.1软件开发的工具和环境 (4)
2.2安装JDK和SDK (4)
3、原理与技术要点分析 (5)
3.1 登录功能概要 (5)
3.2聊天功能概要 (5)
3.3技术要点分析 (6)
3.3.1概念结构设计 (6)
3.3.2逻辑结构设计 (6)
4.详细设计 (8)
4.1 用户聊天模块 (8)
4.1.1 ChatActivity 类 (8)
4.1.2 SplashActivity 类 (10)
4.1.3 activity_login.xml (10)
4.1.4 activity_chat.xml (11)
4.2 客户端模块 (12)
4.2.1 ContactActivity 类 (12)
4.2.2 LoginActivity 类 (13)
4.2.3 activity_contact.xml (15)
4.2.4 item_contact.xml (15)
4.2.5 activity_splash.xml (16)
5、测试分析 (17)
5.1客户端具体功能实现 (17)
心得体会 (19)
android即时通讯软件
摘要
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,例如,国外的ICQ、国内腾讯公司开发的OICQ。基于Java网络编程的强大功能,本次课程设计使用Java编写一个运行在android2.2版本以上的即时通讯软件。一般来说,聊天工具大多数由客户端程序和服务器程序外加服务器端用于存放客户数据的数据库组成。
Java提供的多线程功能用多线程可完成一点对多点的聊天,数据库管理系统用SQLlite来访问数据库的。本系统建立在JAVA平台上,系统的设计使用了面向对象技术和面向对象的设计原则。系统采用C/S结构,客户端与客户端以及客户端与服务器端之间传送消息。使用JAVA语言编写,开发工具采用AS。
在智能手机中,Android平台约占75%市场份额。安卓系统的广泛应用,使
得Android手机应用程序的数量快速增长,即时通讯APP的应用范围也更加广泛。关键字:多线程;客户机/服务器;JAVA;AS ;Android手机应用
1.开发背景
Android的英文翻译是指“机器人”,而Android这个词语作为操作系统的名称出现,是谷歌在2007年发布了应用在手机平台上的操作系统,自此Android作为手机操作系统出现在人们的视野中。同时由于Android的操作系统的开源性和可开发性使得以Android操作系统的应用软件日益增多。Android操作系统被越来越多的人接受和使用。
目前的Android聊天软件基本分为2种架构形式:(1)C/S架构:采取客户端/服务器对等传输的形式,用户方主要使用客户端软件,使用前用户通过网上下载客户端软件,再安装到手机上进行使用,市场上流行的C/S架构的聊天软件有以下几种:QQ、微信、微博、YY、MSN等;(2)B/S架构:浏览器/服务端对等传输的形式,这种形式下的即时通信工具,一般都是依赖于互联网,作为用户无需下载客户端,用户一般在浏览往网上网页时浏览器会提供一个类似于客户端的界面使用户可以发送消息,此架构一般应用在数据流比较大的电商网站,如WebQQ等。
2.软件需求分析
2.1软件开发的工具和环境
1.开发环境:AS
2.开发语言:JAVA
3.模拟机平台:AVD
4.手机运行平台:Android2.1以及上版本开发软件
5.所需插件:JDK
2.2安装JDK和SDK
先从网站上找到JDK1.6(JREaloneisnotsufficient)版本并下载,下载完毕后将它安装在PC机上并在PC机上设置好有关的环境变量,将JAVA_HOME,path等几个设置为适用于Java开发的环境变量,最后将其导入你的JDK文件路径
SDK安装:直接从相关网站下载好SDK压缩包,然后打开Eclipse软件,在其中找到对应路径将其导入就可以。
3、原理与技术要点分析
3.1 登录功能概要
?点击button按钮
?服务器验证登录账号
?跳转进入好友列表界面
登录流程图:
进入
输入账号及密码
失判断账号密码
败是否正确
服务器验证
登录成功
1.1登录功能流程图
3.2聊天功能概要
?用户点击联系人列表中的一个好友时,进入聊天界面?在输入框输入信息,点击发送按钮,发送信息
?好友回复消息是在该聊天页面显示
?当有好友发消息过来时,系统会通过Toast提示
用户聊天模块总体流程图:
1.2用户聊天模块总体流程图
3.3技术要点分析
3.3.1概念结构设计
3.3.2逻辑结构设计
1)用户信息(用户账号,用户密码,昵称,头像)
public class QQMessage extends Protocal{
public String type = QQMessageType.MSG_TYPE_CHA T_P2P; // 数据类型
public long from = 0; // 发送者account
public String fromNick = "";// QQ名
public int fromAvatar = 1; // 头像
public long to = 0; // 接收者account
public String content = ""; // 消息内容(hi)
public String sendTime = MyTime.getTime(); // 发送时间
2)}会话信息(好友账号,好友头像,发送/接收消息时间,消息内容)public class QQMessageType {
public static final String MSG_TYPE_REGISTER = "register"; // 注册
public static final String MSG_TYPE_LOGIN = "login";// 登录
public static final String MSG_TYPE_LOGINOUT = "loginout";// 登出
public static final String MSG_TYPE_CHA T_P2P = "chatp2p";// 聊天
public static final String MSG_TYPE_CHA T_ROOM = "chatroom";// 群聊
public static final String MSG_TYPE_OFFLINE = "offline";// 下线
public static final String MSG_TYPE_SUCCESS = "success";// 成功
public static final String MSG_TYPE_BUDDYLIST = "buddylist";// 好友列表
public static final String MSG_TYPE_FAILURE = "failure";// 失败
}
4.详细设计
4.1 用户聊天模块
4.1.1 ChatActivity 类
public class ChatActivity extends Activity {
ListView listView;
TextView title,send_nick,recv_nick;
EditText input;
String six_space=" ";
String two_space=" ";
private String toNick;
private Long account;
ImApp app;
private ChatMessageAdapter adapter;
List
//内容观察者:观察uri中是否出现数据库被修改的信号
private ContentObserver observer=new ContentObserver( new Handler()) { //观察到发生变化后,所做的动作
//android2.2
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
requery();
}
//android4.0以上
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
requery();
}
};
private void requery() {
//System.out.println("数据发生变化,取出数据刷新聊天界面");
list.clear();
querySetofChatWithOne(account+"",list);
if(adapter!=null){
adapter.notifyDataSetChanged();
}
if(list.size()>0){
listView.setSelection(list.size()-1);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(https://www.doczj.com/doc/f914590878.html,yout.activity_chat);
listView= (ListView) findViewById(R.id.listview_chat);
title= (TextView) findViewById(https://www.doczj.com/doc/f914590878.html,_title);
input= (EditText) findViewById(R.id.edt_input);
send_nick=(TextView)findViewById(https://www.doczj.com/doc/f914590878.html,_send_nick);
recv_nick=(TextView)findViewById(https://www.doczj.com/doc/f914590878.html,_recv_nick);
//注册内容观察者
Uri uri=Uri.parse("content://"+ QQContactDBDao.class.getSimpleName());
// getContentResolver().registerContentObserver(地址:信号,子路径是否有效,指定一个观察者);
this.getContentResolver().registerContentObserver(uri,true,observer);
app= (ImApp) getApplication();
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
account=bundle.getLong("account");
toNick=bundle.getString("nick");
title.setText("与[" +toNick +"]聊天中");
querySetofChatWithOne(account+"",list);
adapter=new ChatMessageAdapter(this,list);
listView.setAdapter(adapter);
if(list.size()-1>0){
listView.setSelection(list.size()-1);
}
}
//接收消息
//1.messageType==p2p 2.app.account==msg.to 3.msg,account->toast
public void clickSend(View v){
String messageBody=input.getText().toString().trim();
if("".equals(messageBody)){
Toast.makeText(getBaseContext(),"发送消息不为空",Toast.LENGTH_SHORT).show();
return;
}
input.setText("");
final QQMessage msg=new QQMessage();
msg.type= QQMessageType.MSG_TYPE_CHA T_P2P;
msg.content=messageBody;
msg.from=app.getAccount();
msg.to=account;
msg.fromNick="人族";
//发送干两件事情
//1:把消息显示到聊天记录区
list.add(msg);
//刷新list
if(adapter!=null){
adapter.notifyDataSetChanged();
}
//从最后一条开始显示
if(list.size()>0)
{
listView.setSelection(list.size()-1);
}
//2:发送给聊天对象
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
try {
app.getCoreService().sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// 把与当前好友聊天记录查询出来,
// 并显示到与当前好友的聊天界面
private void querySetofChatWithOne(String session_id,List
List
dbmsgList=app.getQqContactDBDao().queryRaw("where SESSION_ID = ? order by SENDTIME
ASC",session_id);
for(com.example.meiyu.qq_im.dao.QQContactDB item:dbmsgList){
QQMessage msg = new QQMessage();
msg.type = QQMessageType.MSG_TYPE_CHA T_P2P;
msg.content = item.getContent();
msg.from = item.getFrom();
msg.to = item.getTo();
msg.fromNick = item.getFromNick();
msgList.add(msg);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(observer);
}
}
4.1.2 SplashActivity 类
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(https://www.doczj.com/doc/f914590878.html,yout.activity_splash);
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000); //至少3秒,下限
startActivity(new Intent(getBaseContext(),LoginActivity.class));
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
4.1.3 activity_login.xml
android:layout_width="match_parent" android:layout_height="match_parent"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/ic_launcher_qq"/> android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="QQ账号" android:textSize="25sp"/> android:layout_width="200dp" android:layout_height="wrap_content" android:singleLine="true" android:id="@+id/account" android:text="159"/> android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码" android:textSize="25sp"/> android:layout_width="200dp" android:layout_height="wrap_content" android:singleLine="true" android:id="@+id/psw" android:inputType="textPassword" android:text="test"/>
4.1.4 activity_chat.xml
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="1"> android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="#FFFFFF" android:background="#0099ff" android:gravity="center"/> android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/listview_chat" android:cacheColorHint="@android:color/transparent" android:listSelector="@android:color/transparent" android:divider="@android:color/transparent" android:dividerHeight="1dp"> android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"> android:id="@+id/edt_input" android:layout_weight="6" android:layout_width="0dp" android:layout_height="wrap_content" />
4.2 客户端模块
4.2.1 ContactActivity 类
public class ContactActivity extends Activity {
ListView listView;
ContactAdapter adapter;
ImApp app;
//好友列表
List
//每一个activity必备的监听器
IOnMessageReceiveListener listener=new IOnMessageReceiveListener() {
@Override
public void onReceive(final QQMessage msg) {
ThreadUtils.runUnThread(new Runnable() {
@Override
public void run() {
if(QQMessageType.MSG_TYPE_BUDDYLIST.equals(msg.type)){
String json=msg.content;
Gson gson=new Gson();
//反序列化
QQContactList tempList=gson.fromJson(json,QQContactList.class);
//刷新好友列表
//首先设置列表值
list.clear();
list.addAll(tempList.buddyList);
//其次再刷新列表
if(adapter!=null){
adapter.notifyDataSetChanged();
}
}
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(https://www.doczj.com/doc/f914590878.html,yout.activity_contact);
listView= (ListView) findViewById(R.id.listview_contact);
app= (ImApp) getApplication();
app.getCommunicaCore().addOnMessageReceiveListener(listener);
//处理好友列表
//先取出(app)
String json=app.getBuddyListJson();
System.out.println(json);
//再处理(从json反序列化成对象)
Gson gson=new Gson();
QQContactList tempList=gson.fromJson(json,QQContactList.class);
//把上面完成的对象加入到list里面去
list.addAll(tempList.buddyList);
//绑定适配器
adapter =new ContactAdapter(this,list);
listView.setAdapter(adapter);
// 添加item的click监听器
listView.setOnItemClickListener(new ListView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) { // 获取数据
QQContact contact = list.get(position);
Intent intent = new Intent(getBaseContext(),ChatActivity.class);
intent.putExtra("account",contact.account);
intent.putExtra("nick",contact.nick);
startActivity(intent);
}
});
}
protected void onDestroy(){
super.onDestroy();
app.getCommunicaCore().removeOnMessageReceiveListener(listener);
}
}
4.2.2 LoginActivity 类
public class LoginActivity extends Activity {
EditText account,psw;
String username,password;
QQCommunicationCore communicaCore;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(https://www.doczj.com/doc/f914590878.html,yout.activity_login);
account= (EditText) findViewById(R.id.account);
psw= (EditText) findViewById(R.id.psw);
//网络链接
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
try {
communicaCore=new QQCommunicationCore("192.168.1.126",20001);
communicaCore.addOnMessageReceiveListener(listener);
communicaCore.connection();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//被回调本activity处理消息的核心
IOnMessageReceiveListener listener=new IOnMessageReceiveListener() {
@Override
public void onReceive(final QQMessage msg) {
ThreadUtils.runUnThread(new Runnable() {
@Override
public void run() {
System.out.println(msg.toXML());
if(QQMessageType.MSG_TYPE_BUDDYLIST.equals(msg.type)){
ImApp app= (ImApp) getApplication();
//保存账号
app.setAccount(Long.parseLong( account.getText().toString().trim()));
//保存连接(被保存过的连接叫长连接)
app.setCommunicaCore(communicaCore);
//保存好友列表(好友列表在content)
app.setBuddyListJson(msg.content);
Toast.makeText(getBaseContext(),"登录成功", Toast.LENGTH_LONG).show();
//启动联系人界面
startActivity(new Intent(getBaseContext(),ContactActivity.class));
//启动核心服务(启动式)
startService(new Intent(getBaseContext(),CoreService.class));
finish();
}else {
Toast.makeText(getBaseContext(),"登陆失败",Toast.LENGTH_LONG).show();
}
}
});
}
};
//只发送消息,不处理消息
public void login(View v){
username=account.getText().toString().trim();
password=psw.getText().toString();
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
try {
QQMessage msg=new QQMessage();
msg.type= QQMessageType.MSG_TYPE_LOGIN;
msg.content=username+"#"+password;
communicaCore.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
communicaCore.removeOnMessageReceiveListener(listener);
}
}
4.2.3 activity_contact.xml
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> android:textSize="30sp" android:text="联系人" android:layout_width="match_parent" android:background="#0099ff" android:textColor="#ffffff" android:gravity="center" android:layout_height="50dp" /> android:layout_width="match_parent" android:layout_height="0dp" android:cacheColorHint="@android:color/transparent" android:divider="#0099ff" android:dividerHeight="1dp" android:id="@+id/listview_contact" android:layout_weight="1">
4.2.4 item_contact.xml
android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> android:id="@+id/head" android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center_vertical" android:layout_marginLeft="20dp" android:src="@drawable/ic_launcher"/> android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> android:id="@+id/nick" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="来超" android:textSize="20sp" android:textColor="#ff0000" android:gravity="left|center_vertical" /> android:id="@+id/desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="[在线]" android:textSize="15sp" android:textColor="#000000" android:gravity="left|center_vertical" />
4.2.5 activity_splash.xml
android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/splash_bg"> android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/conversation_bg_logo"/>
5、测试分析
5.1客户端具体功能实现
?登录功能:建立与服务器的连接并登录,能显示登录成功信息。
?界面显示:将好友显示在联系人列表中,并可以通过点击进入会话界面,进行与好友的聊天
?聊天功能:当好友发送消息时会显示在会话界面。用户也同时可以在输入框中输入相应信息点击发送与好友聊天。
?信息提示:Toast提示到来信息的好友账号。
用户在客户端点击应用程序图标后启动应用如下图:
图5-1 客户端启动界面
进入联系人界面后,点击好友账号,进入聊天功能。当好友发送消息时,会显示在会话界面。用户也同时可以在输入框中输入相应信息点击发送与好友聊天。聊天界面如下图:
图5-2 与好友聊天界面
心得体会
本课程设计紧紧围绕了基于Android平台的移动聊天程序进行研究说明,针对基于Android平台的应用程序开发已经及时通讯进行了深入的探讨。移动聊天程序是当今社会实现人机交互的重要技术支撑,通过分析相关移动聊天程序的各种功能需求,并用面向对象语言Java语言实现并封装好这些功能。然后又通过需求分析设计了移动聊天程序所需的各个功能模块,并在需求分析的基础上最终通过编程封装实现了此聊天程序。此聊天程序流程主要分为:登录界面、好友界面、回话界面模块。
Android技术比较新颖,入门感觉稍微有些难,不过本系统能够让用户实现一对一的聊天、实现文字的收发,网络技术支持能功能,但是由于本人的经验不足和时间有限,以及对一些相关的技术、思想、理论掌握的还不够透彻,因此本系统中还存在许多不足、许多待完善的地方:例如界面不够美观等等。这些不足之处,会在今后的学习中不断的完善和维护,希望能够达到更好的效果。
经过课程这个设计的磨练,对移动通讯行业有了更深的了解,也有了更多的知识来充实自己的大脑。