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

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.app;
  18. import android.app.Activity;
  19. import android.app.Application;
  20. import android.content.ComponentName;
  21. import android.content.ContentResolver;
  22. import android.content.ContentUris;
  23. import android.content.ContentValues;
  24. import android.content.Context;
  25. import android.content.Intent;
  26. import android.content.ServiceConnection;
  27. import android.content.res.Resources;
  28. import android.database.Cursor;
  29. import android.net.Uri;
  30. import android.os.Broadcaster;
  31. import android.os.Handler;
  32. import android.os.IBinder;
  33. import android.os.Message;
  34. import android.os.RemoteException;
  35. import android.provider.Im;
  36. import android.util.Log;
  37. import com.android.im.IConnectionCreationListener;
  38. import com.android.im.IImConnection;
  39. import com.android.im.IRemoteImService;
  40. import com.android.im.R;
  41. import com.android.im.app.adapter.ConnectionListenerAdapter;
  42. import com.android.im.engine.ImConnection;
  43. import com.android.im.engine.ImErrorInfo;
  44. import com.android.im.plugin.BrandingResourceIDs;
  45. import com.android.im.plugin.ImPluginInfo;
  46. import com.android.im.service.ImServiceConstants;
  47. import java.util.ArrayList;
  48. import java.util.HashMap;
  49. import java.util.Iterator;
  50. import java.util.List;
  51. public class ImApp extends Application {
  52.     public static final String LOG_TAG = "ImApp";
  53.     public static final String EXTRA_INTENT_SEND_TO_USER = "Send2_U";
  54.     public static final String EXTRA_INTENT_PASSWORD = "password";
  55.     private static ImApp sImApp;
  56.     IRemoteImService mImService;
  57.     HashMap<Long, IImConnection> mConnections;
  58.     MyConnListener mConnectionListener;
  59.     HashMap<Long, ProviderDef> mProviders;
  60.     Broadcaster mBroadcaster;
  61.     /** A queue of messages that are waiting to be sent when service is connected.*/
  62.     ArrayList<Message> mQueue = new ArrayList<Message>();
  63.     /** A flag indicates that we have called to start the service.*/
  64.     private boolean mServiceStarted;
  65.     private Context mApplicationContext;
  66.     private Resources mPrivateResources;
  67.     private HashMap<Long, BrandingResources> mBrandingResources;
  68.     private BrandingResources mDefaultBrandingResources;
  69.     public static final int EVENT_SERVICE_CONNECTED = 100;
  70.     public static final int EVENT_CONNECTION_CREATED = 150;
  71.     public static final int EVENT_CONNECTION_LOGGING_IN = 200;
  72.     public static final int EVENT_CONNECTION_LOGGED_IN = 201;
  73.     public static final int EVENT_CONNECTION_LOGGING_OUT = 202;
  74.     public static final int EVENT_CONNECTION_DISCONNECTED = 203;
  75.     public static final int EVENT_CONNECTION_SUSPENDED = 204;
  76.     public static final int EVENT_USER_PRESENCE_UPDATED = 300;
  77.     public static final int EVENT_UPDATE_USER_PRESENCE_ERROR = 301;
  78.     private static final String[] PROVIDER_PROJECTION = {
  79.         Im.Provider._ID,
  80.         Im.Provider.NAME,
  81.         Im.Provider.FULLNAME,
  82.         Im.Provider.SIGNUP_URL,
  83.     };
  84.     private static final String[] ACCOUNT_PROJECTION = {
  85.         Im.Account._ID,
  86.         Im.Account.PROVIDER,
  87.         Im.Account.NAME,
  88.         Im.Account.USERNAME,
  89.         Im.Account.PASSWORD,
  90.     };
  91.     static final void log(String log) {
  92.         Log.d(LOG_TAG, log);
  93.     }
  94.     public static ImApp getApplication(Activity activity) {
  95.         // TODO should this be synchronized?
  96.         if (sImApp == null) {
  97.             initialize(activity);
  98.         }
  99.         return sImApp;
  100.     }
  101.     /**
  102.      * Initialize performs the manual ImApp instantiation and initialization. When the
  103.      * ImApp is started first in the process, the ImApp public constructor should be called,
  104.      * and sImApp initialized. So calling initialize() later should have no effect. However,
  105.      * if another application runs in the same process and is started first, the ImApp
  106.      * application object won't be instantiated, and we need to call initialize() manually to
  107.      * instantiate and initialize it.
  108.      */
  109.     private static void initialize(Activity activity) {
  110.         // construct the TalkApp manually and call onCreate().
  111.         sImApp = new ImApp();
  112.         sImApp.mApplicationContext = activity.getApplication();
  113.         sImApp.mPrivateResources = activity.getResources();
  114.         sImApp.onCreate();
  115.     }
  116.     @Override
  117.     public Resources getResources() {
  118.         if (mApplicationContext == this) {
  119.             return super.getResources();
  120.         }
  121.         return mPrivateResources;
  122.     }
  123.     @Override
  124.     public ContentResolver getContentResolver() {
  125.         if (mApplicationContext == this) {
  126.             return super.getContentResolver();
  127.         }
  128.         return mApplicationContext.getContentResolver();
  129.     }
  130.     public ImApp() {
  131.         super();
  132.         mConnections = new HashMap<Long, IImConnection>();
  133.         mApplicationContext = this;
  134.         sImApp = this;
  135.     }
  136.     @Override
  137.     public void onCreate() {
  138.         super.onCreate();
  139.         mBroadcaster = new Broadcaster();
  140.         loadDefaultBrandingRes();
  141.         mBrandingResources = new HashMap<Long, BrandingResources>();
  142.     }
  143.     @Override
  144.     public void onTerminate() {
  145.         stopImServiceIfInactive();
  146.         if (mImService != null) {
  147.             try {
  148.                 mImService.removeConnectionCreatedListener(mConnCreationListener);
  149.             } catch (RemoteException e) {
  150.                 Log.w(LOG_TAG, "failed to remove ConnectionCreatedListener");
  151.             }
  152.         }
  153.         super.onTerminate();
  154.     }
  155.     public synchronized void startImServiceIfNeed() {
  156.         if(!mServiceStarted) {
  157.             if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("start ImService");
  158.             Intent serviceIntent = new Intent();
  159.             serviceIntent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT);
  160.             mApplicationContext.startService(serviceIntent);
  161.             mApplicationContext.bindService(serviceIntent, mImServiceConn, Context.BIND_AUTO_CREATE);
  162.             mServiceStarted = true;
  163.             mConnectionListener = new MyConnListener(new Handler());
  164.         }
  165.     }
  166.     public synchronized void stopImServiceIfInactive() {
  167.         boolean hasActiveConnection = true;
  168.         synchronized (mConnections) {
  169.             hasActiveConnection = !mConnections.isEmpty();
  170.         }
  171.         if (!hasActiveConnection && mServiceStarted) {
  172.             if (Log.isLoggable(LOG_TAG, Log.DEBUG))
  173.                 log("stop ImService because there's no active connections");
  174.             if(mImService != null) {
  175.                 mApplicationContext.unbindService(mImServiceConn);
  176.                 mImService = null;
  177.             }
  178.             Intent intent = new Intent();
  179.             intent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT);
  180.             mApplicationContext.stopService(intent);
  181.             mServiceStarted = false;
  182.         }
  183.     }
  184.     private ServiceConnection mImServiceConn = new ServiceConnection() {
  185.         public void onServiceConnected(ComponentName className, IBinder service) {
  186.             if(Log.isLoggable(LOG_TAG, Log.DEBUG))
  187.                 log("service connected");
  188.             mImService = IRemoteImService.Stub.asInterface(service);
  189.             fetchActiveConnections();
  190.             loadBrandingResources();
  191.             synchronized (mQueue) {
  192.                 for (Message msg : mQueue) {
  193.                     msg.sendToTarget();
  194.                 }
  195.                 mQueue.clear();
  196.             }
  197.             Message msg = Message.obtain(null, EVENT_SERVICE_CONNECTED);
  198.             mBroadcaster.broadcast(msg);
  199.         }
  200.         public void onServiceDisconnected(ComponentName className) {
  201.             if(Log.isLoggable(LOG_TAG, Log.DEBUG))
  202.                 log("service disconnected");
  203.             mConnections.clear();
  204.             mImService = null;
  205.         }
  206.     };
  207.     public boolean serviceConnected() {
  208.         return mImService != null;
  209.     }
  210.     public static long insertOrUpdateAccount(ContentResolver cr,
  211.             long providerId, String userName, String pw) {
  212.         String selection = Im.Account.PROVIDER + "=? AND " + Im.Account.USERNAME + "=?";
  213.         String[] selectionArgs = {Long.toString(providerId), userName };
  214.         Cursor c = cr.query(Im.Account.CONTENT_URI, ACCOUNT_PROJECTION,
  215.                 selection, selectionArgs, null);
  216.         if (c != null && c.moveToFirst()) {
  217.             // Update the password
  218.             c.updateString(c.getColumnIndexOrThrow(Im.Account.PASSWORD), pw);
  219.             c.commitUpdates();
  220.             long id = c.getLong(c.getColumnIndexOrThrow(Im.Account._ID));
  221.             c.close();
  222.             return id;
  223.         } else {
  224.             ContentValues values = new ContentValues(4);
  225.             values.put(Im.Account.PROVIDER, providerId);
  226.             values.put(Im.Account.NAME, userName);
  227.             values.put(Im.Account.USERNAME, userName);
  228.             values.put(Im.Account.PASSWORD, pw);
  229.             Uri result = cr.insert(Im.Account.CONTENT_URI, values);
  230.             return ContentUris.parseId(result);
  231.         }
  232.     }
  233.     private void loadImProviderSettings() {
  234.         if (mProviders != null) {
  235.             return;
  236.         }
  237.         mProviders = new HashMap<Long, ProviderDef>();
  238.         ContentResolver cr = getContentResolver();
  239.         Cursor c = cr.query(Im.Provider.CONTENT_URI, PROVIDER_PROJECTION,
  240.                 null, null, null);
  241.         if (c == null) {
  242.             return;
  243.         }
  244.         while (c.moveToNext()) {
  245.             long id = c.getLong(0);
  246.             String providerName = c.getString(1);
  247.             String fullName = c.getString(2);
  248.             String signUpUrl = c.getString(3);
  249.             mProviders.put(id, new ProviderDef(id, providerName, fullName, signUpUrl));
  250.         }
  251.         c.close();
  252.     }
  253.     private void loadDefaultBrandingRes() {
  254.         HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>();
  255.         resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.imlogo_s);
  256.         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE,
  257.                 android.R.drawable.presence_online);
  258.         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY,
  259.                 android.R.drawable.presence_away);
  260.         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY,
  261.                 android.R.drawable.presence_busy);
  262.         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE,
  263.                 android.R.drawable.presence_invisible);
  264.         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE,
  265.                 android.R.drawable.presence_offline);
  266.         resMapping.put(BrandingResourceIDs.DRAWABLE_BLOCK, R.drawable.ic_im_block);
  267.         resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES, R.array.default_smiley_names);
  268.         resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS, R.array.default_smiley_texts);
  269.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AVAILABLE, R.string.presence_available);
  270.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_BUSY, R.string.presence_busy);
  271.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AWAY, R.string.presence_away);
  272.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_IDLE, R.string.presence_idle);
  273.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_OFFLINE, R.string.presence_offline);
  274.         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_INVISIBLE, R.string.presence_invisible);
  275.         resMapping.put(BrandingResourceIDs.STRING_LABEL_USERNAME, R.string.label_username);
  276.         resMapping.put(BrandingResourceIDs.STRING_ONGOING_CONVERSATION,
  277.                 R.string.ongoing_conversation);
  278.         resMapping.put(BrandingResourceIDs.STRING_ADD_CONTACT_TITLE, R.string.add_contact_title);
  279.         resMapping.put(BrandingResourceIDs.STRING_LABEL_INPUT_CONTACT,
  280.                 R.string.input_contact_label);
  281.         resMapping.put(BrandingResourceIDs.STRING_BUTTON_ADD_CONTACT, R.string.invite_label);
  282.         resMapping.put(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE,
  283.                 R.string.contact_profile_title);
  284.         resMapping.put(BrandingResourceIDs.STRING_MENU_ADD_CONTACT, R.string.menu_add_contact);
  285.         resMapping.put(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT, R.string.menu_block_contact);
  286.         resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST,
  287.                 R.string.menu_view_contact_list);
  288.         resMapping.put(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT,
  289.                 R.string.menu_remove_contact);
  290.         resMapping.put(BrandingResourceIDs.STRING_MENU_END_CHAT, R.string.menu_end_conversation);
  291.         resMapping.put(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY, R.string.menu_insert_smiley);
  292.         resMapping.put(BrandingResourceIDs.STRING_MENU_START_CHAT, R.string.menu_start_chat);
  293.         resMapping.put(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE, R.string.menu_view_profile);
  294.         resMapping.put(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS, R.string.menu_switch_chats);
  295.         resMapping.put(BrandingResourceIDs.STRING_TOAST_CHECK_AUTO_SIGN_IN,
  296.                 R.string.check_auto_sign_in);
  297.         resMapping.put(BrandingResourceIDs.STRING_LABEL_SIGN_UP, R.string.sign_up);
  298.         mDefaultBrandingResources = new BrandingResources(this, resMapping, null /* default res */);
  299.     }
  300.     void loadBrandingResources() {
  301.         try {
  302.             List<ImPluginInfo> plugins = mImService.getAllPlugins();
  303.             for (ImPluginInfo plugin : plugins) {
  304.                 long providerId = getProviderId(plugin.mProviderName);
  305.                 if (!mBrandingResources.containsKey(providerId)) {
  306.                     BrandingResources res = new BrandingResources(this,
  307.                             plugin, mDefaultBrandingResources);
  308.                     mBrandingResources.put(providerId, res);
  309.                 }
  310.             }
  311.         } catch (RemoteException e) {
  312.             Log.e(LOG_TAG, "Service died while loading branding resource");
  313.         }
  314.     }
  315.     public long getProviderId(String name) {
  316.         loadImProviderSettings();
  317.         for (ProviderDef provider: mProviders.values()) {
  318.             if(provider.mName.equals(name)) {
  319.                 return provider.mId;
  320.             }
  321.         }
  322.         return -1;
  323.     }
  324.     public ProviderDef getProvider(long id) {
  325.         loadImProviderSettings();
  326.         return mProviders.get(id);
  327.     }
  328.     public List<ProviderDef> getProviders() {
  329.         loadImProviderSettings();
  330.         ArrayList<ProviderDef> result = new ArrayList<ProviderDef>();
  331.         result.addAll(mProviders.values());
  332.         return result;
  333.     }
  334.     public BrandingResources getBrandingResource(long providerId) {
  335.         BrandingResources res = mBrandingResources.get(providerId);
  336.         return res == null ? mDefaultBrandingResources : res;
  337.     }
  338.     public IImConnection createConnection(long providerId) throws RemoteException {
  339.         IImConnection conn = getConnection(providerId);
  340.         if (conn == null) {
  341.             conn = mImService.createConnection(providerId);
  342.         }
  343.         return conn;
  344.     }
  345.     IImConnection getConnection(long providerId) {
  346.         synchronized (mConnections) {
  347.             return mConnections.get(providerId);
  348.         }
  349.     }
  350.     public IImConnection getConnectionByAccount(long accountId) {
  351.         synchronized (mConnections) {
  352.             for (IImConnection conn : mConnections.values()) {
  353.                 try {
  354.                     if (conn.getAccountId() == accountId) {
  355.                         return conn;
  356.                     }
  357.                 } catch (RemoteException e) {
  358.                     // No server!
  359.                 }
  360.             }
  361.             return null;
  362.         }
  363.     }
  364.     public List<IImConnection> getActiveConnections() {
  365.         synchronized (mConnections) {
  366.             ArrayList<IImConnection> result = new ArrayList<IImConnection>();
  367.             result.addAll(mConnections.values());
  368.             return result;
  369.         }
  370.     }
  371.     public void callWhenServiceConnected(Handler target, Runnable callback) {
  372.         Message msg = Message.obtain(target, callback);
  373.         if (serviceConnected()) {
  374.             msg.sendToTarget();
  375.         } else {
  376.             startImServiceIfNeed();
  377.             synchronized (mQueue) {
  378.                 mQueue.add(msg);
  379.             }
  380.         }
  381.     }
  382.     public void removePendingCall(Handler target) {
  383.         synchronized (mQueue) {
  384.            Iterator<Message> iter = mQueue.iterator();
  385.            while (iter.hasNext()) {
  386.                Message msg = iter.next();
  387.                if (msg.getTarget() == target) {
  388.                    iter.remove();
  389.                }
  390.            }
  391.        }
  392.    }
  393.     public void registerForBroadcastEvent(int what, Handler target) {
  394.         mBroadcaster.request(what, target, what);
  395.     }
  396.     public void unregisterForBroadcastEvent(int what, Handler target) {
  397.         mBroadcaster.cancelRequest(what, target, what);
  398.     }
  399.     public void registerForConnEvents(Handler handler) {
  400.         mBroadcaster.request(EVENT_CONNECTION_CREATED, handler,
  401.                 EVENT_CONNECTION_CREATED);
  402.         mBroadcaster.request(EVENT_CONNECTION_LOGGING_IN, handler,
  403.                 EVENT_CONNECTION_LOGGING_IN);
  404.         mBroadcaster.request(EVENT_CONNECTION_LOGGED_IN, handler,
  405.                 EVENT_CONNECTION_LOGGED_IN);
  406.         mBroadcaster.request(EVENT_CONNECTION_LOGGING_OUT, handler,
  407.                 EVENT_CONNECTION_LOGGING_OUT);
  408.         mBroadcaster.request(EVENT_CONNECTION_SUSPENDED, handler,
  409.                 EVENT_CONNECTION_SUSPENDED);
  410.         mBroadcaster.request(EVENT_CONNECTION_DISCONNECTED, handler,
  411.                 EVENT_CONNECTION_DISCONNECTED);
  412.         mBroadcaster.request(EVENT_USER_PRESENCE_UPDATED, handler,
  413.                 EVENT_USER_PRESENCE_UPDATED);
  414.         mBroadcaster.request(EVENT_UPDATE_USER_PRESENCE_ERROR, handler,
  415.                 EVENT_UPDATE_USER_PRESENCE_ERROR);
  416.     }
  417.     public void unregisterForConnEvents(Handler handler) {
  418.         mBroadcaster.cancelRequest(EVENT_CONNECTION_CREATED, handler,
  419.                 EVENT_CONNECTION_CREATED);
  420.         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_IN, handler,
  421.                 EVENT_CONNECTION_LOGGING_IN);
  422.         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGED_IN, handler,
  423.                 EVENT_CONNECTION_LOGGED_IN);
  424.         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_OUT, handler,
  425.                 EVENT_CONNECTION_LOGGING_OUT);
  426.         mBroadcaster.cancelRequest(EVENT_CONNECTION_SUSPENDED, handler,
  427.                 EVENT_CONNECTION_SUSPENDED);
  428.         mBroadcaster.cancelRequest(EVENT_CONNECTION_DISCONNECTED, handler,
  429.                 EVENT_CONNECTION_DISCONNECTED);
  430.         mBroadcaster.cancelRequest(EVENT_USER_PRESENCE_UPDATED, handler,
  431.                 EVENT_USER_PRESENCE_UPDATED);
  432.         mBroadcaster.cancelRequest(EVENT_UPDATE_USER_PRESENCE_ERROR, handler,
  433.                 EVENT_UPDATE_USER_PRESENCE_ERROR);
  434.     }
  435.     void broadcastConnEvent(int what, long providerId, ImErrorInfo error) {
  436.         if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
  437.             log("broadcasting connection event " + what + ", provider id " + providerId);
  438.         }
  439.         android.os.Message msg = android.os.Message.obtain(
  440.                 null,
  441.                 what,
  442.                 (int)(providerId >> 32), (int)providerId,
  443.                 error);
  444.         mBroadcaster.broadcast(msg);
  445.     }
  446.     public void dismissNotifications(long providerId) {
  447.         if (mImService != null) {
  448.             try {
  449.                 mImService.dismissNotifications(providerId);
  450.             } catch (RemoteException e) {
  451.             }
  452.         }
  453.     }
  454.     private void fetchActiveConnections() {
  455.         try {
  456.             // register the listener before fetch so that we won't miss any connection.
  457.             mImService.addConnectionCreatedListener(mConnCreationListener);
  458.             synchronized (mConnections) {
  459.                 for(IBinder binder: (List<IBinder>) mImService.getActiveConnections()) {
  460.                     IImConnection conn = IImConnection.Stub.asInterface(binder);
  461.                     long providerId = conn.getProviderId();
  462.                     if (!mConnections.containsKey(providerId)) {
  463.                         mConnections.put(providerId, conn);
  464.                         conn.registerConnectionListener(mConnectionListener);
  465.                     }
  466.                 }
  467.             }
  468.         } catch (RemoteException e) {
  469.             Log.e(LOG_TAG, "fetching active connections", e);
  470.         }
  471.     }
  472.     private final IConnectionCreationListener mConnCreationListener
  473.             = new IConnectionCreationListener.Stub() {
  474.         public void onConnectionCreated(IImConnection conn)
  475.                 throws RemoteException {
  476.             long providerId = conn.getProviderId();
  477.             synchronized (mConnections) {
  478.                 if (!mConnections.containsKey(providerId)) {
  479.                     mConnections.put(providerId, conn);
  480.                     conn.registerConnectionListener(mConnectionListener);
  481.                 }
  482.             }
  483.             broadcastConnEvent(EVENT_CONNECTION_CREATED, providerId, null);
  484.         }
  485.       };
  486.     private final class MyConnListener extends ConnectionListenerAdapter {
  487.         public MyConnListener(Handler handler) {
  488.             super(handler);
  489.         }
  490.         @Override
  491.         public void onConnectionStateChange(IImConnection conn, int state,
  492.                 ImErrorInfo error) {
  493.             if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
  494.                 log("onConnectionStateChange(" + state + ", " + error + ")");
  495.             }
  496.             try {
  497.                 int what = -1;
  498.                 long providerId = conn.getProviderId();
  499.                 switch (state) {
  500.                 case ImConnection.LOGGED_IN:
  501.                     what = EVENT_CONNECTION_LOGGED_IN;
  502.                     // Update the active value. We restrict to only one active
  503.                     // account per provider right now, so update all accounts of
  504.                     // this provider to inactive first and then update this
  505.                     // account to active.
  506.                     ContentValues values = new ContentValues(1);
  507.                     values.put(Im.Account.ACTIVE, 0);
  508.                     ContentResolver cr = getContentResolver();
  509.                     cr.update(Im.Account.CONTENT_URI, values,
  510.                             Im.Account.PROVIDER + "=" + providerId, null);
  511.                     values.put(Im.Account.ACTIVE, 1);
  512.                     cr.update(ContentUris.withAppendedId(Im.Account.CONTENT_URI, conn.getAccountId()),
  513.                             values, null, null);
  514.                     break;
  515.                 case ImConnection.LOGGING_IN:
  516.                     what = EVENT_CONNECTION_LOGGING_IN;
  517.                     break;
  518.                 case ImConnection.LOGGING_OUT:
  519.                     what = EVENT_CONNECTION_LOGGING_OUT;
  520.                     break;
  521.                 case ImConnection.DISCONNECTED:
  522.                     what = EVENT_CONNECTION_DISCONNECTED;
  523.                     synchronized (mConnections) {
  524.                         mConnections.remove(providerId);
  525.                     }
  526.                     // stop the service if there isn't an active connection anymore.
  527.                     stopImServiceIfInactive();
  528.                     break;
  529.                 case ImConnection.SUSPENDED:
  530.                     what = EVENT_CONNECTION_SUSPENDED;
  531.                     break;
  532.                 }
  533.                 if (what != -1) {
  534.                     broadcastConnEvent(what, providerId, error);
  535.                 }
  536.             } catch (RemoteException e) {
  537.                 Log.e(LOG_TAG, "onConnectionStateChange", e);
  538.             }
  539.         }
  540.         @Override
  541.         public void onUpdateSelfPresenceError(IImConnection connection,
  542.                 ImErrorInfo error) {
  543.             if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
  544.                 log("onUpdateUserPresenceError(" + error + ")");
  545.             }
  546.             try {
  547.                 long providerId = connection.getProviderId();
  548.                 broadcastConnEvent(EVENT_UPDATE_USER_PRESENCE_ERROR, providerId,
  549.                         error);
  550.             } catch (RemoteException e) {
  551.                 Log.e(LOG_TAG, "onUpdateUserPresenceError", e);
  552.             }
  553.         }
  554.         @Override
  555.         public void onSelfPresenceUpdated(IImConnection connection) {
  556.             if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("onUserPresenceUpdated");
  557.             try {
  558.                 long providerId = connection.getProviderId();
  559.                 broadcastConnEvent(EVENT_USER_PRESENCE_UPDATED, providerId,
  560.                         null);
  561.             } catch (RemoteException e) {
  562.                 Log.e(LOG_TAG, "onUserPresenceUpdated", e);
  563.             }
  564.         }
  565.     }
  566. }