📄 remoteimservice.java
字号:
/* * 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.service;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Vector;import android.app.AlarmManager;import android.app.PendingIntent;import android.app.Service;import android.content.ContentResolver;import android.content.ContentUris;import android.content.ContentValues;import android.content.Intent;import android.content.pm.PackageManager;import android.content.pm.ResolveInfo;import android.content.pm.ServiceInfo;import android.database.Cursor;import android.net.ConnectivityManager;import android.net.NetworkConnectivityListener;import android.net.Uri;import android.net.NetworkConnectivityListener.State;import android.net.NetworkInfo;import android.os.Bundle;import android.os.RemoteException;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.SystemClock;import android.os.SystemProperties;import android.provider.Im;import android.telephony.TelephonyManager;import android.text.TextUtils;import android.util.Log;import android.widget.Toast;import com.android.im.IConnectionCreationListener;import com.android.im.IImConnection;import com.android.im.IRemoteImService;import com.android.im.engine.ConnectionFactory;import com.android.im.engine.ImConnection;import com.android.im.engine.ImException;import com.android.im.imps.ImpsConnectionConfig;import com.android.im.imps.TcpCirAlarmService;import com.android.im.imps.ImpsConnectionConfig.CirMethod;import com.android.im.plugin.IImPlugin;import com.android.im.plugin.ImConfigNames;import com.android.im.plugin.ImPluginConstants;import com.android.im.plugin.ImPluginInfo;import com.android.im.plugin.ImpsConfigNames;import dalvik.system.PathClassLoader;public class RemoteImService extends Service { private static final String[] ACCOUNT_PROJECTION = { Im.Account._ID, Im.Account.PROVIDER, Im.Account.USERNAME, Im.Account.PASSWORD, }; private static final int ACCOUNT_ID_COLUMN = 0; private static final int ACCOUNT_PROVIDER_COLUMN = 1; private static final int ACCOUNT_USERNAME_COLUMN = 2; private static final int ACCOUNT_PASSOWRD_COLUMN = 3; static final String TAG = "ImService"; private static final int EVENT_SHOW_TOAST = 100; private static final int EVENT_NETWORK_STATE_CHANGED = 200; private StatusBarNotifier mStatusBarNotifier; private Handler mServiceHandler; NetworkConnectivityListener mNetworkConnectivityListener; private int mNetworkType; private boolean mNeedCheckAutoLogin; Vector<ImConnectionAdapter> mConnections; private PendingIntent mTcpCirAlarmSender; private HashMap<Long, ImPluginInfo> mPlugins; public RemoteImService() { mConnections = new Vector<ImConnectionAdapter>(); mPlugins = new HashMap<Long, ImPluginInfo>(); } @Override public void onCreate() { Log.d(TAG, "ImService started"); mStatusBarNotifier = new StatusBarNotifier(this); mServiceHandler = new ServiceHandler(); mNetworkConnectivityListener = new NetworkConnectivityListener(); mNetworkConnectivityListener.registerHandler(mServiceHandler, EVENT_NETWORK_STATE_CHANGED); mNetworkConnectivityListener.startListening(this); findAvaiablePlugins(); } private void findAvaiablePlugins() { PackageManager pm = getPackageManager(); List<ResolveInfo> plugins = pm.queryIntentServices( new Intent(ImPluginConstants.PLUGIN_ACTION_NAME), PackageManager.GET_META_DATA); for (ResolveInfo info : plugins) { Log.d(TAG, "Found plugin " + info); ServiceInfo serviceInfo = info.serviceInfo; if (serviceInfo == null) { Log.e(TAG, "Ignore bad IM plugin: " + info); continue; } String providerName = null; String providerFullName = null; String signUpUrl = null; Bundle metaData = serviceInfo.metaData; if (metaData != null) { providerName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_NAME); providerFullName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME); signUpUrl = metaData.getString(ImPluginConstants.METADATA_SIGN_UP_URL); } if (TextUtils.isEmpty(providerName) || TextUtils.isEmpty(providerFullName)) { Log.e(TAG, "Ignore bad IM plugin: " + info + ". Lack of required meta data"); continue; } ImPluginInfo pluginInfo = new ImPluginInfo(providerName, serviceInfo.packageName, serviceInfo.name, serviceInfo.applicationInfo.sourceDir); Map<String, String> config = loadProviderConfigFromPlugin(pluginInfo); if (config == null) { Log.e(TAG, "Ignore bad IM plugin"); break; } config.put(ImConfigNames.PLUGIN_PATH, pluginInfo.mSrcPath); config.put(ImConfigNames.PLUGIN_CLASS, pluginInfo.mClassName); long providerId = updateProviderDb(providerName, providerFullName, signUpUrl, config); mPlugins.put(providerId, pluginInfo); } } private Map<String, String> loadProviderConfigFromPlugin(ImPluginInfo pluginInfo) { // XXX Load the plug-in implementation directly from the apk rather than // binding to the service and call through IPC Binder API. This is much // more effective since we don't need to start the service in other // process. We can not run the plug-in service in the same process as a // local service because that the interface is defined in a shared // library in order to compile the plug-in separately. In this case, the // interface will be loaded by two class loader separately and a // ClassCastException will be thrown if we cast the binder to the // interface. PathClassLoader loader = new PathClassLoader(pluginInfo.mSrcPath, getClassLoader()); try { Class cls = loader.loadClass(pluginInfo.mClassName); Method m = cls.getMethod("onBind", Intent.class); IImPlugin plugin = (IImPlugin)m.invoke(cls.newInstance(), new Object[]{null}); return plugin.getProviderConfig(); } catch (ClassNotFoundException e) { Log.e(TAG, "Could not find plugin class", e); } catch (IllegalAccessException e) { Log.e(TAG, "Could not create plugin instance", e); } catch (InstantiationException e) { Log.e(TAG, "Could not create plugin instance", e); } catch (SecurityException e) { Log.e(TAG, "Could not load config from the plugin", e); } catch (NoSuchMethodException e) { Log.e(TAG, "Could not load config from the plugin", e); } catch (IllegalArgumentException e) { Log.e(TAG, "Could not load config from the plugin", e); } catch (InvocationTargetException e) { Log.e(TAG, "Could not load config from the plugin", e); } catch (RemoteException e) { Log.e(TAG, "Could not load config from the plugin", e); } return null; } private long updateProviderDb(String providerName, String providerFullName, String signUpUrl, Map<String, String> config) { long providerId; ContentResolver cr = getContentResolver(); String where = Im.Provider.NAME + "=?"; String[] selectionArgs = new String[]{providerName}; Cursor c = cr.query(Im.Provider.CONTENT_URI, null, where, selectionArgs, null); if (c == null) { return -1; } if (c.moveToFirst()) { providerId = c.getLong(c.getColumnIndexOrThrow(Im.Provider._ID)); } else { ContentValues values = new ContentValues(3); values.put(Im.Provider.NAME, providerName); values.put(Im.Provider.FULLNAME, providerFullName); values.put(Im.Provider.SIGNUP_URL, signUpUrl); Uri result = cr.insert(Im.Provider.CONTENT_URI, values); providerId = ContentUris.parseId(result); ContentValues[] settingValues = new ContentValues[config.size()]; int index = 0; for (Map.Entry<String, String> entry : config.entrySet()) { ContentValues settingValue = new ContentValues(); settingValue.put(Im.ProviderSettings.PROVIDER, providerId); settingValue.put(Im.ProviderSettings.NAME, entry.getKey()); settingValue.put(Im.ProviderSettings.VALUE, entry.getValue()); settingValues[index++] = settingValue; } cr.bulkInsert(Im.ProviderSettings.CONTENT_URI, settingValues); } c.close(); return providerId; } public void startTcpCirAlarm() { if (mTcpCirAlarmSender != null) { return; } mTcpCirAlarmSender = PendingIntent.getService(this, 0, new Intent(this, TcpCirAlarmService.class), 0); long firstTime = SystemClock.elapsedRealtime(); AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, TcpCirAlarmService.INTERVAL, mTcpCirAlarmSender); } public void stopTcpCirAlarm() { if (mTcpCirAlarmSender != null) { AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); am.cancel(mTcpCirAlarmSender); mTcpCirAlarmSender = null; } } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); mNeedCheckAutoLogin = intent.getBooleanExtra(ImServiceConstants.EXTRA_CHECK_AUTO_LOGIN, false); Log.d(TAG, "ImService.onStart, checkAutoLogin=" + mNeedCheckAutoLogin); // Check and login accounts if network is ready, otherwise it's checked // when the network becomes available. if (mNeedCheckAutoLogin && mNetworkConnectivityListener.getState() == State.CONNECTED) { mNeedCheckAutoLogin = false; autoLogin();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -