| /* |
| * Copyright (C) 2007-2008 Esmertec AG. |
| * Copyright (C) 2007-2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.im.app; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import android.app.Activity; |
| import android.app.Application; |
| import android.content.ComponentName; |
| import android.content.ContentResolver; |
| import android.content.ContentUris; |
| import android.content.ContentValues; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.ServiceConnection; |
| import android.content.pm.PackageManager; |
| import android.content.pm.PackageManager.NameNotFoundException; |
| import android.content.res.Resources; |
| import android.database.Cursor; |
| import android.net.ConnectivityManager; |
| import android.net.Uri; |
| import android.os.Broadcaster; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.Message; |
| import android.os.RemoteException; |
| import android.util.Log; |
| |
| import com.android.im.IConnectionCreationListener; |
| import com.android.im.IImConnection; |
| import com.android.im.IRemoteImService; |
| import com.android.im.R; |
| import com.android.im.app.adapter.ConnectionListenerAdapter; |
| import com.android.im.engine.ImConnection; |
| import com.android.im.engine.ImErrorInfo; |
| import com.android.im.plugin.BrandingResourceIDs; |
| import com.android.im.plugin.ImPlugin; |
| import com.android.im.plugin.ImPluginInfo; |
| import com.android.im.provider.Imps; |
| import com.android.im.service.ImServiceConstants; |
| |
| public class ImApp extends Application { |
| public static final String LOG_TAG = "ImApp"; |
| |
| public static final String EXTRA_INTENT_SEND_TO_USER = "Send2_U"; |
| public static final String EXTRA_INTENT_PASSWORD = "password"; |
| |
| public static final String IMPS_CATEGORY = "com.android.im.IMPS_CATEGORY"; |
| |
| private static ImApp sImApp; |
| |
| IRemoteImService mImService; |
| |
| HashMap<Long, IImConnection> mConnections; |
| MyConnListener mConnectionListener; |
| HashMap<Long, ProviderDef> mProviders; |
| |
| Broadcaster mBroadcaster; |
| |
| /** A queue of messages that are waiting to be sent when service is connected.*/ |
| ArrayList<Message> mQueue = new ArrayList<Message>(); |
| |
| /** A flag indicates that we have called to start the service.*/ |
| private boolean mServiceStarted; |
| private Context mApplicationContext; |
| private Resources mPrivateResources; |
| |
| private HashMap<String, BrandingResources> mBrandingResources; |
| private BrandingResources mDefaultBrandingResources; |
| |
| public static final int EVENT_SERVICE_CONNECTED = 100; |
| public static final int EVENT_CONNECTION_CREATED = 150; |
| public static final int EVENT_CONNECTION_LOGGING_IN = 200; |
| public static final int EVENT_CONNECTION_LOGGED_IN = 201; |
| public static final int EVENT_CONNECTION_LOGGING_OUT = 202; |
| public static final int EVENT_CONNECTION_DISCONNECTED = 203; |
| public static final int EVENT_CONNECTION_SUSPENDED = 204; |
| public static final int EVENT_USER_PRESENCE_UPDATED = 300; |
| public static final int EVENT_UPDATE_USER_PRESENCE_ERROR = 301; |
| |
| private static final String[] PROVIDER_PROJECTION = { |
| Imps.Provider._ID, |
| Imps.Provider.NAME, |
| Imps.Provider.FULLNAME, |
| Imps.Provider.SIGNUP_URL, |
| }; |
| |
| private static final String[] ACCOUNT_PROJECTION = { |
| Imps.Account._ID, |
| Imps.Account.PROVIDER, |
| Imps.Account.NAME, |
| Imps.Account.USERNAME, |
| Imps.Account.PASSWORD, |
| }; |
| |
| static final void log(String log) { |
| Log.d(LOG_TAG, log); |
| } |
| |
| public static ImApp getApplication(Activity activity) { |
| // TODO should this be synchronized? |
| if (sImApp == null) { |
| initialize(activity); |
| } |
| |
| return sImApp; |
| } |
| |
| /** |
| * Initialize performs the manual ImApp instantiation and initialization. When the |
| * ImApp is started first in the process, the ImApp public constructor should be called, |
| * and sImApp initialized. So calling initialize() later should have no effect. However, |
| * if another application runs in the same process and is started first, the ImApp |
| * application object won't be instantiated, and we need to call initialize() manually to |
| * instantiate and initialize it. |
| */ |
| private static void initialize(Activity activity) { |
| // construct the TalkApp manually and call onCreate(). |
| sImApp = new ImApp(); |
| sImApp.mApplicationContext = activity.getApplication(); |
| sImApp.mPrivateResources = activity.getResources(); |
| sImApp.onCreate(); |
| } |
| |
| @Override |
| public Resources getResources() { |
| if (mApplicationContext == this) { |
| return super.getResources(); |
| } |
| |
| return mPrivateResources; |
| } |
| |
| @Override |
| public ContentResolver getContentResolver() { |
| if (mApplicationContext == this) { |
| return super.getContentResolver(); |
| } |
| |
| return mApplicationContext.getContentResolver(); |
| } |
| |
| public ImApp() { |
| super(); |
| mConnections = new HashMap<Long, IImConnection>(); |
| mApplicationContext = this; |
| sImApp = this; |
| } |
| |
| @Override |
| public void onCreate() { |
| super.onCreate(); |
| mBroadcaster = new Broadcaster(); |
| loadDefaultBrandingRes(); |
| } |
| |
| @Override |
| public void onTerminate() { |
| stopImServiceIfInactive(); |
| if (mImService != null) { |
| try { |
| mImService.removeConnectionCreatedListener(mConnCreationListener); |
| } catch (RemoteException e) { |
| Log.w(LOG_TAG, "failed to remove ConnectionCreatedListener"); |
| } |
| } |
| |
| super.onTerminate(); |
| } |
| |
| public synchronized void startImServiceIfNeed() { |
| if(!mServiceStarted) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("start ImService"); |
| |
| Intent serviceIntent = new Intent(); |
| serviceIntent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT); |
| mApplicationContext.startService(serviceIntent); |
| mApplicationContext.bindService(serviceIntent, mImServiceConn, Context.BIND_AUTO_CREATE); |
| mServiceStarted = true; |
| |
| mConnectionListener = new MyConnListener(new Handler()); |
| } |
| } |
| |
| public synchronized void stopImServiceIfInactive() { |
| boolean hasActiveConnection = true; |
| synchronized (mConnections) { |
| hasActiveConnection = !mConnections.isEmpty(); |
| } |
| |
| if (!hasActiveConnection && mServiceStarted) { |
| if (Log.isLoggable(LOG_TAG, Log.DEBUG)) |
| log("stop ImService because there's no active connections"); |
| |
| if(mImService != null) { |
| mApplicationContext.unbindService(mImServiceConn); |
| mImService = null; |
| } |
| Intent intent = new Intent(); |
| intent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT); |
| mApplicationContext.stopService(intent); |
| mServiceStarted = false; |
| } |
| } |
| |
| private ServiceConnection mImServiceConn = new ServiceConnection() { |
| public void onServiceConnected(ComponentName className, IBinder service) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)) |
| log("service connected"); |
| |
| mImService = IRemoteImService.Stub.asInterface(service); |
| fetchActiveConnections(); |
| |
| synchronized (mQueue) { |
| for (Message msg : mQueue) { |
| msg.sendToTarget(); |
| } |
| mQueue.clear(); |
| } |
| Message msg = Message.obtain(null, EVENT_SERVICE_CONNECTED); |
| mBroadcaster.broadcast(msg); |
| } |
| |
| public void onServiceDisconnected(ComponentName className) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)) |
| log("service disconnected"); |
| |
| mConnections.clear(); |
| mImService = null; |
| } |
| }; |
| |
| public boolean serviceConnected() { |
| return mImService != null; |
| } |
| |
| public boolean isBackgroundDataEnabled() { |
| ConnectivityManager manager = |
| (ConnectivityManager) mApplicationContext.getSystemService(CONNECTIVITY_SERVICE); |
| return manager.getBackgroundDataSetting(); |
| } |
| |
| public static long insertOrUpdateAccount(ContentResolver cr, |
| long providerId, String userName, String pw) { |
| String selection = Imps.Account.PROVIDER + "=? AND " + Imps.Account.USERNAME + "=?"; |
| String[] selectionArgs = {Long.toString(providerId), userName }; |
| |
| Cursor c = cr.query(Imps.Account.CONTENT_URI, ACCOUNT_PROJECTION, |
| selection, selectionArgs, null); |
| if (c != null && c.moveToFirst()) { |
| // Update the password |
| c.updateString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD), pw); |
| c.commitUpdates(); |
| |
| long id = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID)); |
| c.close(); |
| return id; |
| } else { |
| ContentValues values = new ContentValues(4); |
| values.put(Imps.Account.PROVIDER, providerId); |
| values.put(Imps.Account.NAME, userName); |
| values.put(Imps.Account.USERNAME, userName); |
| values.put(Imps.Account.PASSWORD, pw); |
| |
| Uri result = cr.insert(Imps.Account.CONTENT_URI, values); |
| return ContentUris.parseId(result); |
| } |
| } |
| |
| private void loadImProviderSettings() { |
| if (mProviders != null) { |
| return; |
| } |
| |
| mProviders = new HashMap<Long, ProviderDef>(); |
| ContentResolver cr = getContentResolver(); |
| |
| String selectionArgs[] = new String[1]; |
| selectionArgs[0] = ImApp.IMPS_CATEGORY; |
| |
| Cursor c = cr.query(Imps.Provider.CONTENT_URI, PROVIDER_PROJECTION, |
| Imps.Provider.CATEGORY+"=?", selectionArgs, null); |
| if (c == null) { |
| return; |
| } |
| |
| try { |
| while (c.moveToNext()) { |
| long id = c.getLong(0); |
| String providerName = c.getString(1); |
| String fullName = c.getString(2); |
| String signUpUrl = c.getString(3); |
| |
| mProviders.put(id, new ProviderDef(id, providerName, fullName, signUpUrl)); |
| } |
| } finally { |
| c.close(); |
| } |
| } |
| |
| private void loadDefaultBrandingRes() { |
| HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>(); |
| |
| resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.imlogo_s); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE, |
| android.R.drawable.presence_online); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY, |
| android.R.drawable.presence_away); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY, |
| android.R.drawable.presence_busy); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE, |
| android.R.drawable.presence_invisible); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE, |
| android.R.drawable.presence_offline); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_READ_CHAT, |
| R.drawable.status_chat); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_UNREAD_CHAT, |
| R.drawable.status_chat_new); |
| resMapping.put(BrandingResourceIDs.DRAWABLE_BLOCK, |
| R.drawable.ic_im_block); |
| |
| resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES, |
| R.array.default_smiley_names); |
| resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS, |
| R.array.default_smiley_texts); |
| |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AVAILABLE, |
| R.string.presence_available); |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_BUSY, |
| R.string.presence_busy); |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AWAY, |
| R.string.presence_away); |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_IDLE, |
| R.string.presence_idle); |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_OFFLINE, |
| R.string.presence_offline); |
| resMapping.put(BrandingResourceIDs.STRING_PRESENCE_INVISIBLE, |
| R.string.presence_invisible); |
| resMapping.put(BrandingResourceIDs.STRING_LABEL_USERNAME, |
| R.string.label_username); |
| resMapping.put(BrandingResourceIDs.STRING_ONGOING_CONVERSATION, |
| R.string.ongoing_conversation); |
| resMapping.put(BrandingResourceIDs.STRING_ADD_CONTACT_TITLE, |
| R.string.add_contact_title); |
| resMapping.put(BrandingResourceIDs.STRING_LABEL_INPUT_CONTACT, |
| R.string.input_contact_label); |
| resMapping.put(BrandingResourceIDs.STRING_BUTTON_ADD_CONTACT, |
| R.string.invite_label); |
| resMapping.put(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE, |
| R.string.contact_profile_title); |
| |
| resMapping.put(BrandingResourceIDs.STRING_MENU_ADD_CONTACT, |
| R.string.menu_add_contact); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT, |
| R.string.menu_block_contact); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST, |
| R.string.menu_view_contact_list); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT, |
| R.string.menu_remove_contact); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_END_CHAT, |
| R.string.menu_end_conversation); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY, |
| R.string.menu_insert_smiley); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_START_CHAT, |
| R.string.menu_start_chat); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE, |
| R.string.menu_view_profile); |
| resMapping.put(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS, |
| R.string.menu_switch_chats); |
| |
| resMapping.put(BrandingResourceIDs.STRING_TOAST_CHECK_AUTO_SIGN_IN, |
| R.string.check_auto_sign_in); |
| resMapping.put(BrandingResourceIDs.STRING_LABEL_SIGN_UP, |
| R.string.sign_up); |
| |
| mDefaultBrandingResources = new BrandingResources(this, resMapping, |
| null /* default res */); |
| } |
| |
| private void loadThirdPartyResources() { |
| ImPluginHelper helper = ImPluginHelper.getInstance(this); |
| helper.loadAvaiablePlugins(); |
| ArrayList<ImPlugin> pluginList = helper.getPluginObjects(); |
| ArrayList<ImPluginInfo> infoList = helper.getPluginsInfo(); |
| int N = pluginList.size(); |
| PackageManager pm = getPackageManager(); |
| for (int i = 0; i < N; i++) { |
| ImPlugin plugin = pluginList.get(i); |
| ImPluginInfo pluginInfo = infoList.get(i); |
| |
| try { |
| Resources packageRes = pm.getResourcesForApplication(pluginInfo.mPackageName); |
| |
| Map<Integer, Integer> resMap = plugin.getResourceMap(); |
| int[] smileyIcons = plugin.getSmileyIconIds(); |
| |
| BrandingResources res = new BrandingResources(packageRes, resMap, |
| smileyIcons, mDefaultBrandingResources); |
| mBrandingResources.put(pluginInfo.mProviderName, res); |
| } catch (NameNotFoundException e) { |
| Log.e(LOG_TAG, "Failed to load third party resources.", e); |
| } |
| } |
| } |
| |
| public long getProviderId(String name) { |
| loadImProviderSettings(); |
| for (ProviderDef provider: mProviders.values()) { |
| if(provider.mName.equals(name)) { |
| return provider.mId; |
| } |
| } |
| return -1; |
| } |
| |
| public ProviderDef getProvider(long id) { |
| loadImProviderSettings(); |
| return mProviders.get(id); |
| } |
| |
| public List<ProviderDef> getProviders() { |
| loadImProviderSettings(); |
| ArrayList<ProviderDef> result = new ArrayList<ProviderDef>(); |
| result.addAll(mProviders.values()); |
| return result; |
| } |
| |
| public BrandingResources getBrandingResource(long providerId) { |
| ProviderDef provider = getProvider(providerId); |
| if (provider == null) { |
| return mDefaultBrandingResources; |
| } |
| if (mBrandingResources == null) { |
| mBrandingResources = new HashMap<String, BrandingResources>(); |
| loadThirdPartyResources(); |
| } |
| BrandingResources res = mBrandingResources.get(provider.mName); |
| return res == null ? mDefaultBrandingResources : res; |
| } |
| |
| public IImConnection createConnection(long providerId) throws RemoteException { |
| if (mImService == null) { |
| // Service hasn't been connected or has died. |
| return null; |
| } |
| IImConnection conn = getConnection(providerId); |
| if (conn == null) { |
| conn = mImService.createConnection(providerId); |
| } |
| return conn; |
| } |
| |
| IImConnection getConnection(long providerId) { |
| synchronized (mConnections) { |
| return mConnections.get(providerId); |
| } |
| } |
| |
| public IImConnection getConnectionByAccount(long accountId) { |
| synchronized (mConnections) { |
| for (IImConnection conn : mConnections.values()) { |
| try { |
| if (conn.getAccountId() == accountId) { |
| return conn; |
| } |
| } catch (RemoteException e) { |
| // No server! |
| } |
| } |
| return null; |
| } |
| } |
| |
| public List<IImConnection> getActiveConnections() { |
| synchronized (mConnections) { |
| ArrayList<IImConnection> result = new ArrayList<IImConnection>(); |
| result.addAll(mConnections.values()); |
| return result; |
| } |
| } |
| |
| public void callWhenServiceConnected(Handler target, Runnable callback) { |
| Message msg = Message.obtain(target, callback); |
| if (serviceConnected()) { |
| msg.sendToTarget(); |
| } else { |
| startImServiceIfNeed(); |
| synchronized (mQueue) { |
| mQueue.add(msg); |
| } |
| } |
| } |
| |
| public void removePendingCall(Handler target) { |
| synchronized (mQueue) { |
| Iterator<Message> iter = mQueue.iterator(); |
| while (iter.hasNext()) { |
| Message msg = iter.next(); |
| if (msg.getTarget() == target) { |
| iter.remove(); |
| } |
| } |
| } |
| } |
| |
| public void registerForBroadcastEvent(int what, Handler target) { |
| mBroadcaster.request(what, target, what); |
| } |
| |
| public void unregisterForBroadcastEvent(int what, Handler target) { |
| mBroadcaster.cancelRequest(what, target, what); |
| } |
| |
| public void registerForConnEvents(Handler handler) { |
| mBroadcaster.request(EVENT_CONNECTION_CREATED, handler, |
| EVENT_CONNECTION_CREATED); |
| mBroadcaster.request(EVENT_CONNECTION_LOGGING_IN, handler, |
| EVENT_CONNECTION_LOGGING_IN); |
| mBroadcaster.request(EVENT_CONNECTION_LOGGED_IN, handler, |
| EVENT_CONNECTION_LOGGED_IN); |
| mBroadcaster.request(EVENT_CONNECTION_LOGGING_OUT, handler, |
| EVENT_CONNECTION_LOGGING_OUT); |
| mBroadcaster.request(EVENT_CONNECTION_SUSPENDED, handler, |
| EVENT_CONNECTION_SUSPENDED); |
| mBroadcaster.request(EVENT_CONNECTION_DISCONNECTED, handler, |
| EVENT_CONNECTION_DISCONNECTED); |
| mBroadcaster.request(EVENT_USER_PRESENCE_UPDATED, handler, |
| EVENT_USER_PRESENCE_UPDATED); |
| mBroadcaster.request(EVENT_UPDATE_USER_PRESENCE_ERROR, handler, |
| EVENT_UPDATE_USER_PRESENCE_ERROR); |
| } |
| |
| public void unregisterForConnEvents(Handler handler) { |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_CREATED, handler, |
| EVENT_CONNECTION_CREATED); |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_IN, handler, |
| EVENT_CONNECTION_LOGGING_IN); |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGED_IN, handler, |
| EVENT_CONNECTION_LOGGED_IN); |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_OUT, handler, |
| EVENT_CONNECTION_LOGGING_OUT); |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_SUSPENDED, handler, |
| EVENT_CONNECTION_SUSPENDED); |
| mBroadcaster.cancelRequest(EVENT_CONNECTION_DISCONNECTED, handler, |
| EVENT_CONNECTION_DISCONNECTED); |
| mBroadcaster.cancelRequest(EVENT_USER_PRESENCE_UPDATED, handler, |
| EVENT_USER_PRESENCE_UPDATED); |
| mBroadcaster.cancelRequest(EVENT_UPDATE_USER_PRESENCE_ERROR, handler, |
| EVENT_UPDATE_USER_PRESENCE_ERROR); |
| } |
| |
| void broadcastConnEvent(int what, long providerId, ImErrorInfo error) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)){ |
| log("broadcasting connection event " + what + ", provider id " + providerId); |
| } |
| android.os.Message msg = android.os.Message.obtain( |
| null, |
| what, |
| (int)(providerId >> 32), (int)providerId, |
| error); |
| mBroadcaster.broadcast(msg); |
| } |
| |
| public void dismissNotifications(long providerId) { |
| if (mImService != null) { |
| try { |
| mImService.dismissNotifications(providerId); |
| } catch (RemoteException e) { |
| } |
| } |
| } |
| |
| public void dismissChatNotification(long providerId, String username) { |
| if (mImService != null) { |
| try { |
| mImService.dismissChatNotification(providerId, username); |
| } catch (RemoteException e) { |
| } |
| } |
| } |
| |
| private void fetchActiveConnections() { |
| try { |
| // register the listener before fetch so that we won't miss any connection. |
| mImService.addConnectionCreatedListener(mConnCreationListener); |
| synchronized (mConnections) { |
| for(IBinder binder: (List<IBinder>) mImService.getActiveConnections()) { |
| IImConnection conn = IImConnection.Stub.asInterface(binder); |
| long providerId = conn.getProviderId(); |
| if (!mConnections.containsKey(providerId)) { |
| mConnections.put(providerId, conn); |
| conn.registerConnectionListener(mConnectionListener); |
| } |
| } |
| } |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "fetching active connections", e); |
| } |
| } |
| |
| private final IConnectionCreationListener mConnCreationListener |
| = new IConnectionCreationListener.Stub() { |
| public void onConnectionCreated(IImConnection conn) |
| throws RemoteException { |
| long providerId = conn.getProviderId(); |
| synchronized (mConnections) { |
| if (!mConnections.containsKey(providerId)) { |
| mConnections.put(providerId, conn); |
| conn.registerConnectionListener(mConnectionListener); |
| } |
| } |
| broadcastConnEvent(EVENT_CONNECTION_CREATED, providerId, null); |
| } |
| }; |
| |
| private final class MyConnListener extends ConnectionListenerAdapter { |
| public MyConnListener(Handler handler) { |
| super(handler); |
| } |
| |
| @Override |
| public void onConnectionStateChange(IImConnection conn, int state, |
| ImErrorInfo error) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)){ |
| log("onConnectionStateChange(" + state + ", " + error + ")"); |
| } |
| |
| try { |
| int what = -1; |
| long providerId = conn.getProviderId(); |
| switch (state) { |
| case ImConnection.LOGGED_IN: |
| what = EVENT_CONNECTION_LOGGED_IN; |
| break; |
| |
| case ImConnection.LOGGING_IN: |
| what = EVENT_CONNECTION_LOGGING_IN; |
| break; |
| |
| case ImConnection.LOGGING_OUT: |
| what = EVENT_CONNECTION_LOGGING_OUT; |
| synchronized (mConnections) { |
| mConnections.remove(providerId); |
| } |
| break; |
| |
| case ImConnection.DISCONNECTED: |
| what = EVENT_CONNECTION_DISCONNECTED; |
| synchronized (mConnections) { |
| mConnections.remove(providerId); |
| } |
| // stop the service if there isn't an active connection anymore. |
| stopImServiceIfInactive(); |
| break; |
| |
| case ImConnection.SUSPENDED: |
| what = EVENT_CONNECTION_SUSPENDED; |
| break; |
| } |
| if (what != -1) { |
| broadcastConnEvent(what, providerId, error); |
| } |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "onConnectionStateChange", e); |
| } |
| } |
| |
| @Override |
| public void onUpdateSelfPresenceError(IImConnection connection, |
| ImErrorInfo error) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)){ |
| log("onUpdateUserPresenceError(" + error + ")"); |
| } |
| try { |
| long providerId = connection.getProviderId(); |
| broadcastConnEvent(EVENT_UPDATE_USER_PRESENCE_ERROR, providerId, |
| error); |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "onUpdateUserPresenceError", e); |
| } |
| } |
| |
| @Override |
| public void onSelfPresenceUpdated(IImConnection connection) { |
| if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("onUserPresenceUpdated"); |
| |
| try { |
| long providerId = connection.getProviderId(); |
| broadcastConnEvent(EVENT_USER_PRESENCE_UPDATED, providerId, |
| null); |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "onUserPresenceUpdated", e); |
| } |
| } |
| } |
| } |