zoukankan      html  css  js  c++  java
  • InputMethodManagerService处理输入法——监听APK变动

    androidframeworksbaseservicesjavacomandroidserverInputMethodManagerService.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变动的现成代码。可以拿来直接用,贴上完整源码。

    androidframeworksasecorejavacomandroidinternalcontentPackageMonitor.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;
        }
    }
    View Code

    在实现监听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>          
  • 相关阅读:
    时间及时间戳相互转换
    指针偏移
    C# TreeView模糊查找节点
    Checkedlistbox只能单选不能多选
    获取本机的IP地址
    检测插件是否已注册,注册插件
    知道内存中一个图片的指针IntPtr大小,转换成图片显示
    C# 判断点是否在矩形框内
    C# 从图片中截取一部分图片,并返回所截取的图片
    C# 管道通信 (client —— server)Framework2.0版本也可用
  • 原文地址:https://www.cnblogs.com/antoon/p/4250758.html
Copyright © 2011-2022 走看看