版权说明:本文是基于开源LumaQQ下,开发者不直接参与QQ协议的分析工作,移植到Android平台纯粹是为了方便学习和研究之用,并且没有产生任何直接的经济效益,并且纯粹是个人的技术学习研究行为,与本人所在单位没有任何关系。此文的读者在使用过程产生的效益和涉及的法律责任与本人没有直接关系。如果影响到您或您的公司利益,敬请谅解并且与我联系,本人会第一时间作出处理。
作为一个IM工具,如果没有发送、接收消息的功能岂不是搞笑?今天我们就开始进入LumaQQ的核心部分,消息的发送和接收。其中发送部分很简单,前面的文章有过介绍,今天主要就消息的接收部分来做详细的说明。
QQ的消息大致分为普通消息、群消息、系统消息和临时消息。普通消息就是QQ用户发给你的消息;群消息就是群中的聊天消息;系统消息就是腾讯发给你的一些系统通知;临时消息就是用户创建的临时会话信息。这么多种消息我们如何来管理呢?在这里我们来模拟操作系统的消息处理机制,实现一个消息队列MessageQueue,这个消息队列类大致如下:
有了这个消息队列,我们就可以随时来处理QQ的消息,不会因为没来及读取消息导致消息的丢失。
QQ消息如此之多只是有个管理的队列显然不够,我们还需要对这些消息进行处理,我们来实现一个处理消息的辅助类MessageHelper,大致代码如下,里面我们现在只处理了普通消息
- public class MessageHelper {
- private MainShell main;
-
-
- private Map<Integer, Object[]> fragmentCache;
- public MessageHelper(MainShell main) {
- this.main = main;
- fragmentCache = new HashMap<Integer, Object[]>();
- }
-
- public String convertBytes(byte[] b) {
- StringBuffer sb = new StringBuffer();
- int offset = 0;
- int length = 0;
- for (int i = 0; i < b.length; i++) {
- if (b[i] == QQ.QQ_TAG_DEFAULT_FACE) {
- sb.append(Util.getString(b, offset, length));
- sb.append((char) b[i]).append((char) (b[i + 1] & 0xFF));
- i++;
- offset = i + 1;
- length = 0;
- } else
- length++;
- }
- if (length > 0)
- sb.append(Util.getString(b, offset, length));
- return sb.toString();
- }
-
- private boolean isFragment(NormalIM im) {
- return im.totalFragments > 1;
- }
-
- private boolean isFragment(ClusterIM im) {
- return im.fragmentCount > 1;
- }
-
- private void addFragment(NormalIM im) {
- Object[] fragments = fragmentCache.get(im.messageId);
- if (fragments == null || fragments.length != im.totalFragments) {
- fragments = new Object[im.totalFragments];
- fragmentCache.put(im.messageId, fragments);
- }
- fragments[im.fragmentSequence] = im;
- }
-
- private void addFragment(ClusterIM im) {
- Object[] fragments = fragmentCache.get(im.messageId);
- if (fragments == null || fragments.length != im.fragmentCount) {
- fragments = new Object[im.fragmentCount];
- fragmentCache.put(im.messageId, fragments);
- }
- fragments[im.fragmentSequence] = im;
- }
-
- private ClusterIM getIntegratedClusterIM(int messageId) {
- Object[] fragments = fragmentCache.remove(messageId);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (Object f : fragments) {
- try {
- baos.write(((ClusterIM) f).messageBytes);
- } catch (IOException e) {
- }
- }
- ClusterIM ret = (ClusterIM) fragments[fragments.length - 1];
- ret.messageBytes = baos.toByteArray();
- ret.message = convertBytes(ret.messageBytes);
- return ret;
- }
-
- private NormalIM getIntegratedNormalIM(int messageId) {
- Object[] fragments = fragmentCache.remove(messageId);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (Object f : fragments) {
- try {
- baos.write(((NormalIM) f).messageBytes);
- } catch (IOException e) {
- }
- }
- NormalIM ret = (NormalIM) fragments[0];
- ret.message = NormalIMFormalizer.deformalize(baos.toByteArray());
- return ret;
- }
-
- private boolean isMessageComplete(int messageId) {
- if (!fragmentCache.containsKey(messageId))
- return false;
- Object[] fragments = fragmentCache.get(messageId);
- for (Object f : fragments) {
- if (f == null)
- return false;
- }
- return true;
- }
-
- public void putNormalIM(ReceiveIMPacket packet) {
-
- MessageQueue mq = main.getMessageQueue();
- if (mq.isPostpone()) {
- mq.postponeMessage(packet);
- return;
- }
-
- if (isFragment(packet.normalIM)) {
- addFragment(packet.normalIM);
- if (isMessageComplete(packet.normalIM.messageId)) {
- packet.normalIM = getIntegratedNormalIM(packet.normalIM.messageId);
- } else {
- return;
- }
- } else {
- packet.normalIM.message = NormalIMFormalizer
- .deformalize(packet.normalIM.messageBytes);
- }
-
-
-
- User f = ModelRegistry.getUser(packet.normalHeader.sender);
- boolean iAmHisStranger = packet.header.type == QQ.QQ_RECV_IM_STRANGER;
- boolean noSuchUser = f == null || f.group.isCluster();
-
- boolean heIsMyBlacklist = f != null && f.group.isBlackList();
- if (heIsMyBlacklist || noSuchUser && iAmHisStranger) {
- return;
- }
-
- UIHelper uihelper = main.getUIHelper();
-
- if (noSuchUser) {
- f = new User();
- f.qq = packet.normalHeader.sender;
- f.nick = String.valueOf(f.qq);
- f.displayName = f.nick;
- uihelper.addUser(f, GroupType.STRANGER_GROUP);
- main.getUIHelper().refreshGroup();
- main.getClient().user_GetInfo(f.qq);
- }
- uihelper.appendMessage(f, packet.normalIM, packet.normalHeader);
-
- mq.putMessage(packet);
- }
- }
有了这两个基础的类之后我们就可以对QQ消息事件进行处理了。QQ消息方面的事件很多,这里我们只处理一下普通消息的事件
- protected void OnQQEvent(QQEvent e) {
- switch (e.type) {
- case QQEvent.IM_RECEIVED:
- processReceiveNormalIM(e);
- break;
- }
- }
- private void processReceiveNormalIM(QQEvent e) {
-
- ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
- main.getMessageHelper().putNormalIM(packet);
- }
发表于 @
2008年10月18日 11:30:00 | | 编辑|
举报| 收藏