Android 侦听应用(Package)变化的方法侦听广播
侦听广播
应用安装:
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";
应用被完全卸载时发出(数据被删除)
ACTION_MY_PACKAGE_REPLACED是如何处理的?
private void sendSystemPackageUpdatedBroadcastsInternal() {
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, removedAppId >= ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage,
extras, , null, null, null);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
extras, , null, null, null);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
null, , 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, -);
if (uid > && 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,
, null, null, null, android.app.AppOpsManager.OP_NONE,
null, finishedReceiver != null, false, id);
}
} catch (RemoteException ex) {
}
}
});
}
ACTION_PACKAGE_CHANGED在PMS中只有一处使用入口:
private void sendPackageChangedBroadcast(String packageName,
boolean killFlag, ArrayList<String> componentNames, int packageUid) {
if (DEBUG_INSTALL)
Log.v(TAG, "Sending package changed: package=" + packageName + " components="
+ componentNames);
Bundle extras = new Bundle();
extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get());
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 : ;
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
new int[] {UserHandle.getUserId(packageUid)});
}
这是实现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,当然调用是需要检查权限的,此处不展开介绍。
查看这两个Action在PMS中的使用,发现只有一处:
private void sendPackageRemovedBroadcastInternal(boolean killApp) {
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, removedAppId >= ? 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, , null, null, removedUsers);
if (dataRemoved && !isRemovedPackageSystemUpdate) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
removedPackage, extras, , null, null, removedUsers);
}
}
if (removedAppId >= ) {
sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, , null, null,
removedUsers);
}
}
看到Package removed发生时,会发ACTION_PACKAGE_REMOVED;并且只有在数据被删除且非删除系统更新的app时,才会发送ACTION_PACKAGE_FULLY_REMOVED。在PackageManager中有一个flag常量定义PackageManager.DELETE_KEEP_DATA,用以决定在删除app时是否保留数据。
Android 侦听应用(Package)变化的方法侦听广播的更多相关文章
- jQuery 监听元素内容变化的方法
我们可以用onchange事件来完成元素值发生改变触发的监听.但是 onchange 比较适用于<input>.<textarea> 以及 <select> 元素. ...
- 前端组件化Polymer入门教程(6)——监听属性值变化
监听属性值变化 如果需要监听属性值变化可以通过给observer赋值一个回调函数. <say-Hello></say-Hello> <dom-module id=&quo ...
- Android简易实战教程--第十九话《手把手教您监听EditText文本变化,实现抖动和震动的效果》
昨晚写博客太仓促,代码结构有问题,早上测试发现没法监听文本变化!今日更改一下.真心见谅啦,哈哈!主活动的代码已经改好了,看截图这次的确实现了文本监听变化情况. 监听文本输入情况,仅仅限于土司略显low ...
- Android监听手机网络变化
Android监听手机网络变化 手机网络状态发生变化会发送广播,利用广播接收者,监听手机网络变化 效果图 注册广播接收者 <?xml version="1.0" encodi ...
- 计算属性(computed)+侦听器(watch)+ 方法(methods)
计算属性 computed 当数据改变时,方法的结果也会发生改变.如果多处地方调用计算属性里面的同一个方法时,该方法只会执行一次.如图,在控制台改变data里面的num值时,虽然在多处使用comput ...
- onchange监听input值变化及input隐藏后change事件不触发的原因与解决方法(设置readonly后onchange不起作用的解决方案)
转自:https://www.cnblogs.com/white0710/p/7338456.html 1. onchange事件监听input值变化的使用方法: <input id=" ...
- 关于微信小程序使用watch监听数据变化的方法
众所周知,Vue中,可以使用监听属性 watch来观察和响应 Vue 实例上的数据变化,那么小程序能不能实现这一点呢? 监听器的原理,是将data中需监听的数据写在watch对象中,并给其提供一个方法 ...
- Android 关于ListView中按钮监听的优化问题(方法二)
关于ListView中按钮监听的优化问题(方法一)地址: http://www.cnblogs.com/steffen/p/3951901.html 之前的方法一,虽然能够解决position的传递, ...
- android -- 小问题 关于ListView设置了OnScrollListener之后onScrollStateChanged()和onScroll方法监听不到的问题
关于ListView设置了OnScrollListener之后onScrollStateChanged()和onScroll方法监听不到的问题: 原因: 首先OnScrollListener是焦点滚动 ...
随机推荐
- 【POJ 1981】Circle and Points(已知圆上两点求圆心坐标)
[题目链接]:http://poj.org/problem?id=1981 [题意] 给你n个点(n<=300); 然后给你一个半径R: 让你在平面上找一个半径为R的圆; 这里R=1 使得这个圆 ...
- Maven学习总结(1)——Maven入门
Maven学习总结(一)--Maven入门 一.Maven的基本概念 Maven(翻译为"专家","内行")是跨平台的项目管理工具.主要服务于基于Java平台的 ...
- crontab定时任务安装、使用方法
本文介绍下,在linux中安装crontab的方法,以及crontab的具体用法,有需要的朋友参考下. 这里使用yum方式安装crontab: 复制代码代码示例: [root@CentOS ~]# ...
- 贪心算法 Heidi and Library (easy)
A. Heidi and Library (easy) time limit per test 2 seconds memory limit per test 256 megabytes input ...
- BZOJ——T 1800: [Ahoi2009]fly 飞行棋
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1767 Solved: 1395[Submit][Status][Discuss] Descripti ...
- saprk里面的action - aggregate
上一篇讲到了spark里面的action函数: Action列表: reduce collect count first take takeSample takeOrdered saveAsTextF ...
- java调用百度地图API依据地理位置中文获取经纬度
百度地图api提供了非常多地图相关的免费接口,有利于地理位置相关的开发,百度地图api首页:http://developer.baidu.com/map/. 博主使用过依据地理依据地理位置中文获取经纬 ...
- c# POST和GET方式通过server地址提交数据
1:POST方式提交: <strong><span style="font-size:14px;">private static string HttpPo ...
- 3D数学读书笔记——多坐标系和向量基础
本系列文章由birdlove1987编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/24662453 第一个知识点 ...
- iOS7系统iLEX RAT冬青鼠安装教程:无需刷机还原纯净越狱系统
全网科技 温馨提醒:iLEX RAT和Semi-Restore的作用都是让你的已越狱的设备恢复至越狱的初始状态. 可是要注意无论你是用iLexRAT冬青鼠还是Semi-restore.对于还原来说都存 ...