基础概念:
pendingIntent字面意义:等待的,未决定的Intent。pendingIntent对象,使用方法类的静态方法 :
getActivity(Context, int, Intent, int)------->跳转到一个activity组件
getBroadcast(Context, int, Intent, int)------>打开一个广播组件
getService(Context, int, Intent, int)-------->打开一个服务组件
在PendingIntent.java文件中,我们可以看到有如下几个比较常见的静态函数:
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags) public static PendingIntent getActivities(Context context, int requestCode, Intent[] intents, int flags) public static PendingIntent getActivities(Context context, int requestCode, Intent[] intents, int flags, Bundle options)
pendingIntent是一种特殊的Intent。主要的区别在于Intent的执行立刻的,而pendingIntent的执行不是立刻的,而是在其他方法处被调用,所以看起来就像被延迟了一样。主要的使用的地方和例子:通知Notificatio的发送,短消息SmsManager的发送和警报器AlarmManager的执行等等。
很明显,这种异步激发常常是要跨进程执行的。比如说A进程作为发起端,它可以从系统“获取”一个PendingIntent,然后A进程可以将PendingIntent对象通过binder机制“传递”给B进程,再由B进程在未来某个合适时机,“回调”PendingIntent对象的send()动作,完成激发。
Intent和PendingIntent的区别
a. Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
b. Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
c. PendingIntent自带Context,而Intent需要在某个Context内运行
d. Intent在原task中运行,PendingIntent在新的task中运行
阿里巴巴Android开发手册
1. 【强制】使用 PendingIntent 时,禁止使用空 intent,同时禁止使用隐式 Intent
说明:
1) 使用 PendingIntent 时,使用了空 Intent,会导致恶意用户劫持修改 Intent 的内容。禁止使用一个空 Intent 去构造 PendingIntent,构造 PendingIntent 的 Intent一定要设置 ComponentName 或者 action。
2) PendingIntent 可以让其他 APP 中的代码像是运行自己 APP 中。PendingIntent的intent接收方在使用该intent时与发送方有相同的权限。在使用PendingIntent时,PendingIntent中包装的intent如果是隐式的Intent,容易遭到劫持,导致信息泄露。
正例:
Intent intent = new Intent(this, SomeActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT); try { pendingIntent.send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); }
反例 1:
Bundle addAccountOptions = new Bundle(); mPendingIntent = PendingTntent.getBroadcast(this, 0, new Intent, 0); addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent); addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, Utils.hasMultipleUsers(this)); AccountManager.get(this).addAccount(accountType, null, null, addAccountOptions, null, mCallback, null);
mPendingIntent 是通过 new Intent()构造原始 Intent 的,所以为“双无”Intent,这个PendingIntent最终被通过AccountManager.addAccount 方法传递给了恶意APP接口。
反例 2:
Intent intent = new Intent("com.test.test.pushservice.action.METHOD"); intent.addFlags(32); intent.putExtra("app", PendingIntent.getBroadcast(this, 0, intent, 0));
如上代码PendingIntent.getBroadcast,PendingItent中包含的Intent为隐式intent,因此当 PendingIntent 触发执行时,发送的 intent 很可能被嗅探或者劫持,导致 intent内容泄漏。
参考:
Android中pendingIntent的深入理解
https://www.cnblogs.com/itcqx/p/5557241.html
说说PendingIntent的内部机制
http://blog.csdn.net/codefly/article/details/42319591
https://my.oschina.net/youranhongcha/blog/196933
关于Notification的一点愚见(PendingIntent工作流程)
http://blog.csdn.net/yujunyu12/article/details/52401414