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

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 java.util.HashMap;
  19. import java.util.Map;
  20. import android.content.ContentResolver;
  21. import android.content.ContentUris;
  22. import android.content.ContentValues;
  23. import android.database.Cursor;
  24. import android.net.Uri;
  25. import android.os.RemoteException;
  26. import android.provider.Im;
  27. import android.util.Log;
  28. import com.android.im.IChatSessionManager;
  29. import com.android.im.IConnectionListener;
  30. import com.android.im.IContactListManager;
  31. import com.android.im.IImConnection;
  32. import com.android.im.IInvitationListener;
  33. import com.android.im.engine.ChatGroupManager;
  34. import com.android.im.engine.ConnectionListener;
  35. import com.android.im.engine.Contact;
  36. import com.android.im.engine.ContactListManager;
  37. import com.android.im.engine.ImConnection;
  38. import com.android.im.engine.ImErrorInfo;
  39. import com.android.im.engine.ImException;
  40. import com.android.im.engine.Invitation;
  41. import com.android.im.engine.InvitationListener;
  42. import com.android.im.engine.LoginInfo;
  43. import com.android.im.engine.Presence;
  44. public class ImConnectionAdapter extends IImConnection.Stub {
  45.     private static final String TAG = RemoteImService.TAG;
  46.     private static final String[] SESSION_COOKIE_PROJECTION = {
  47.         Im.SessionCookies.NAME,
  48.         Im.SessionCookies.VALUE,
  49.     };
  50.     private static final int COLUMN_SESSION_COOKIE_NAME = 0;
  51.     private static final int COLUMN_SESSION_COOKIE_VALUE = 1;
  52.     ImConnection mConnection;
  53.     private ConnectionListenerAdapter mConnectionListener;
  54.     private InvitationListenerAdapter mInvitationListener;
  55.     ChatSessionManagerAdapter mChatSessionManager;
  56.     ContactListManagerAdapter mContactListManager;
  57.     ChatGroupManager mGroupManager;
  58.     RemoteImService mService;
  59.     long mProviderId = -1;
  60.     long mAccountId = -1;
  61.     boolean mAutoLoadContacts;
  62.     int mConnectionState = ImConnection.DISCONNECTED;
  63.     public ImConnectionAdapter(long providerId, ImConnection connection,
  64.             RemoteImService service) {
  65.         mProviderId = providerId;
  66.         mConnection = connection;
  67.         mService = service;
  68.         mConnectionListener = new ConnectionListenerAdapter();
  69.         mConnection.addConnectionListener(mConnectionListener);
  70.         if ((connection.getCapability() & ImConnection.CAPABILITY_GROUP_CHAT) != 0) {
  71.             mGroupManager = mConnection.getChatGroupManager();
  72.             mInvitationListener = new InvitationListenerAdapter();
  73.             mGroupManager.setInvitationListener(mInvitationListener);
  74.         }
  75.     }
  76.     public ImConnection getAdaptee() {
  77.         return mConnection;
  78.     }
  79.     public RemoteImService getContext() {
  80.         return mService;
  81.     }
  82.     public long getProviderId() {
  83.         return mProviderId;
  84.     }
  85.     public long getAccountId() {
  86.         return mAccountId;
  87.     }
  88.     public int[] getSupportedPresenceStatus() {
  89.         return mConnection.getSupportedPresenceStatus();
  90.     }
  91.     public void networkTypeChanged() {
  92.         mConnection.networkTypeChanged();
  93.     }
  94.     void reestablishSession() {
  95.         mConnectionState = ImConnection.LOGGING_IN;
  96.         ContentResolver cr = mService.getContentResolver();
  97.         if ((mConnection.getCapability() & ImConnection.CAPABILITY_SESSION_REESTABLISHMENT) != 0) {
  98.             HashMap<String, String> cookie = querySessionCookie(cr);
  99.             if (cookie != null) {
  100.                 Log.d(TAG, "re-establish session");
  101.                 try {
  102.                     mConnection.reestablishSessionAsync(cookie);
  103.                 } catch (IllegalArgumentException e) {
  104.                     Log.e(TAG, "Invalid session cookie, probably modified by others.");
  105.                     clearSessionCookie(cr);
  106.                 }
  107.             }
  108.         }
  109.     }
  110.     private Uri getSessionCookiesUri() {
  111.         Uri.Builder builder = Im.SessionCookies.CONTENT_URI_SESSION_COOKIES_BY.buildUpon();
  112.         ContentUris.appendId(builder, mProviderId);
  113.         ContentUris.appendId(builder, mAccountId);
  114.         return builder.build();
  115.     }
  116.     public void login(long accountId, String userName, String password,
  117.             boolean autoLoadContacts) {
  118.         mAccountId = accountId;
  119.         mAutoLoadContacts = autoLoadContacts;
  120.         mConnectionState = ImConnection.LOGGING_IN;
  121.         mConnection.loginAsync(new LoginInfo(userName, password));
  122.         mChatSessionManager = new ChatSessionManagerAdapter(this);
  123.         mContactListManager = new ContactListManagerAdapter(this);
  124.     }
  125.     private HashMap<String, String> querySessionCookie(ContentResolver cr) {
  126.         Cursor c = cr.query(getSessionCookiesUri(), SESSION_COOKIE_PROJECTION, null, null, null);
  127.         if (c == null) {
  128.             return null;
  129.         }
  130.         HashMap<String, String> cookie = null;
  131.         if (c.getCount() > 0) {
  132.             cookie = new HashMap<String, String>();
  133.             while(c.moveToNext()) {
  134.                 cookie.put(c.getString(COLUMN_SESSION_COOKIE_NAME),
  135.                     c.getString(COLUMN_SESSION_COOKIE_VALUE));
  136.             }
  137.         }
  138.         c.close();
  139.         return cookie;
  140.     }
  141.     public void logout() {
  142.         mConnectionState = ImConnection.LOGGING_OUT;
  143.         mConnection.logoutAsync();
  144.     }
  145.     public synchronized void cancelLogin() {
  146.         if (mConnectionState >= ImConnection.LOGGED_IN) {
  147.             // too late
  148.             return;
  149.         }
  150.         logout();
  151.     }
  152.     void suspend() {
  153.         mConnectionState = ImConnection.SUSPENDING;
  154.         mConnection.suspend();
  155.         if (mContactListManager != null) {
  156.             mContactListManager.clearPresence();
  157.         }
  158.     }
  159.     public void registerConnectionListener(IConnectionListener listener) {
  160.         mConnectionListener.addRemoteListener(listener);
  161.     }
  162.     public void unregisterConnectionListener(IConnectionListener listener) {
  163.         mConnectionListener.removeRemoteListener(listener);
  164.     }
  165.     public void setInvitationListener(IInvitationListener listener) {
  166.         if(mInvitationListener != null) {
  167.             mInvitationListener.mRemoteListener = listener;
  168.         }
  169.     }
  170.     public IChatSessionManager getChatSessionManager() {
  171.         return mChatSessionManager;
  172.     }
  173.     public IContactListManager getContactListManager() {
  174.         return mContactListManager;
  175.     }
  176.     public int getChatSessionCount() {
  177.         if (mChatSessionManager == null) {
  178.             return 0;
  179.         }
  180.         return mChatSessionManager.getChatSessionCount();
  181.     }
  182.     public Contact getLoginUser() {
  183.         return mConnection.getLoginUser();
  184.     }
  185.     public Presence getUserPresence() {
  186.         return mConnection.getUserPresence();
  187.     }
  188.     public int updateUserPresence(Presence newPresence) {
  189.         try {
  190.             mConnection.updateUserPresenceAsync(newPresence);
  191.         } catch (ImException e) {
  192.             return e.getImError().getCode();
  193.         }
  194.         return ImErrorInfo.NO_ERROR;
  195.     }
  196.     public int getState() {
  197.         return mConnectionState;
  198.     }
  199.     public void rejectInvitation(long id){
  200.         handleInvitation(id, false);
  201.     }
  202.     public void acceptInvitation(long id) {
  203.         handleInvitation(id, true);
  204.     }
  205.     private void handleInvitation(long id, boolean accept) {
  206.         if(mGroupManager == null) {
  207.             return;
  208.         }
  209.         ContentResolver cr = mService.getContentResolver();
  210.         Cursor c = cr.query(ContentUris.withAppendedId(Im.Invitation.CONTENT_URI, id), null, null, null, null);
  211.         if(c == null) {
  212.             return;
  213.         }
  214.         if(c.moveToFirst()) {
  215.             String inviteId = c.getString(c.getColumnIndexOrThrow(Im.Invitation.INVITE_ID));
  216.             int status;
  217.             if(accept) {
  218.                 mGroupManager.acceptInvitationAsync(inviteId);
  219.                 status = Im.Invitation.STATUS_ACCEPTED;
  220.             } else {
  221.                 mGroupManager.rejectInvitationAsync(inviteId);
  222.                 status = Im.Invitation.STATUS_REJECTED;
  223.             }
  224.             c.updateInt(c.getColumnIndexOrThrow(Im.Invitation.STATUS), status);
  225.             c.commitUpdates();
  226.         }
  227.         c.close();
  228.     }
  229.     void saveSessionCookie(ContentResolver cr) {
  230.         HashMap<String, String> cookies = mConnection.getSessionContext();
  231.         int i = 0;
  232.         ContentValues[] valuesList = new ContentValues[cookies.size()];
  233.         for(Map.Entry<String,String> entry : cookies.entrySet()){
  234.             ContentValues values = new ContentValues(2);
  235.             values.put(Im.SessionCookies.NAME, entry.getKey());
  236.             values.put(Im.SessionCookies.VALUE, entry.getValue());
  237.             valuesList[i++] = values;
  238.         }
  239.         cr.bulkInsert(getSessionCookiesUri(), valuesList);
  240.     }
  241.     void clearSessionCookie(ContentResolver cr) {
  242.         cr.delete(getSessionCookiesUri(), null, null);
  243.     }
  244.     final class ConnectionListenerAdapter
  245.             extends RemoteListenerManager<IConnectionListener>
  246.             implements ConnectionListener{
  247.         public void onStateChanged(final int state, final ImErrorInfo error) {
  248.             synchronized (this) {
  249.                 if (state == ImConnection.LOGGED_IN
  250.                         && mConnectionState == ImConnection.LOGGING_OUT) {
  251.                     // A bit tricky here. The engine did login successfully
  252.                     // but the notification comes a bit late; user has already
  253.                     // issued a cancelLogin() and that cannot be undone. Here
  254.                     // we have to ignore the LOGGED_IN event and wait for
  255.                     // the upcoming DISCONNECTED.
  256.                     return;
  257.                 }
  258.                 if (state != ImConnection.DISCONNECTED) {
  259.                     mConnectionState = state;
  260.                 }
  261.             }
  262.             ContentResolver cr = mService.getContentResolver();
  263.             if(state == ImConnection.LOGGED_IN) {
  264.                 if ((mConnection.getCapability() & ImConnection.CAPABILITY_SESSION_REESTABLISHMENT) != 0){
  265.                     saveSessionCookie(cr);
  266.                 }
  267.                 if(mAutoLoadContacts && mContactListManager.getState()
  268.                         != ContactListManager.LISTS_LOADED) {
  269.                     mContactListManager.loadContactLists();
  270.                 }
  271.                 for (ChatSessionAdapter session : mChatSessionManager.mActiveSessions.values()) {
  272.                     session.sendPostponedMessages();
  273.                 }
  274.             } else if(state == ImConnection.DISCONNECTED) {
  275.                 mService.removeConnection(ImConnectionAdapter.this);
  276.                 clearSessionCookie(cr);
  277.                 // mContactListManager might still be null if we fail
  278.                 // immediately in loginAsync (say, an invalid host URL)
  279.                 if (mContactListManager != null) {
  280.                     mContactListManager.clearOnLogout();
  281.                 }
  282.                 if (mChatSessionManager != null) {
  283.                     mChatSessionManager.closeAllChatSessions();
  284.                 }
  285.                 mConnectionState = state;
  286.             } else if(state == ImConnection.SUSPENDED && error != null) {
  287.                 // re-establish failed, schedule to retry
  288.                 // TODO increase delay after retry failed.
  289.                 mService.scheduleReconnect(15000);
  290.             }
  291.             notifyRemoteListeners(new ListenerInvocation<IConnectionListener>() {
  292.                 public void invoke(IConnectionListener remoteListener)
  293.                         throws RemoteException {
  294.                     remoteListener.onStateChanged(ImConnectionAdapter.this,
  295.                             state, error);
  296.                 }
  297.             });
  298.         }
  299.         public void onUserPresenceUpdated() {
  300.             notifyRemoteListeners(new ListenerInvocation<IConnectionListener>() {
  301.                 public void invoke(IConnectionListener remoteListener)
  302.                         throws RemoteException {
  303.                     remoteListener.onUserPresenceUpdated(ImConnectionAdapter.this);
  304.                 }
  305.             });
  306.         }
  307.         public void onUpdatePresenceError(final ImErrorInfo error) {
  308.             notifyRemoteListeners(new ListenerInvocation<IConnectionListener>() {
  309.                 public void invoke(IConnectionListener remoteListener)
  310.                         throws RemoteException {
  311.                     remoteListener.onUpdatePresenceError(ImConnectionAdapter.this,
  312.                             error);
  313.                 }
  314.             });
  315.         }
  316.     }
  317.     final class InvitationListenerAdapter implements InvitationListener {
  318.         IInvitationListener mRemoteListener;
  319.         public void onGroupInvitation(Invitation invitation) {
  320.             String sender = invitation.getSender().getScreenName();
  321.             ContentValues values = new ContentValues(7);
  322.             values.put(Im.Invitation.PROVIDER, mProviderId);
  323.             values.put(Im.Invitation.ACCOUNT, mAccountId);
  324.             values.put(Im.Invitation.INVITE_ID, invitation.getInviteID());
  325.             values.put(Im.Invitation.SENDER, sender);
  326.             values.put(Im.Invitation.GROUP_NAME, invitation.getGroupAddress().getScreenName());
  327.             values.put(Im.Invitation.NOTE, invitation.getReason());
  328.             values.put(Im.Invitation.STATUS, Im.Invitation.STATUS_PENDING);
  329.             ContentResolver resolver = mService.getContentResolver();
  330.             Uri uri = resolver.insert(Im.Invitation.CONTENT_URI, values);
  331.             long id = ContentUris.parseId(uri);
  332.             try {
  333.                 if (mRemoteListener != null) {
  334.                     mRemoteListener.onGroupInvitation(id);
  335.                     return;
  336.                 }
  337.             } catch (RemoteException e) {
  338.                 Log.i(TAG, "onGroupInvitation: dead listener "
  339.                         + mRemoteListener +"; removing");
  340.                 mRemoteListener = null;
  341.             }
  342.             // No listener registered or failed to notify the listener, send a
  343.             // notification instead.
  344.             mService.getStatusBarNotifier().notifyGroupInvitation(mProviderId, mAccountId, id, sender);
  345.         }
  346.     }
  347. }