PendingIntent 可以看作是对 Intent 的一个封装,但它不是立即执行某个行为,而是满足某些条件或者触发某些事件后才执行指定的行为。
获取 PendingIntent 的方法有以下三种,分别是通过 Activity、Service、BroadcastReceiver 获取:
getActivity
系列方法从系统中获取一个用于启动 Activity 的 PendingIntent 对象;getService
系列方法从系统中获取一个用于启动 Service 的 PendingIntent 对象;getBroadcast
系列方法从系统中获取一个用于启动 BroadcastReceiver 的 PendingIntent 对象;以下是相关源码:
public final class PendingIntent implements Parcelable {public static PendingIntent getActivity(Context context, int requestCode,Intent intent, @Flags int flags) {return getActivity(context, requestCode, intent, flags, null);}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(context);intent.prepareToLeaveProcess(context);IIntentSender target =ActivityManager.getService().getIntentSenderWithFeature(ActivityManager.INTENT_SENDER_ACTIVITY, packageName,context.getAttributionTag(), 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();}}public static PendingIntent getActivities(Context context, int requestCode,@NonNull Intent[] intents, @Flags int flags) {return getActivities(context, requestCode, intents, flags, null);}public static PendingIntent getActivities(Context context, int requestCode,@NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) {String packageName = context.getPackageName();String[] resolvedTypes = new String[intents.length];for (int i=0; iintents[i].migrateExtraStreamToClipData(context);intents[i].prepareToLeaveProcess(context);resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());}try {IIntentSender target =ActivityManager.getService().getIntentSenderWithFeature(ActivityManager.INTENT_SENDER_ACTIVITY, packageName,context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,flags, options, context.getUserId());return target != null ? new PendingIntent(target) : null;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}public static PendingIntent getService(Context context, int requestCode,@NonNull Intent intent, @Flags int flags) {return buildServicePendingIntent(context, requestCode, intent, flags,ActivityManager.INTENT_SENDER_SERVICE);}public static PendingIntent getBroadcast(Context context, int requestCode,Intent intent, @Flags int flags) {return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());}
}
对于参数 flag 可以有以下状态:
send
方法触发过后,PendingIntent 将自动调用 cancel
进行销毁。如果再次调用 send
方法的话,系统将会返回一个 SendIntentException
;备注:两个 PendingIntent 对等指它们的 operation 一样,且它们的 Intent 的 action、data、categories、components 和 flags 都一样,但它们的 Intent 的 Extra 可以不一样。
PendingIntent 的匹配规则:如果两个 PendingIntent 的 Intent 相同并且 requestCode 也相同,那么这两个 PendingIntent 是相匹配的。
Intent 的匹配规则:如果两个 Intent 的 ComponentName 和 intent-filter 都相同,那么这两个 Intent 是相同的,Extras 不参加 Intent 的匹配过程。以下是 Intent.filterEquals
方法:
public class Intent implements Parcelable, Cloneable {/* * Determine if two intents are the same for the purposes of intent resolution (filtering). Thatis, * if their action, data, type, identity, class, and categories are the same. This does not compare * any extra data included in the intents. Note that technically when actually matching against an * IntentFilter the identifier is ignored, while here it is directly compared for equality like the * other fields.* Params:* other – The other Intent to compare against.* Returns:* Returns true if action, data, type, class, and categories are the same.*/public boolean filterEquals(Intent other) {if (other == null) {return false;}if (!Objects.equals(this.mAction, other.mAction)) return false;if (!Objects.equals(this.mData, other.mData)) return false;if (!Objects.equals(this.mType, other.mType)) return false;if (!Objects.equals(this.mIdentifier, other.mIdentifier)) return false;if (!(this.hasPackageEquivalentComponent() && other.hasPackageEquivalentComponent())&& !Objects.equals(this.mPackage, other.mPackage)) {return false;}if (!Objects.equals(this.mComponent, other.mComponent)) return false;if (!Objects.equals(this.mCategories, other.mCategories)) return false;return true;}
}
如果是 Android 12 及以上的系统,要求为每个创建的 PendingIntent 对象指定可变性,这样做可以提高应用的安全性。如需声明 PendingIntent 对象是否可变,分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。如果在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException。
在 Android 12 之前的版本中,不带有 FLAG_IMMUTABLE 标记创建的 PendingIntent 默认是可变类型的。
PendingIntent 的使用场景:
Android基础——PendingIntent理解
PendingIntent详解
PendingIntent
PendingIntent的解惑
关于 PendingIntent 您需要知道的那些事