Android之基于XMPP协议即时通信软件(二)

2013博客之星投票请移步:http://vote.blog.csdn.net/blogstaritem/blogstar2013/weidi1989java

昨天给你们粗略的介绍了一下我那个简单的项目:Android之基于XMPP协议即时通信软件(一)数据库

从今天开始,就详细展开的介绍设计思路,一是给本身作个总结,二是但愿能给各位朋友一点点帮助吧!设计模式

也许和不少刚刚开始入行程序猿的朋友同样,我最初也是每开始一个新项目,只是稍微思考一下便开始写代码。一个星期后,尽管实现了部分功能,却发现本身有点乱了,由于又忽然生出不少新的想法,因而又顺着思路写下去,再持续一段时间,就会发现这个项目作不下去了。代码重复不少,并且bug也是层出不穷。所以不得不推翻从新开始,浪费了不少时间。因此说,开始前的准备工做是至关重要的。服务器

通常说来完成一个项目能够分红三步:框架

首先:画几天时间好好理清思路,能够在草稿纸上写写画画,列出必须实现的功能已经界面特效等等,作到成竹在胸。ide

其次:开始搭建框架,定义好全部功能的接口,而且注释好作什么用,这是方便团队合做的项目,我的项目也能够养成写注释的好习惯。函数

最后:分开实现各部分功能,而且分开调试,能够单独独立成一个应用或者单元测试模块。好比说本应用的全部界面效果都是独立成一个应用测试无误后才最后合入的。工具

我这个项目呢,一开始是完成了全部的界面模块工做,由于是直接从以前的项目移植过来的,稍微修改了一下,因此这部分省掉了不少时间。单元测试

重心就直接放在了功能实现这方面了。功能模块部分就是下面两个包:com.way.service和 com.way.smack测试

首先是定义通用接口,主要就是将第三方包asmack.jar中须要用到的东西拿出来,这个包是很是庞大的,可是咱们这个小应用并非须要实现全部的功能,因此,抽取本身须要的那部分就能够了,定义成接口,方便之后扩展须要的功能,代码以下:

[java] view plaincopyprint?/**

  • 首先定义一些接口,须要实现一些什么样的功能,
  • @author way

/
public interface Smack {
/
* * 登录 *
* @param account * 帐号 * @param password * 密码 * @return 是否登录成功 * @throws XXException * 抛出自定义异常,以便统一处理登录失败的问题 */
public boolean login(String account, String password) throws XXException;

/** 
 * 注销登录 
 *  
 * @return 是否成功 
 */  
public boolean logout();  

/** 
 * 是否已经链接上服务器 
 *  
 * @return 
 */  
public boolean isAuthenticated();  

/** 
 * 添加好友 
 *  
 * @param user 
 *            好友id 
 * @param alias 
 *            昵称 
 * @param group 
 *            所在的分组 
 * @throws XXException 
 */  
public void addRosterItem(String user, String alias, String group)  
        throws XXException;  

/** 
 * 删除好友 
 *  
 * @param user 
 *            好友id 
 * @throws XXException 
 */  
public void removeRosterItem(String user) throws XXException;  

/** 
 * 修改好友昵称 
 *  
 * @param user 
 *            好友id 
 * @param newName 
 *            新昵称 
 * @throws XXException 
 */  
public void renameRosterItem(String user, String newName)  
        throws XXException;  

/** 
 * 移动好友到新分组 
 *  
 * @param user 
 *            好友id 
 * @param group 
 *            新组名 
 * @throws XXException 
 */  
public void moveRosterItemToGroup(String user, String group)  
        throws XXException;  

/** 
 * 重命名分组 
 *  
 * @param group 
 *            以前的组名 
 * @param newGroup 
 *            新组名 
 */  
public void renameRosterGroup(String group, String newGroup);  

/** 
 * 请求好友从新受权,用在添加好友失败时,重复添加 再次向对方发出申请 
 *  
 * @param user 
 *            好友id 
 */  
public void requestAuthorizationForRosterItem(String user);  

/** 
 * 添加新分组 
 *  
 * @param group 
 */  
public void addRosterGroup(String group);  

/** 
 * 设置当前在线状态 
 */  
public void setStatusFromConfig();  

/** 
 * 发送消息 
 *  
 * @param user 
 * @param message 
 */  
public void sendMessage(String user, String message);  

/** 
 * 向服务器发送心跳包,保持长链接 经过一个闹钟控制,定时发送, 
 */  
public void sendServerPing();  

/** 
 * 从jid中获取好友名 
 *  
 * @param jid 
 * @return 
 */  
public String getNameForJID(String jid);

}

/**

  • 首先定义一些接口,须要实现一些什么样的功能,
  • @author way

/ public interface Smack { /* * 登录 * * @param account * 帐号 * @param password * 密码 * @return 是否登录成功 * @throws XXException * 抛出自定义异常,以便统一处理登录失败的问题 */ public boolean login(String account, String password) throws XXException;

/**
 * 注销登录
 * 
 * @return 是否成功
 */
public boolean logout();

/**
 * 是否已经链接上服务器
 * 
 * @return
 */
public boolean isAuthenticated();

/**
 * 添加好友
 * 
 * @param user
 *            好友id
 * @param alias
 *            昵称
 * @param group
 *            所在的分组
 * @throws XXException
 */
public void addRosterItem(String user, String alias, String group)
		throws XXException;

/**
 * 删除好友
 * 
 * @param user
 *            好友id
 * @throws XXException
 */
public void removeRosterItem(String user) throws XXException;

/**
 * 修改好友昵称
 * 
 * @param user
 *            好友id
 * @param newName
 *            新昵称
 * @throws XXException
 */
public void renameRosterItem(String user, String newName)
		throws XXException;

/**
 * 移动好友到新分组
 * 
 * @param user
 *            好友id
 * @param group
 *            新组名
 * @throws XXException
 */
public void moveRosterItemToGroup(String user, String group)
		throws XXException;

/**
 * 重命名分组
 * 
 * @param group
 *            以前的组名
 * @param newGroup
 *            新组名
 */
public void renameRosterGroup(String group, String newGroup);

/**
 * 请求好友从新受权,用在添加好友失败时,重复添加 再次向对方发出申请
 * 
 * @param user
 *            好友id
 */
public void requestAuthorizationForRosterItem(String user);

/**
 * 添加新分组
 * 
 * @param group
 */
public void addRosterGroup(String group);

/**
 * 设置当前在线状态
 */
public void setStatusFromConfig();

/**
 * 发送消息
 * 
 * @param user
 * @param message
 */
public void sendMessage(String user, String message);

/**
 * 向服务器发送心跳包,保持长链接 经过一个闹钟控制,定时发送,
 */
public void sendServerPing();

/**
 * 从jid中获取好友名
 * 
 * @param jid
 * @return
 */
public String getNameForJID(String jid);

}

真正的实现就留给他的子工具类SmackImpl。昨天我说过,本应用只有一个服务:XXService,他时继承自BaseService,BaseService也是完成了一部分通用的功能,好比说通知栏消息处理等。在XXService中,咱们主要是处理Activity与Smack中链接工做。每一个Activity在onResume时,就与该XXService绑定,绑定以后,即可调用该Service中的全部公共函数,好比说登录、发消息等等,而后Service再调用Smack中已经定义好的各类接口函数,便可完成与服务器的交互。没错,其实这就是MVC设计模式。

Service担当这个C的角色,Activity就是V的角色,Smack就是M了。

如今咱们的Activity能够调用Service中的函数提交消息给服务器了,这是单方面的,咱们同时须要得到服务器返回的信息,好比说是否登录成功、收消息之类。这个任务就天然的落到了回调接口IConnectionStatusCallback身上了,在绑定服务成功的同时,咱们注册此回调接口,下面是此接口定义的惟一一个函数。也许眼尖的朋友会问了,为何没有收到新消息的回调,其实一开始我是加了的,后面由于将数据库改为了ContentProvider,就能够去掉了,由于收消息能够经过监听数据库动态变化嘛,对吧?这就是ContentProvider的好处所在,这个留待后续详细说,这里只是说起一下。

[java] view plaincopyprint?/**

  • 服务器回调接口
  • @author way

/
public interface IConnectionStatusCallback {
/
* * 链接状态改变 *
* @param connectedState * 链接状态,有链接、未链接、连接中三种 * @param reason * 链接失败的缘由 */
public void connectionStatusChanged(int connectedState, String reason);
}

/**

  • 服务器回调接口
  • @author way

/ public interface IConnectionStatusCallback { /* * 链接状态改变 * * @param connectedState * 链接状态,有链接、未链接、连接中三种 * @param reason * 链接失败的缘由 */ public void connectionStatusChanged(int connectedState, String reason); } 在绑定服务成功的时候,将此回调传递给Service,好比登录界面的ServiceConnection:

[java] view plaincopyprint?ServiceConnection mServiceConnection = new ServiceConnection() {

@Override  
public void onServiceConnected(ComponentName name, IBinder service) {  
    mXxService = ((XXService.XXBinder) service).getService();  
    //注册回调   
    mXxService.registerConnectionStatusCallback(LoginActivity.this);  
}  

@Override  
public void onServiceDisconnected(ComponentName name) {  
    mXxService.unRegisterConnectionStatusCallback();  
    mXxService = null;  
}

};

ServiceConnection mServiceConnection = new ServiceConnection() {

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
		mXxService = ((XXService.XXBinder) service).getService();
		//注册回调
		mXxService.registerConnectionStatusCallback(LoginActivity.this);
	}

	@Override
	public void onServiceDisconnected(ComponentName name) {
		mXxService.unRegisterConnectionStatusCallback();
		mXxService = null;
	}

};

就这样,总体与服务器交互的基本框架就完成了。很简单对吧?

OK,今天就到这里了,以上仅是本人的一点心得体会,后续将详细讲解功能接口Smack的实现以及如何处理联系人和聊天记录数据库等功能,很是感谢你看到了文章末尾,话说,你是否忘记投票了呢?O(∩_∩)O哈哈~

相关文章
相关标签/搜索