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是焦点滚动 ...
随机推荐
- Linux的安装教程
CentOS 6 + VMWare: 资源:https://pan.baidu.com/s/1AA4gaMpaoVaMor-tRU-n7A 提取码:6e8r ( 内附 VMWare 14 激活 ...
- models中字段参数blank和null的用法区别
blank当blank=True时,说明此处的数据可以不填,默认情况下为False,也就意味着默认情况下,所输入的数据不得空,blank是和页面表单有关,在页面需要输入参数的时候,如果在models里 ...
- sudo dpkg-reconfigure phpmyadmin命令,重新配置一遍phpmyadmin
sudo dpkg-reconfigure phpmyadmin命令,重新配置一遍phpmyadmin
- Python基础-while
使用while循环实现输出2-3+4-5+6.....+100的和. i = 2 sum=0 while i<=100: if i % 2 == 0: sum += i else: sum -= ...
- Spring整合Junit框架进行单元测试Demo
一.开发环境 eclipse版本:4.6.1 maven版本:3.3.3 junit版本:4.12 spring版本:4.1.5.RELEASE JDK版本:1.8.0_111 二.项目结构 图 三. ...
- (44). Spring Boot日志记录SLF4J【从零开始学Spring Boot】
在开发中打印内容,使用 System.out.println() 和 Log4j 应当是人人皆知的方法了. 其实在开发中我们不建议使用 System.out 因为大量的使用 System.out 会增 ...
- iOS学习笔记17-FMDB你好!
上一节我已经介绍了SQLite的简单使用,不了解的可以提前去看一下iOS学习笔记16-数据库SQLite,这节我们来讲下FMDB. 一.FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQL ...
- hdu_1232_畅通工程_201403091018
畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- SpringMVC项目
一.说明该项目是为了演示SpringMVC框架中涉及到的一些知识点,相对独立,掌握这些,基本上就能够解决工作中遇到的一些问题.整个项目的构建规划如下: 1.创建一个标准的Maven Web项目;2.使 ...
- D. Multiplication Table 二分查找
刚做这道题根本没想到二分,最关键是没想出来怎样统计在这个矩阵中比一个数小的有几个怎么算.造成自己想了好久最后看了别人的提示才做出来.哎.好久不做题太弱了 #include<iostream> ...