PendingIntent延迟意图
PendingIntent一般用在Notification和桌面小挂件AppWidgetProvider的点击事件发生时传递的Intent意图。这里主要了解一下PendingIntent,至于具体使用场景参考另外两篇详细介绍。
1、什么是PendingIntent
PendingIntent谷歌官方文档的解释是“A description of an Intent and target action to perform with it.(要执行的意图和目标动作的描述)”。位于android.app包中。
PendingIntent就是一个Intent的描述,是对真实Intent的一种封装载体。不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为。
2、获取PendingInteng
一共有五种方法创建PendingIntent对象,都是PendingIntent类中提供的static方法:
- getActivities(Context context, int requestCode, Intent[] intents, int flags)
- getActivity(Context context, int requestCode, Intent intent, int flags)
- getBroadcast(Context context, int requestCode, Intent intent, int flags)
- getService(Context context, int requestCode, Intent intent, int flags)
- getForegroundService(Context context, int requestCode, Intent intent, int flags)
最常用的三种获取PendingIntent的方式:
- getActivities(Context context, int requestCode, Intent[] intents, int flags):从系统 取得一个用于启动一个Activity的PendingIntent对象
- getBroadcast(Context context, int requestCode, Intent intent, int flags):从系统取得一个向BroadcastReceiver的发送广播的PendingIntent对象
- getService(Context context, int requestCode, Intent intent, int flags):从系统取得一个 用于启动一个Service的PendingIntent对象
不难发现它们的参数都有4个:Context、requestCode、Intent、flags。分别是上下文、请求码、意图、标志位。最后一个参数flags有四种可选,每种都代表不同的意义:
- FLAG_ONE_SHOT
/ **
*标志指示此PendingIntent只能使用一次。
*如果已设置,则在send()被调用,它将自动
*已为您取消,以后再尝试通过它发送都会失败。
* /
public static final int FLAG_ONE_SHOT = 1 << 30;- FLAG_NO_CREATE
/ **
*标志,指示如果描述的PendingIntent不
*已经存在,然后简单地返回null而不是创建它。
* /
public static final int FLAG_NO_CREATE = 1 << 29;- FLAG_CANCEL_CURRENT
/ **
*如果当前系统中已经存在一个相同的PendingIntent对象,
*那么就将先将已有的PendingIntent取消
*然后重新生成一个PendingIntent对象。
* /
public static final int FLAG_CANCEL_CURRENT = 1 << 28;- FLAG_UPDATE_CURRENT
/ **
*如果系统中有一个和你描述的PendingIntent对等的PendingInent,
*那么系统将使用该PendingIntent对象,
*但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据
*例如更新Intent中的Extras
* /
public static final int FLAG_UPDATE_CURRENT = 1 << 27;3、PendingInteng用途
PendingIntent本身只是对系统维护的令牌的引用,该令牌描述了用于检索令牌的原始数据。这意味着,即使其拥有的应用程序的进程被杀死,PendingIntent本身也将在已赋予它的其他进程中保持可用。
PendingIntent中保存有当前App的Context,使它赋予外部App一种能力,使得外部App可以如同当前App一样的执行pendingIntent里的Intent,算在执行时当前App已经不存在了,也能通过存在pendingintent里的Context照样执行Intent。
①PendingIntent的使用场景主要用于闹钟、通知、桌面部件。定时服务AlarmManager设置闹铃时间到时触发PendingIntent:
setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation);
set(int type, long triggerAtMillis, PendingIntent operation);
setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation);②用于Notification通知,给通知添加点击事件PendingIntent
Notification.Builder.setContentIntent(PendingIntent intent4、PendingInteng和Intent区别
①Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
②Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
③PendingIntent自带Context,而Intent需要在某个Context内运行
④Intent在原task中运行,PendingIntent在新的task中运行
5、PendingInteng示例
常常用来给通知设置一些事件,如:
Notification.Builder builder = new Notification.Builder(this);
Intent intent = new Intent();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
... ...
builder.setContentIntent(pendingIntent);
... ...附:PendingIntent创建部分源码
①getActivity
public static PendingIntent getActivity(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
String packageName = context.getPackageName();
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSender(
ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, context.getUserId());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}②getBroadcast
public static PendingIntent getBroadcast(Context context, int requestCode,
Intent intent, @Flags int flags) {
return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());
}
public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
Intent intent, int flags, UserHandle userHandle) {
String packageName = context.getPackageName();
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSender(
ActivityManager.INTENT_SENDER_BROADCAST, packageName,
null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, userHandle.getIdentifier());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}③getService
public static PendingIntent getService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags) {
return buildServicePendingIntent(context, requestCode, intent, flags,
ActivityManager.INTENT_SENDER_SERVICE);
}同时查看PendingIntent 类可以看到许多的Send函数,就是PendingIntent在进行被赋予的相关的操作。send()方法执行与此PendingIntent相关的操作,允许调用方指定有关要使用的Intent的信息,并在发送完成时得到通知。
public void send(Context context, int code, @Nullable Intent intent,
@Nullable OnFinished onFinished, @Nullable Handler handler) throws CanceledException {
send(context, code, intent, onFinished, handler, null, null);
}参考资料:
Android Documentation of PendingIntent
Android基础——PendingIntent理解

