PendingIntent 中的單詞 “pending” 指延遲或掛起,就是指它是延遲的或掛起的。一句話概括,PendingIntent 一種是支持授權(quán)其他應(yīng)用以當前應(yīng)用的身份執(zhí)行包裝的 Intent 操作的系統(tǒng)特性。
什么場景下會使用 PendingIntent?
場景 1 - 系統(tǒng)通知消息的點擊操作
場景 2 - 桌面Widget的點擊操作
場景 3 - 系統(tǒng)鬧鐘操作
場景 4 - 第三方應(yīng)用回調(diào)操作
PendingIntent 和 Intent 有什么區(qū)別?
從結(jié)構(gòu)上來說,PendingIntent 是 Intent 的包裝類,其內(nèi)部持有一個代表最終意圖操作的 Intent。
1、執(zhí)行進程不同 —— PendingIntent 在其他進程執(zhí)行: Intent 通常會在創(chuàng)建進程中執(zhí)行,而 PendingIntent 通常不會在創(chuàng)建進程中執(zhí)行;
2、執(zhí)行時間不同 —— PendingIntent 會延遲執(zhí)行: Intent 通常會立即執(zhí)行,而 PendingIntent 通常會延遲執(zhí)行,延遲到其他進程完成任務(wù)后再執(zhí)行,甚至延遲到創(chuàng)建進程消亡后。例如,在 場景 1 - 系統(tǒng)通知消息的點擊操作 中,即使發(fā)送系統(tǒng)通知消息的進程已經(jīng)消亡了,依然不妨礙二級 Intent 的跳轉(zhuǎn);
3、執(zhí)行身份不同 —— PendingIntent 支持授權(quán): PendingIntent 內(nèi)部持有授權(quán)信息,支持其他應(yīng)用以當前應(yīng)用的身份執(zhí)行,這有利于避免嵌套 Intent 存在的安全隱患。
PendingIntent 的使用方法
啟動組件:
// 啟動 Activity
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
// 啟動 Service
PendingIntent.Service(Context context, int requestCode, Intent intent, int flags)
// 發(fā)送廣播
PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)
PendingIntent 的 4 個參數(shù):
1、context: 當前應(yīng)用的上下文,PendingIntent 將從中抽取授權(quán)信息;
2、requestCode: PendingIntent 的請求碼,與 Intent 的請求碼類似;
3、intent: 需要跳轉(zhuǎn)的包裝intent;
4、flag: PendingIntent標記位
PendingIntent標記位
FLAG_IMMUTABLE:不可變標記位,將約束外部應(yīng)用消費 PendingIntent 修改其中的 Intent;
FLAG_MUTABLE:可變標記位,不約束外部應(yīng)用消費 PendingIntent 修改其中的 Intent;
FLAG_UPDATE_CURRENT:如果系統(tǒng)中已經(jīng)存在相同的 PendingIntent,那么將保留原有 PendingIntent 對象,而更新其中的 Intent。即使不可變 PendingIntent,依然可以在當前應(yīng)用更新;
FLAG_CANCEL_CURRENT:如果系統(tǒng)中已經(jīng)存在相同的 PendingIntent,那么將先取消原有的 PendingIntent,并重新創(chuàng)建新的 PendingIntent。
FLAG_NO_CREATE:如果系統(tǒng)中已經(jīng)存在相同的 PendingIntent,那么不會重新創(chuàng)建,而是直接返回 null;
FLAG_ONE_SHOT:一次有效標記位,PendingIntent 被消費后不支持重復(fù)消費,即只能使用一次。
PendingIntent 可變性是一種對外部應(yīng)用消費行為的約束機制,通過標記位 FLAG_MUTABLE 和 FLAG_IMMUTABLE 控制 PendingIntent 可變或不可變??勺冃砸馕吨谙M PendingIntent 時,可以針對其中包裝的 Intent 進行修改。強烈建議在創(chuàng)建 PendingIntent 時使用 FLAG_IMMUTABLE。
完整使用示例:
val intent = Intent()
intent.action = "xxxaction"
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
var flag = PendingIntent.FLAG_UPDATE_CURRENT
if (android.os.Build.VERSION.SDK_INT >= 31) {
flag = flag or PendingIntent.FLAG_IMMUTABLE
}
PendingIntent.getActivity(
context,
appWidgetId,
intent,
flag
)