ChatSessionAdapter.java
上传用户:szyujian
上传日期:2016-09-20
资源大小:320k
文件大小:21k
源码类别:

android开发

开发平台:

C/C++

  1. /*
  2.  * Copyright (C) 2007-2008 Esmertec AG.
  3.  * Copyright (C) 2007-2008 The Android Open Source Project
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package com.android.im.service;
  18. import com.android.im.IChatListener;
  19. import com.android.im.IChatSession;
  20. import com.android.im.engine.ChatGroup;
  21. import com.android.im.engine.ChatGroupManager;
  22. import com.android.im.engine.ChatSession;
  23. import com.android.im.engine.Contact;
  24. import com.android.im.engine.GroupListener;
  25. import com.android.im.engine.GroupMemberListener;
  26. import com.android.im.engine.ImConnection;
  27. import com.android.im.engine.ImEntity;
  28. import com.android.im.engine.ImErrorInfo;
  29. import com.android.im.engine.Message;
  30. import com.android.im.engine.MessageListener;
  31. import com.android.im.engine.Presence;
  32. import android.content.ContentResolver;
  33. import android.content.ContentValues;
  34. import android.content.ContentUris;
  35. import android.database.Cursor;
  36. import android.net.Uri;
  37. import android.os.RemoteException;
  38. import android.provider.BaseColumns;
  39. import android.provider.Im;
  40. import android.util.Log;
  41. import java.util.ArrayList;
  42. import java.util.HashMap;
  43. import java.util.List;
  44. public class ChatSessionAdapter extends IChatSession.Stub {
  45.     private static final String NON_CHAT_MESSAGE_SELECTION = Im.BaseMessageColumns.TYPE
  46.             + "!=" + Im.MessageType.INCOMING + " AND " + Im.BaseMessageColumns.TYPE
  47.             + "!=" + Im.MessageType.OUTGOING;
  48.     static final String TAG = RemoteImService.TAG;
  49.     ImConnectionAdapter mConnection;
  50.     ChatSessionManagerAdapter mChatManager;
  51.     ChatSession mAdaptee;
  52.     ListenerAdapter mListenerAdapter;
  53.     boolean mIsGroupChat;
  54.     StatusBarNotifier mStatusBarNotifier;
  55.     private ContentResolver mContentResolver;
  56.     /*package*/Uri mChatURI;
  57.     private Uri mMessageURI;
  58.     private boolean mConvertingToGroupChat;
  59.     private static final int MAX_HISTORY_COPY_COUNT = 10;
  60.     private HashMap<String, Integer> mContactStatusMap = new HashMap<String, Integer>();
  61.     public ChatSessionAdapter(ChatSession adaptee,
  62.             ImConnectionAdapter connection) {
  63.         mAdaptee = adaptee;
  64.         mConnection = connection;
  65.         RemoteImService service = connection.getContext();
  66.         mContentResolver = service.getContentResolver();
  67.         mStatusBarNotifier = service.getStatusBarNotifier();
  68.         mChatManager = (ChatSessionManagerAdapter) connection.getChatSessionManager();
  69.         mListenerAdapter = new ListenerAdapter();
  70.         mAdaptee.addMessageListener(mListenerAdapter);
  71.         ImEntity participant = mAdaptee.getParticipant();
  72.         if(participant instanceof ChatGroup) {
  73.             init((ChatGroup)participant);
  74.         } else {
  75.             init((Contact)participant);
  76.         }
  77.     }
  78.     private void init(ChatGroup group) {
  79.         mIsGroupChat = true;
  80.         long groupId = insertGroupContactInDb(group);
  81.         group.addMemberListener(mListenerAdapter);
  82.         mMessageURI = ContentUris.withAppendedId(
  83.                 Im.GroupMessages.CONTENT_URI_GROUP_MESSAGES_BY, groupId);
  84.         mChatURI = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, groupId);
  85.         insertOrUpdateChat(null);
  86.         for (Contact c : group.getMembers()) {
  87.             mContactStatusMap.put(c.getName(), c.getPresence().getStatus());
  88.         }
  89.     }
  90.     private void init(Contact contact) {
  91.         mIsGroupChat = false;
  92.         ContactListManagerAdapter listManager =
  93.             (ContactListManagerAdapter) mConnection.getContactListManager();
  94.         long contactId = listManager.queryOrInsertContact(contact);
  95.         long provider = mConnection.getProviderId();
  96.         long account  = mConnection.getAccountId();
  97.         String address = contact.getAddress().getFullName();
  98.         mMessageURI = Im.Messages.getContentUriByContact(provider, account, address);
  99.         mChatURI = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, contactId);
  100.         insertOrUpdateChat(null);
  101.         mContactStatusMap.put(contact.getName(), contact.getPresence().getStatus());
  102.     }
  103.     private ChatGroupManager getGroupManager() {
  104.         return mConnection.getAdaptee().getChatGroupManager();
  105.     }
  106.     public ChatSession getAdaptee() {
  107.         return mAdaptee;
  108.     }
  109.     public Uri getChatUri() {
  110.         return mChatURI;
  111.     }
  112.     public String[] getPariticipants() {
  113.         if (mIsGroupChat) {
  114.             Contact self = mConnection.getLoginUser();
  115.             ChatGroup group = (ChatGroup)mAdaptee.getParticipant();
  116.             List<Contact> members = group.getMembers();
  117.             String[] result = new String[members.size() - 1];
  118.             int index = 0;
  119.             for (Contact c : members) {
  120.                 if (!c.equals(self)) {
  121.                     result[index++] = c.getAddress().getFullName();
  122.                 }
  123.             }
  124.             return result;
  125.         } else {
  126.             return new String[] {mAdaptee.getParticipant().getAddress().getFullName()};
  127.         }
  128.     }
  129.     /**
  130.      * Convert this chat session to a group chat. If it's already a group chat,
  131.      * nothing will happen. The method works in async mode and the registered
  132.      * listener will be notified when it's converted to group chat successfully.
  133.      *
  134.      * Note that the method is not thread-safe since it's always called from
  135.      * the UI and Android uses single thread mode for UI.
  136.      */
  137.     public void convertToGroupChat() {
  138.         if (mIsGroupChat || mConvertingToGroupChat) {
  139.             return;
  140.         }
  141.         mConvertingToGroupChat = true;
  142.         new ChatConvertor().convertToGroupChat();
  143.     }
  144.     public boolean isGroupChatSession() {
  145.         return mIsGroupChat;
  146.     }
  147.     public String getName() {
  148.         return mAdaptee.getParticipant().getAddress().getScreenName();
  149.     }
  150.     public String getAddress() {
  151.         return mAdaptee.getParticipant().getAddress().getFullName();
  152.     }
  153.     public long getId() {
  154.         return ContentUris.parseId(mChatURI);
  155.     }
  156.     public void inviteContact(String contact) {
  157.         if(!mIsGroupChat){
  158.             return;
  159.         }
  160.         ContactListManagerAdapter listManager =
  161.             (ContactListManagerAdapter) mConnection.getContactListManager();
  162.         Contact invitee = listManager.getContactByAddress(contact);
  163.         if(invitee == null) {
  164.             ImErrorInfo error = new ImErrorInfo(ImErrorInfo.ILLEGAL_CONTACT_ADDRESS,
  165.                 "Cannot find contact with address: " + contact);
  166.             mListenerAdapter.onError((ChatGroup)mAdaptee.getParticipant(), error);
  167.         } else {
  168.             getGroupManager().inviteUserAsync((ChatGroup)mAdaptee.getParticipant(),
  169.                     invitee);
  170.         }
  171.     }
  172.     public void leave() {
  173.         if (mIsGroupChat) {
  174.             getGroupManager().leaveChatGroupAsync((ChatGroup)mAdaptee.getParticipant());
  175.             mContentResolver.delete(mMessageURI, null, null);
  176.         } else {
  177.             mContentResolver.delete(mMessageURI, NON_CHAT_MESSAGE_SELECTION, null);
  178.         }
  179.         mContentResolver.delete(mChatURI, null, null);
  180.         mStatusBarNotifier.dismissChatNotification(
  181.                 mConnection.getProviderId(), getAddress());
  182.         mChatManager.closeChatSession(this);
  183.     }
  184.     public void sendMessage(String text) {
  185.         if (mConnection.getState() == ImConnection.SUSPENDED) {
  186.             // connection has been suspended, save the message without send it
  187.             insertMessageInDb(null, text, -1, Im.MessageType.POSTPONED);
  188.             return;
  189.         }
  190.         Message msg = new Message(text);
  191.         mAdaptee.sendMessageAsync(msg);
  192.         long now = System.currentTimeMillis();
  193.         insertMessageInDb(null, text, now, Im.MessageType.OUTGOING);
  194.     }
  195.     void sendPostponedMessages() {
  196.         String[] projection = new String[] {
  197.             BaseColumns._ID,
  198.             Im.BaseMessageColumns.BODY,
  199.             Im.BaseMessageColumns.DATE,
  200.             Im.BaseMessageColumns.TYPE,
  201.         };
  202.         String selection = Im.BaseMessageColumns.TYPE + "=?";
  203.         Cursor c = mContentResolver.query(mMessageURI, projection, selection,
  204.                 new String[]{Integer.toString(Im.MessageType.POSTPONED)}, null);
  205.         if (c == null) {
  206.             Log.e(TAG, "Query error while querying postponed messages");
  207.             return;
  208.         }
  209.         while (c.moveToNext()) {
  210.             String body = c.getString(1);
  211.             mAdaptee.sendMessageAsync(new Message(body));
  212.             c.updateLong(2, System.currentTimeMillis());
  213.             c.updateInt(3, Im.MessageType.OUTGOING);
  214.         }
  215.         c.commitUpdates();
  216.         c.close();
  217.     }
  218.     public void registerChatListener(IChatListener listener) {
  219.         if (listener != null) {
  220.             mListenerAdapter.addRemoteListener(listener);
  221.         }
  222.     }
  223.     public void unregisterChatListener(IChatListener listener) {
  224.         mListenerAdapter.removeRemoteListener(listener);
  225.     }
  226.     String getNickName(String username) {
  227.         ImEntity participant = mAdaptee.getParticipant();
  228.         if (mIsGroupChat) {
  229.             ChatGroup group = (ChatGroup)participant;
  230.             List<Contact> members = group.getMembers();
  231.             for (Contact c : members) {
  232.                 if (username.equals(c.getAddress().getFullName())) {
  233.                     return c.getName();
  234.                 }
  235.             }
  236.             // not found, impossible
  237.             return username;
  238.         } else {
  239.             return ((Contact)participant).getName();
  240.         }
  241.     }
  242.     void onConvertToGroupChatSuccess(ChatGroup group) {
  243.         Contact oldParticipant = (Contact)mAdaptee.getParticipant();
  244.         String oldAddress = getAddress();
  245.         mAdaptee.setParticipant(group);
  246.         mChatManager.updateChatSession(oldAddress, this);
  247.         Uri oldChatUri = mChatURI;
  248.         Uri oldMessageUri = mMessageURI;
  249.         init(group);
  250.         copyHistoryMessages(oldParticipant);
  251.         mContentResolver.delete(oldMessageUri, NON_CHAT_MESSAGE_SELECTION, null);
  252.         mContentResolver.delete(oldChatUri, null, null);
  253.         mListenerAdapter.notifyChatSessionConverted();
  254.         mConvertingToGroupChat = false;
  255.     }
  256.     private void copyHistoryMessages(Contact oldParticipant) {
  257.         List<Message> historyMessages = mAdaptee.getHistoryMessages();
  258.         int total = historyMessages.size();
  259.         int start = total > MAX_HISTORY_COPY_COUNT ? total - MAX_HISTORY_COPY_COUNT : 0;
  260.         for (int i = start; i < total; i++) {
  261.             Message msg = historyMessages.get(i);
  262.             boolean incoming = msg.getFrom().equals(oldParticipant.getAddress());
  263.             String contact = incoming ? oldParticipant.getName() : null;
  264.             long time = msg.getDateTime().getTime();
  265.             insertMessageInDb(contact, msg.getBody(), time,
  266.                     incoming ? Im.MessageType.INCOMING : Im.MessageType.OUTGOING);
  267.         }
  268.     }
  269.     void insertOrUpdateChat(String message) {
  270.         ContentValues values = new ContentValues(2);
  271.         values.put(Im.Chats.LAST_MESSAGE_DATE, System.currentTimeMillis());
  272.         values.put(Im.Chats.LAST_UNREAD_MESSAGE, message);
  273.         // ImProvider.insert() will replace the chat if it already exist.
  274.         mContentResolver.insert(mChatURI, values);
  275.     }
  276.     private long insertGroupContactInDb(ChatGroup group) {
  277.         // Insert a record in contacts table
  278.         ContentValues values = new ContentValues(4);
  279.         values.put(Im.Contacts.USERNAME, group.getAddress().getFullName());
  280.         values.put(Im.Contacts.NICKNAME, group.getName());
  281.         values.put(Im.Contacts.CONTACTLIST, ContactListManagerAdapter.FAKE_TEMPORARY_LIST_ID);
  282.         values.put(Im.Contacts.TYPE, Im.Contacts.TYPE_GROUP);
  283.         Uri contactUri = ContentUris.withAppendedId(ContentUris.withAppendedId(
  284.                 Im.Contacts.CONTENT_URI, mConnection.mProviderId), mConnection.mAccountId);
  285.         long id = ContentUris.parseId(mContentResolver.insert(contactUri, values));
  286.         ArrayList<ContentValues> memberValues = new ArrayList<ContentValues>();
  287.         Contact self = mConnection.getLoginUser();
  288.         for (Contact member : group.getMembers()) {
  289.             if (!member.equals(self)) { // avoid to insert the user himself
  290.                 ContentValues memberValue = new ContentValues(2);
  291.                 memberValue.put(Im.GroupMembers.USERNAME,
  292.                         member.getAddress().getFullName());
  293.                 memberValue.put(Im.GroupMembers.NICKNAME,
  294.                         member.getName());
  295.                 memberValues.add(memberValue);
  296.             }
  297.         }
  298.         if (!memberValues.isEmpty()) {
  299.             ContentValues[] result = new ContentValues[memberValues.size()];
  300.             memberValues.toArray(result);
  301.             Uri memberUri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, id);
  302.             mContentResolver.bulkInsert(memberUri, result);
  303.         }
  304.         return id;
  305.     }
  306.     void insertGroupMemberInDb(Contact member) {
  307.         ContentValues values1 = new ContentValues(2);
  308.         values1.put(Im.GroupMembers.USERNAME, member.getAddress().getFullName());
  309.         values1.put(Im.GroupMembers.NICKNAME, member.getName());
  310.         ContentValues values = values1;
  311.         long groupId = ContentUris.parseId(mChatURI);
  312.         Uri uri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, groupId);
  313.         mContentResolver.insert(uri, values);
  314.         insertMessageInDb(member.getName(), null, System.currentTimeMillis(),
  315.                 Im.MessageType.PRESENCE_AVAILABLE);
  316.     }
  317.     void deleteGroupMemberInDb(Contact member) {
  318.         String where = Im.GroupMembers.USERNAME + "=?";
  319.         String[] selectionArgs = { member.getAddress().getFullName() };
  320.         long groupId = ContentUris.parseId(mChatURI);
  321.         Uri uri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, groupId);
  322.         mContentResolver.delete(uri, where, selectionArgs);
  323.         insertMessageInDb(member.getName(), null, System.currentTimeMillis(),
  324.                 Im.MessageType.PRESENCE_UNAVAILABLE);
  325.     }
  326.     void insertPresenceUpdatesMsg(String contact, Presence presence) {
  327.         int status = presence.getStatus();
  328.         Integer previousStatus = mContactStatusMap.get(contact);
  329.         if (previousStatus != null && previousStatus == status) {
  330.             // don't insert the presence message if it's the same status
  331.             // with the previous presence update notification
  332.             return;
  333.         }
  334.         mContactStatusMap.put(contact, status);
  335.         int messageType;
  336.         switch (status) {
  337.             case Presence.AVAILABLE:
  338.                 messageType = Im.MessageType.PRESENCE_AVAILABLE;
  339.                 break;
  340.             case Presence.AWAY:
  341.             case Presence.IDLE:
  342.                 messageType = Im.MessageType.PRESENCE_AWAY;
  343.                 break;
  344.             case Presence.DO_NOT_DISTURB:
  345.                 messageType = Im.MessageType.PRESENCE_DND;
  346.                 break;
  347.             default:
  348.                 messageType = Im.MessageType.PRESENCE_UNAVAILABLE;
  349.                 break;
  350.         }
  351.         if(mIsGroupChat) {
  352.             insertMessageInDb(contact, null, System.currentTimeMillis(), messageType);
  353.         } else {
  354.             insertMessageInDb(null, null, System.currentTimeMillis(), messageType);
  355.         }
  356.     }
  357.     void removeMessageInDb(int type) {
  358.         mContentResolver.delete(mMessageURI, Im.BaseMessageColumns.TYPE + "=?",
  359.                 new String[]{Integer.toString(type)});
  360.     }
  361.     Uri insertMessageInDb(String contact, String body, long time, int type) {
  362.         return insertMessageInDb(contact, body, time, type, 0/*No error*/);
  363.     }
  364.     Uri insertMessageInDb(String contact, String body, long time, int type, int errCode) {
  365.         ContentValues values = new ContentValues(mIsGroupChat ? 4 : 3);
  366.         values.put(Im.BaseMessageColumns.BODY, body);
  367.         values.put(Im.BaseMessageColumns.DATE, time);
  368.         values.put(Im.BaseMessageColumns.TYPE, type);
  369.         values.put(Im.BaseMessageColumns.ERROR_CODE, errCode);
  370.         if (mIsGroupChat) {
  371.             values.put(Im.BaseMessageColumns.CONTACT, contact);
  372.         }
  373.         return mContentResolver.insert(mMessageURI, values);
  374.     }
  375.     class ListenerAdapter extends RemoteListenerManager<IChatListener>
  376.             implements MessageListener, GroupMemberListener {
  377.         public void onIncomingMessage(ChatSession ses, final Message msg) {
  378.             String body = msg.getBody();
  379.             String username = msg.getFrom().getFullName();
  380.             String nickname = getNickName(username);
  381.             long time = msg.getDateTime().getTime();
  382.             if(mIsGroupChat) {
  383.                 insertOrUpdateChat(nickname + ": " + body);
  384.             } else {
  385.                 insertOrUpdateChat(body);
  386.             }
  387.             insertMessageInDb(nickname, body, time, Im.MessageType.INCOMING);
  388.             boolean notified = notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  389.                 public void invoke(IChatListener remoteListener)
  390.                         throws RemoteException {
  391.                     remoteListener.onIncomingMessage(ChatSessionAdapter.this,
  392.                             msg);
  393.                 }
  394.             });
  395.             if (!notified) {
  396.                 mStatusBarNotifier.notifyChat(mConnection.getProviderId(),
  397.                         mConnection.getAccountId(), getId(), username, nickname, body);
  398.             }
  399.         }
  400.         public void onSendMessageError(ChatSession ses, final Message msg,
  401.                 final ImErrorInfo error) {
  402.             insertMessageInDb(null, null, System.currentTimeMillis(),
  403.                     Im.MessageType.OUTGOING, error.getCode());
  404.             notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  405.                 public void invoke(IChatListener remoteListener)
  406.                         throws RemoteException {
  407.                     remoteListener.onSendMessageError(ChatSessionAdapter.this,
  408.                             msg, error);
  409.                 }
  410.             });
  411.         }
  412.         public void onMemberJoined(ChatGroup group, final Contact contact) {
  413.             insertGroupMemberInDb(contact);
  414.             notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  415.                 public void invoke(IChatListener remoteListener)
  416.                         throws RemoteException {
  417.                     remoteListener.onContactJoined(ChatSessionAdapter.this,
  418.                             contact);
  419.                 }
  420.             });
  421.         }
  422.         public void onMemberLeft(ChatGroup group, final Contact contact) {
  423.             deleteGroupMemberInDb(contact);
  424.             notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  425.                 public void invoke(IChatListener remoteListener)
  426.                         throws RemoteException {
  427.                     remoteListener.onContactLeft(ChatSessionAdapter.this,
  428.                             contact);
  429.                 }
  430.             });
  431.         }
  432.         public void onError(ChatGroup group, final ImErrorInfo error) {
  433.             // TODO: insert an error message?
  434.             notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  435.                 public void invoke(IChatListener remoteListener)
  436.                         throws RemoteException {
  437.                     remoteListener.onInviteError(ChatSessionAdapter.this,
  438.                             error);
  439.                 }
  440.             });
  441.         }
  442.         public void notifyChatSessionConverted() {
  443.             notifyRemoteListeners(new ListenerInvocation<IChatListener>() {
  444.                 public void invoke(IChatListener remoteListener)
  445.                         throws RemoteException {
  446.                     remoteListener.onConvertedToGroupChat(ChatSessionAdapter.this);
  447.                 }
  448.             });
  449.         }
  450.     }
  451.     class ChatConvertor implements GroupListener, GroupMemberListener {
  452.         private ChatGroupManager mGroupMgr;
  453.         private String mGroupName;
  454.         public ChatConvertor() {
  455.             mGroupMgr = mConnection.mGroupManager;
  456.         }
  457.         public void convertToGroupChat() {
  458.             mGroupMgr.addGroupListener(this);
  459.             mGroupName = "G" + System.currentTimeMillis();
  460.             mGroupMgr.createChatGroupAsync(mGroupName);
  461.         }
  462.         public void onGroupCreated(ChatGroup group) {
  463.             if (mGroupName.equalsIgnoreCase(group.getName())) {
  464.                 mGroupMgr.removeGroupListener(this);
  465.                 group.addMemberListener(this);
  466.                 mGroupMgr.inviteUserAsync(group, (Contact)mAdaptee.getParticipant());
  467.             }
  468.         }
  469.         public void onMemberJoined(ChatGroup group, Contact contact) {
  470.             if (mAdaptee.getParticipant().equals(contact)) {
  471.                 onConvertToGroupChatSuccess(group);
  472.             }
  473.             mContactStatusMap.put(contact.getName(), contact.getPresence().getStatus());
  474.         }
  475.         public void onGroupDeleted(ChatGroup group) {
  476.         }
  477.         public void onGroupError(int errorType, String groupName, ImErrorInfo error) {
  478.         }
  479.         public void onJoinedGroup(ChatGroup group) {
  480.         }
  481.         public void onLeftGroup(ChatGroup group) {
  482.         }
  483.         public void onError(ChatGroup group, ImErrorInfo error) {
  484.         }
  485.         public void onMemberLeft(ChatGroup group, Contact contact) {
  486.             mContactStatusMap.remove(contact.getName());
  487.         }
  488.     }
  489. }