标签:
android\frameworks\base\services\java\com\android\server\InputMethodManagerService.java public InputMethodManagerService(Context context, WindowManagerService windowManager) { ....... //构建IME通知栏显示信息 mImeSwitcherNotification = new Notification(); mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default; mImeSwitcherNotification.when = 0; mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT; mImeSwitcherNotification.tickerText = null; mImeSwitcherNotification.defaults = 0; // please be quiet mImeSwitcherNotification.sound = null; mImeSwitcherNotification.vibrate = null; // Tag this notification specially so SystemUI knows it‘s important mImeSwitcherNotification.kind = new String[] { "android.system.imeswitcher" }; //此Intent弹出选择输入法的Dialog Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER); mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); ...... //监听灭屏,亮屏 final IntentFilter broadcastFilter = new IntentFilter(); broadcastFilter.addAction(Intent.ACTION_SCREEN_ON); broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF); broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter); ...... //监听APK安装,卸载,不可用/可用,等变动 mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true); ...... //获取系统中输入法列表 mSettings = new InputMethodSettings( mRes, context.getContentResolver(), mMethodMap, mMethodList, userId); ...... final String defaultImiId = mSettings.getSelectedInputMethod(); if (DEBUG) { Slog.d(TAG, "Initial default ime = " + defaultImiId); } mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId); buildInputMethodListLocked(mMethodList, mMethodMap, !mImeSelectedOnBoot /* resetDefaultEnabledIme */); mSettings.enableAllIMEsIfThereIsNoEnabledIME(); //监听Settings数据库 mSettingsObserver = new SettingsObserver(mHandler); ...... //监听系统语言变化 final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_LOCALE_CHANGED); mContext.registerReceiver( new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized(mMethodMap) { resetStateIfCurrentLocaleChangedLocked(); } } },
filter); }
主要看一下对APK安装/卸载,不可用/可用,等变动的监听。
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); class MyPackageMonitor extends PackageMonitor { ...... @Override public void onSomePackagesChanged() { ...... //判断输入法APK安装,卸载,然后更新IME int change = isPackageDisappearing(imi.getPackageName()); if (isPackageModified(imi.getPackageName())) { mFileManager.deleteAllInputMethodSubtypes(imiId); } if (change == PACKAGE_TEMPORARY_CHANGE || change == PACKAGE_PERMANENT_CHANGE) { Slog.i(TAG, "Input method uninstalled, disabling: " + imi.getComponent()); setInputMethodEnabledLocked(imi.getId(), false); } ...... } }
PackageMonitor是系统源码中监听APP变动的现成代码。可以拿来直接用,贴上完整源码。
android\frameworks\base\core\java\com\android\internal\content\PackageMonitor.java package com.android.internal.content; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.UserHandle; import com.android.internal.os.BackgroundThread; import java.util.HashSet; /** * Helper class for monitoring the state of packages: adding, removing, * updating, and disappearing and reappearing on the SD card. */ public abstract class PackageMonitor extends android.content.BroadcastReceiver { static final IntentFilter sPackageFilt = new IntentFilter(); static final IntentFilter sNonDataFilt = new IntentFilter(); static final IntentFilter sExternalFilt = new IntentFilter(); static { sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); sPackageFilt.addAction(Intent.ACTION_UID_REMOVED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); } final HashSet<String> mUpdatingPackages = new HashSet<String>(); Context mRegisteredContext; Handler mRegisteredHandler; String[] mDisappearingPackages; String[] mAppearingPackages; String[] mModifiedPackages; int mChangeType; int mChangeUserId = UserHandle.USER_NULL; boolean mSomePackagesChanged; String[] mTempArray = new String[1]; public void register(Context context, Looper thread, boolean externalStorage) { register(context, thread, null, externalStorage); } public void register(Context context, Looper thread, UserHandle user, boolean externalStorage) { if (mRegisteredContext != null) { throw new IllegalStateException("Already registered"); } mRegisteredContext = context; if (thread == null) { mRegisteredHandler = BackgroundThread.getHandler(); } else { mRegisteredHandler = new Handler(thread); } if (user != null) { context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler); context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler); if (externalStorage) { context.registerReceiverAsUser(this, user, sExternalFilt, null, mRegisteredHandler); } } else { context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler); context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler); if (externalStorage) { context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler); } } } public Handler getRegisteredHandler() { return mRegisteredHandler; } public void unregister() { if (mRegisteredContext == null) { throw new IllegalStateException("Not registered"); } mRegisteredContext.unregisterReceiver(this); mRegisteredContext = null; } //not yet implemented boolean isPackageUpdating(String packageName) { synchronized (mUpdatingPackages) { return mUpdatingPackages.contains(packageName); } } public void onBeginPackageChanges() { } /** * Called when a package is really added (and not replaced). */ public void onPackageAdded(String packageName, int uid) { } /** * Called when a package is really removed (and not replaced). */ public void onPackageRemoved(String packageName, int uid) { } /** * Called when a package is really removed (and not replaced) for * all users on the device. */ public void onPackageRemovedAllUsers(String packageName, int uid) { } public void onPackageUpdateStarted(String packageName, int uid) { } public void onPackageUpdateFinished(String packageName, int uid) { } /** * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED * Intent.ACTION_PACKAGE_CHANGED} being received, informing you of * changes to the enabled/disabled state of components in a package * and/or of the overall package. * * @param packageName The name of the package that is changing. * @param uid The user ID the package runs under. * @param components Any components in the package that are changing. If * the overall package is changing, this will contain an entry of the * package name itself. * @return Return true to indicate you care about this change, which will * result in {@link #onSomePackagesChanged()} being called later. If you * return false, no further callbacks will happen about this change. The * default implementation returns true if this is a change to the entire * package. */ public boolean onPackageChanged(String packageName, int uid, String[] components) { if (components != null) { for (String name : components) { if (packageName.equals(name)) { return true; } } } return false; } public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { return false; } public void onHandleUserStop(Intent intent, int userHandle) { } public void onUidRemoved(int uid) { } public void onPackagesAvailable(String[] packages) { } public void onPackagesUnavailable(String[] packages) { } public static final int PACKAGE_UNCHANGED = 0; public static final int PACKAGE_UPDATING = 1; public static final int PACKAGE_TEMPORARY_CHANGE = 2; public static final int PACKAGE_PERMANENT_CHANGE = 3; /** * Called when a package disappears for any reason. */ public void onPackageDisappeared(String packageName, int reason) { } /** * Called when a package appears for any reason. */ public void onPackageAppeared(String packageName, int reason) { } /** * Called when an existing package is updated or its disabled state changes. */ public void onPackageModified(String packageName) { } public boolean didSomePackagesChange() { return mSomePackagesChanged; } public int isPackageAppearing(String packageName) { if (mAppearingPackages != null) { for (int i=mAppearingPackages.length-1; i>=0; i--) { if (packageName.equals(mAppearingPackages[i])) { return mChangeType; } } } return PACKAGE_UNCHANGED; } public boolean anyPackagesAppearing() { return mAppearingPackages != null; } public int isPackageDisappearing(String packageName) { if (mDisappearingPackages != null) { for (int i=mDisappearingPackages.length-1; i>=0; i--) { if (packageName.equals(mDisappearingPackages[i])) { return mChangeType; } } } return PACKAGE_UNCHANGED; } public boolean anyPackagesDisappearing() { return mDisappearingPackages != null; } public boolean isPackageModified(String packageName) { if (mModifiedPackages != null) { for (int i=mModifiedPackages.length-1; i>=0; i--) { if (packageName.equals(mModifiedPackages[i])) { return true; } } } return false; } public void onSomePackagesChanged() { } public void onFinishPackageChanges() { } public int getChangingUserId() { return mChangeUserId; } String getPackageName(Intent intent) { Uri uri = intent.getData(); String pkg = uri != null ? uri.getSchemeSpecificPart() : null; return pkg; } @Override public void onReceive(Context context, Intent intent) { mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (mChangeUserId == UserHandle.USER_NULL) { throw new IllegalArgumentException( "Intent broadcast does not contain user handle: " + intent); } onBeginPackageChanges(); mDisappearingPackages = mAppearingPackages = null; mSomePackagesChanged = false; String action = intent.getAction(); if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); // We consider something to have changed regardless of whether // this is just an update, because the update is now finished // and the contents of the package may have changed. mSomePackagesChanged = true; if (pkg != null) { mAppearingPackages = mTempArray; mTempArray[0] = pkg; if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { mModifiedPackages = mTempArray; mChangeType = PACKAGE_UPDATING; onPackageUpdateFinished(pkg, uid); onPackageModified(pkg); } else { mChangeType = PACKAGE_PERMANENT_CHANGE; onPackageAdded(pkg, uid); } onPackageAppeared(pkg, mChangeType); if (mChangeType == PACKAGE_UPDATING) { synchronized (mUpdatingPackages) { mUpdatingPackages.remove(pkg); } } } } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); if (pkg != null) { mDisappearingPackages = mTempArray; mTempArray[0] = pkg; if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { mChangeType = PACKAGE_UPDATING; synchronized (mUpdatingPackages) { //not used for now //mUpdatingPackages.add(pkg); } onPackageUpdateStarted(pkg, uid); } else { mChangeType = PACKAGE_PERMANENT_CHANGE; // We only consider something to have changed if this is // not a replace; for a replace, we just need to consider // it when it is re-added. mSomePackagesChanged = true; onPackageRemoved(pkg, uid); if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) { onPackageRemovedAllUsers(pkg, uid); } } onPackageDisappeared(pkg, mChangeType); } } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { String pkg = getPackageName(intent); int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); String[] components = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); if (pkg != null) { mModifiedPackages = mTempArray; mTempArray[0] = pkg; mChangeType = PACKAGE_PERMANENT_CHANGE; if (onPackageChanged(pkg, uid, components)) { mSomePackagesChanged = true; } onPackageModified(pkg); } } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { mDisappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); mChangeType = PACKAGE_TEMPORARY_CHANGE; boolean canRestart = onHandleForceStop(intent, mDisappearingPackages, intent.getIntExtra(Intent.EXTRA_UID, 0), false); if (canRestart) setResultCode(Activity.RESULT_OK); } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { mDisappearingPackages = new String[] {getPackageName(intent)}; mChangeType = PACKAGE_TEMPORARY_CHANGE; onHandleForceStop(intent, mDisappearingPackages, intent.getIntExtra(Intent.EXTRA_UID, 0), true); } else if (Intent.ACTION_UID_REMOVED.equals(action)) { onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID, 0)); } else if (Intent.ACTION_USER_STOPPED.equals(action)) { if (intent.hasExtra(Intent.EXTRA_USER_HANDLE)) { onHandleUserStop(intent, intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); mAppearingPackages = pkgList; mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE; mSomePackagesChanged = true; if (pkgList != null) { onPackagesAvailable(pkgList); for (int i=0; i<pkgList.length; i++) { onPackageAppeared(pkgList[i], mChangeType); } } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); mDisappearingPackages = pkgList; mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE; mSomePackagesChanged = true; if (pkgList != null) { onPackagesUnavailable(pkgList); for (int i=0; i<pkgList.length; i++) { onPackageDisappeared(pkgList[i], mChangeType); } } } if (mSomePackagesChanged) { onSomePackagesChanged(); } onFinishPackageChanges(); mChangeUserId = UserHandle.USER_NULL; } }
在实现监听APK安装,卸载时,可能用不到PackageMonitor中那么详细的处理。
但是要注意
final IntentFilter sPackageFilt = new IntentFilter(); sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); sPackageFilt.addAction(Intent.ACTION_UID_REMOVED); sPackageFilt.addDataScheme("package");//这个是必须要有的,否则监听不到。
如果在AndroidManifest.xml中配置广播监听APK变动
<receiver android:name="MyReceiver" > <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <action android:name="android.intent.action......." /> <action android:name="android.intent.action......." /> <data android:scheme="package" /> <!--注意这行一定要加--> </intent-filter> </receiver>
InputMethodManagerService处理输入法——监听APK变动
标签:
原文地址:http://www.cnblogs.com/antoon/p/4250758.html