博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 侦听应用(Package)变化的方法侦听广播
阅读量:5809 次
发布时间:2019-06-18

本文共 7592 字,大约阅读时间需要 25 分钟。

应用的状态变化,包括安装、卸载、更新,是android系统上重要的事件。如何侦听到?有两种方法,一是通过侦听广播,一是实现PackageMonitor。
侦听广播
 
当Package状态发生变化时,系统会广播如下一些Action的Intent:
应用安装:
public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
应用更新:
public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
应用的新版本替代旧版本被安装
public static final String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
应用的新版本替代旧版本被安装,只发给被更新的应用自己
public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
应用被改变,譬如某些组件被disable/enable
应用卸载:
public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
应用被卸载时发出,正在被卸载的应用自身不会收到
public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
应用被完全卸载时发出(数据被删除)
 
上述Intent都为保护型,只能够由系统发出。
 
针对上述定义,结合android源代码,研究几个问题。Android对于Package的管理主要逻辑在PackageManagerService(PMS)中,主要在这个类中研究上述问题:
 
(1)系统如何实现只发给某个应用?

ACTION_MY_PACKAGE_REPLACED是如何处理的?

private void sendSystemPackageUpdatedBroadcastsInternal() {    Bundle extras = new Bundle(2);    extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);    extras.putBoolean(Intent.EXTRA_REPLACING, true);    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage,            extras, 0, null, null, null);    sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,            extras, 0, null, null, null);    sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,            null, 0, removedPackage, null, null);}final void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,        final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,        final int[] userIds) {    mHandler.post(new Runnable() {        @Override        public void run() {            try {                final IActivityManager am = ActivityManagerNative.getDefault();                if (am == null) return;                final int[] resolvedUserIds;                if (userIds == null) {                    resolvedUserIds = am.getRunningUserIds();                } else {                    resolvedUserIds = userIds;                }                for (int id : resolvedUserIds) {                    final Intent intent = new Intent(action,                            pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);                    if (extras != null) {                        intent.putExtras(extras);                    }                    if (targetPkg != null) {                        intent.setPackage(targetPkg);                    }                    // Modify the UID when posting to other users                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);                    if (uid > 0 && UserHandle.getUserId(uid) != id) {                        uid = UserHandle.getUid(id, UserHandle.getAppId(uid));                        intent.putExtra(Intent.EXTRA_UID, uid);                    }                    intent.putExtra(Intent.EXTRA_USER_HANDLE, id);                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | flags);                    if (DEBUG_BROADCASTS) {                        RuntimeException here = new RuntimeException("here");                        here.fillInStackTrace();                        Slog.d(TAG, "Sending to user " + id + ": "                                + intent.toShortString(false, true, false, false)                                + " " + intent.getExtras(), here);                    }                    am.broadcastIntent(null, intent, null, finishedReceiver,                            0, null, null, null, android.app.AppOpsManager.OP_NONE,                            null, finishedReceiver != null, false, id);                }            } catch (RemoteException ex) {            }        }    });}
看到在广播ACTION_MY_PACKAGE_REPLACED的时候,是通过Intent.setPackage(String packageName)实现定向发送。
(2)ACTION_PACKAGE_CHANGED在什么场景下使用?

ACTION_PACKAGE_CHANGED在PMS中只有一处使用入口:

private void sendPackageChangedBroadcast(String packageName,        boolean killFlag, ArrayList
componentNames, int packageUid) { if (DEBUG_INSTALL) Log.v(TAG, "Sending package changed: package=" + packageName + " components=" + componentNames); Bundle extras = new Bundle(4); extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0)); String nameList[] = new String[componentNames.size()]; componentNames.toArray(nameList); extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList); extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag); extras.putInt(Intent.EXTRA_UID, packageUid); // If this is not reporting a change of the overall package, then only send it // to registered receivers. We don't want to launch a swath of apps for every // little component state change. final int flags = !componentNames.contains(packageName) ? Intent.FLAG_RECEIVER_REGISTERED_ONLY : 0; sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null, new int[] {UserHandle.getUserId(packageUid)});}
追踪sendPackageChangedBroadcast()的调用,来自setComponentEnabledSetting()。

这是实现PackageManager的对外公开API,看一下PackageManager中对此的定义:

/** * Set the enabled setting for a package component (activity, receiver, service, provider). * This setting will override any enabled state which may have been set by the component in its * manifest. * * @param componentName The component to enable * @param newState The new enabled state for the component.  The legal values for this state *                 are: *                   {@link #COMPONENT_ENABLED_STATE_ENABLED}, *                   {@link #COMPONENT_ENABLED_STATE_DISABLED} *                   and *                   {@link #COMPONENT_ENABLED_STATE_DEFAULT} *                 The last one removes the setting, thereby restoring the component's state to *                 whatever was set in it's manifest (or enabled, by default). * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. */public abstract void setComponentEnabledSetting(ComponentName componentName,        int newState, int flags);

这是PackageManager提供的修改四大控件enable/disable的API,当然调用是需要检查权限的,此处不展开介绍。

(3)ACTION_PACKAGE_REMOVED和ACTION_PACKAGE_FULLY_REMOVED的逻辑关系

查看这两个Action在PMS中的使用,发现只有一处:

private void sendPackageRemovedBroadcastInternal(boolean killApp) {    Bundle extras = new Bundle(2);    extras.putInt(Intent.EXTRA_UID, removedAppId >= 0  ? removedAppId : uid);    extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);    extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);    if (isUpdate || isRemovedPackageSystemUpdate) {        extras.putBoolean(Intent.EXTRA_REPLACING, true);    }    extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);    if (removedPackage != null) {        sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,                extras, 0, null, null, removedUsers);        if (dataRemoved && !isRemovedPackageSystemUpdate) {            sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,                    removedPackage, extras, 0, null, null, removedUsers);        }    }    if (removedAppId >= 0) {        sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null,                removedUsers);    }}

看到Package removed发生时,会发ACTION_PACKAGE_REMOVED;并且只有在数据被删除且非删除系统更新的app时,才会发送ACTION_PACKAGE_FULLY_REMOVED。在PackageManager中有一个flag常量定义PackageManager.DELETE_KEEP_DATA,用以决定在删除app时是否保留数据。

转载地址:http://fwjbx.baihongyu.com/

你可能感兴趣的文章
洛谷 P2015 二叉苹果树(codevs5565) 树形dp入门
查看>>
详解c++多线程(一)
查看>>
Windows Gdi & CDC和HDC的区别与转换
查看>>
EPEL源
查看>>
POJ - 3662 Telephone Lines
查看>>
如何在云服务器创建maven私有仓库
查看>>
委托的来由
查看>>
数据库开启对sys用户的审计
查看>>
sublimetext 自定义build
查看>>
郝小亮-读王坚《在线》:互联网能做的和没做的事还有很多
查看>>
(转)hasLayout与BFC的触发条件
查看>>
Leetcode Longest Substring Without Repeating Characters
查看>>
Java项目 打war包方法
查看>>
Redis在WEB开发中的应用与实践
查看>>
mysql技术内幕InnoDB 第五章
查看>>
2019.4.3 区块链论文翻译
查看>>
学习笔记-dom操作与Virtual Dom
查看>>
spark SQL学习(spark连接 mysql)
查看>>
c博客作业--函数
查看>>
java排序算法之冒泡排序(Bubble Sort)
查看>>