最近在寫一個鬧鐘程序的時候使用到了 PendingIntent, 而且是兩個地方用到,一個是 AlarmManager 定時的時候, 另一個是在點擊通知進入應用的時候。其實我早就想深入研究一下 PendingIntent 了,因為我很好奇一下幾個問題:
Intent 是意圖的意思。Android 中的 Intent 正是取自這個意思,它是一個消息對象,通過它,Android 系統的四大組件能夠方便的通信,并且保證解耦。
Intent 可以說明某種意圖,攜帶一種行為和相應的數據,發送到目標組件。
IntentFilter 與 Intent 配套使用,它聲明了一個組件接受某個 Intent。
PendingIntent 是對 Intent 的封裝,關鍵的不同在于:
A組件 創建了一個 PendingIntent 的對象然后傳給 B組件,B 在執行這個 PendingIntent 的 send 時候,它里面的 Intent 會被發送出去,而接受到這個 Intent 的 C 組件會認為是 A 發的。
B 以 A 的權限和身份發送了這個 Intent。
比如,我們的 Activity 如果設置了 exported = false,其他應用如果使用 Intent 就訪問不到這個 Activity,但是使用 PendingIntent 是可以的。
綜上所述,PendingIntent 有兩個特點:
為什么沒有 getContentProvider?
我猜測,ContentProvider 作為一個數據源,太重要了,相當于是把數據直接暴露出去了
它們的參數都相同,都是四個:Context, requestCode, Intent, flags。Context 不必多說,要想讓其他組件代替自己辦事,當然要將自己的上下文傳給它。action, requestCode 和 Intent 共同來標志一個行為的唯一性,什么意思呢?
簡單的說,我們通過相同的方法(action), 相同的 requestCode 和相同的 Intent 獲取到的 PendingIntent, 雖然可能不是同一個對象,但是,卻是代表同一個東西,之所以這樣看 flags 參數就知道了。
FLAG_ONE_SHOT: 只執行一次, 在調用了 send 以后自動調用 cancel,不能在調用 send 了。
FLAG_NO_CREATE: 不創建新的,如果我們之前設置過,這次就能獲取到,否則,返回 null。
FLAG_CANCEL_CURRENT: 如果之前設置過,就取消掉, 重新創建個新的
FLAG_UPDATE_CURRENT: 如果之前設置過,就更新它。更新什么呢,Intent 的 Extras
FLAG_IMMUTABLE: 設置 Intent 在 send 的時候不能更改
send 是觸發 PendingIntent 包含的行為,它有很多重載形式,我們通常的開發用不到他,除非我們做桌面程序開發或者 Android Framework 開發。
這里我們只是大體說明一下,可以傳給它一個 Intent 來對它原來的 Intent 做修改,但是如果目標設置了 FLAG_IMMUTABLE 則給參數忽略??梢栽O置 callback 當發送完成獲得回調,并且可以通過設置handler決定回調發生的線程。
只有設置 PendingIntent 的原來的應用可以取消它,發送方只能發送,當一個 PendingIntent 被取消后,發送則不會成功。
已知的使用場景是:
通知,鬧鐘,桌面小部件,都是運行在其他應用中的,但是給我們的感知就像是我們自己的應用的一部分。
大體的原理是: A應用希望讓B應用幫忙觸發一個行為,這是跨應用的通信,需要 Android 系統作為中間人,這里的中間人就是 ActivityManager。 A應用創建建 PendingIntent,在創建 PendingIntent 的過程中,向 ActivityManager 注冊了這個 PendingIntent,所以,即使A應用死了,當它再次蘇醒時,只要提供相同的參數,還是可以獲取到之前那個 PendingIntent 的。當 A 將 PendingIntent 調用系統 API 比如 AlarmManager.set(),實際是將權限給了B應用,這時候, B應用可以根據參數信息,來從 ActivityManager 獲取到 A 設置的 PendingIntent。
匹配 PendingIntent 相同時,需要匹配 Intent 相同,Intent 如何匹配相同的?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。