Broadcast Receiver總結(jié)


這是四大組件的第一篇(其他還沒整理好:) ),之前有個習慣,就是把一些筆記記在書上弃甥,但是隨著書越來越多,翻閱的時候比較麻煩汁讼,尤其是一段時間不用之后潘飘,想要翻閱某個知識點太費勁,這里就打算統(tǒng)一整理在一起掉缺,方便查看卜录。

其中有很多內(nèi)容參照了網(wǎng)上的博文,但是時間比較久眶明,忘記出處了艰毒。另外就是參照Android developer的相關(guān)文檔,加上自己的理解搜囱,如果有錯誤丑瞧,歡迎指出啊。

應用場景

  • 同一APP內(nèi)部的同一組件內(nèi)的消息通信(單個或多個線程之間)

  • 同一APP內(nèi)部的不同組件間的消息通信(單個進程)

  • 同一APP內(nèi)部的具有不同進程的多個組件間的消息通信(多個進程)

  • 不同APP組件間的消息通信(多個進程)

  • Android系統(tǒng)與APP之間的消息通信(系統(tǒng)廣播)

分類

1. 普通廣播

<pre>
public abstract void sendBroadcast (Intent intent, String receiverPermission)

public abstract void sendBroadcast (Intent intent)
</pre>
所有receiver都是無序的蜀肘,各receiver往往同時運行绊汹。相對來說更為高效,但各receiver無法終止廣播或使用其他廣播執(zhí)行的結(jié)果扮宠。

2. 有序廣播

<pre>
public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission)

public abstract void sendOrderedBroadcast (Intent intent,
String receiverPermission,
BroadcastReceiver finalResultReceiver,
Handler scheduler,
int initialCode,
String initialData,
Bundle initialExtras)
</pre>

finalResultReceiver作為最末尾的receiver西乖,可以得到前面一系列receiver的處理結(jié)果。通常應該提供自定義的receiver坛增。

scheduler一般設(shè)為null获雕,說明使用context的主線程。

initialCode一般設(shè)為RESULT_OK收捣,作為resultCode的初始值届案。

initialData一般設(shè)為null。作為resultData的初始值罢艾。

initialExtras一般設(shè)為null楣颠,作為resultExtras的初始值。

通過Context.sendOrderedBroadcast發(fā)送咐蚯,receiver會按照android:priority所指定的優(yōu)先級由大到小依次執(zhí)行(android:priority范圍為-1000~1000童漩,數(shù)值越大優(yōu)先級越高,默認優(yōu)先級為0)仓蛆,由于是有序傳播睁冬,可以實現(xiàn)如下效果:

  • 終止傳播:通過調(diào)用abortBroadcast,之后的receiver將接收不到該廣播

  • 向后繼者傳遞數(shù)據(jù):在onReceive中可以調(diào)用setResult、setResultCode豆拨、setResultData/setResultExtras設(shè)置信息直奋,后繼者可以通過getResultCode、getResultData施禾、getResultExtra來獲取信息脚线。sendOrderedBroadcast中的參數(shù)initialCode、initialData弥搞、initialExtras提供了初始值邮绿。

注意:當靜態(tài)注冊與動態(tài)注冊使用了相同的優(yōu)先級(priority)時,動態(tài)注冊的receiver處于更優(yōu)先的位置攀例。

安全方面的考慮

1. 隱患

  • 其他APP可能會針對性的發(fā)出與當前APP中intent-filter相匹配的廣播船逮,導致當前APP不斷受到廣播并處理。

  • 其他APP可能注冊與當前APP一致的intent-filter用于接收廣播粤铭,從而截獲了廣播的具體信息

2. 措施

  • 如果receiver是用于同一APP內(nèi)部的挖胃,則直接將其exported設(shè)為false

  • 在發(fā)送廣播時,使用含有permission的版本

  • 在動態(tài)注冊receiver時梆惯,使用含有permission的版本

  • 在靜態(tài)注冊receiver時酱鸭,在xml中增加permission字段

  • 在發(fā)送廣播時,可以指定receiver的包名垛吗。通過intent.setPackage(packageName)

3. 更便捷的方式——使用LocalBroadcastManager

  • 獲取單例
    <pre>
    static LocalBroadcastManager getInstance(Context context);
    </pre>

  • 注冊
    <pre>
    void registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
    </pre>

  • 注銷
    <pre>
    void unregisterReceiver(BroadcastReceiver receiver);
    </pre>

  • 發(fā)送廣播
    <pre>
    boolean sendBroadcast(Intent intent);
    </pre>

  • 發(fā)送廣播(同步發(fā)送凹髓,會阻塞直至所有相關(guān)receiver執(zhí)行完畢onReceive并返回)
    <pre>
    void sendBroadcastSync(Intent intent);
    </pre>

注冊方式

1. 靜態(tài)注冊

通過xml文件的形式進行注冊,此種方式注冊的receiver會在APP運行期間一直存在怯屉,當APP被kill后就接收不到了蔚舀。此種方式更為常用。

通過靜態(tài)注冊方式注冊的receiver蚀之,其onReceive(Context context蝗敢, Intent intent)中的context為ReceiverRestrictedContext(Context含有的bindService和registerReceiver函數(shù)被禁用)

注意:當BroadcastReceiver作為內(nèi)部類被實現(xiàn),同時又使用了靜態(tài)注冊的方式足删,那么該內(nèi)部類必須聲明為“public static

注意:從4.0開始,需要至少啟動一次APP后锁右,靜態(tài)注冊的receiver才算注冊完畢

2. 動態(tài)注冊

通過代碼的方式進行注冊失受,BroadcastReceiver可實現(xiàn)為內(nèi)部類或一般的外部類。

一般情況下咏瑟,可以在onResume注冊receiver拂到,在onPause中注銷receiver(少數(shù)情況下,也可以在onCreate中注冊码泞,在onDestory中注銷)

通過動態(tài)注冊方式注冊的receiver兄旬,其onReceive(Context context, Intent intent)中的context為Activity的Context。

3. LocalBroadcastManager的動態(tài)注冊

如果廣播只是在APP內(nèi)部進行收發(fā)领铐,那么更高效和安全的方式是使用LocalBroadcastManager悯森。這種方式只能夠進行動態(tài)注冊。

采用此種方式注冊的receiver绪撵,其onReceive(Context context瓢姻, Intent intent)中的context為Application的Context。

生命周期

receiver的生命周期

receiver對象只有在onReceive的調(diào)用期間是有效的音诈,是“活躍”的幻碱,一旦從onReceive中返回,那么系統(tǒng)將認為該對象已經(jīng)結(jié)束细溅,變?yōu)?strong>“不活躍”狀態(tài)褥傍。

任何需要異步的操作都不應該放在onReceive中,因為當異步操作結(jié)束時喇聊,receiver可能已經(jīng)處于“不活躍”狀態(tài)恍风,不能保證對象是否還存在。

注意:不能夠在onReceive中顯示對話框承疲,可行的替代方案是使用NotificationManager相關(guān)功能邻耕。

注意:不能夠在onReceive中綁定服務(bindService),可行的替代方案是通過startService發(fā)送命令燕鸽。

process的生命周期

正在執(zhí)行receiver中onReceive的代碼的process被認為是“前臺進程”兄世,它會一直保持運行(除非遇到非常極端的內(nèi)存方面的壓力才會被kill,這一般不會出現(xiàn))

一旦從onReceive中返回啊研,receiver變?yōu)椤安换钴S”狀態(tài)御滩,它所在的process的重要性將取決于運行在該process中的其他組件。如果這個process沒有其他組件在運行(比如一個APP党远,用戶近期沒有與之交互過)削解,那么系統(tǒng)將認為這是一個“空process”,會在合適的時機kill掉它沟娱。

產(chǎn)生的問題:如果在onReceive中產(chǎn)生一個thread氛驮,然后返回,整個進程济似、包括新產(chǎn)生的thread矫废,都不認定為“不活躍”的,存在被kill的危機砰蠢。解決的方式是與service相結(jié)合蓖扑,在onReceive中啟動一個Service,讓Service去做具體的工作台舱,由于Service的存在律杠,當前的process的重要性取決于Service的狀態(tài),只要Service執(zhí)行的工作未完成,它就一直是“活躍”的柜去,就不會被kill灰嫉。

其他注意事項

如果希望在receiver中的onReceive中開啟一個Activity,則必須增加FLAG_ACTIVITY_NEW_TASK標記诡蜓。

onReceive必須在10秒鐘內(nèi)執(zhí)行完畢熬甫,否則會產(chǎn)生ANR(Application Not Response)。如確實需要進行耗時的操作蔓罚,可以通過啟動一個Service的方式進行椿肩。

與廣播相關(guān)的Intent的FLAG:

<pre>
FLAG_EXCLUDE_STOPPED_PACKAGES (不再通知process被終止的receiver,默認行為)

FLAG_INCLUDE_STOPPED_PACKAGES (仍然通知process被終止的receiver)
</pre>

從3.1開始豺谈,如果靜態(tài)注冊的APP退出后郑象,不一定能夠收到廣播。

因為3.1開始系統(tǒng)增加了對APP是否處于運行狀態(tài)的跟蹤茬末。在發(fā)送廣播時厂榛,系統(tǒng)默認增加了FLAG_EXCLUDE_STOPPED_PACKAGES的flag,導致即使是靜態(tài)注冊的receiver,當其所在process退出后丽惭,同樣無法接收到廣播击奶。

對于自定義的廣播,可以修改這種行為责掏,使靜態(tài)注冊的receiver在process被結(jié)束后依然可以收到廣播柜砾,方法就是在intent中將FLAG_EXCLUDE_STOPPED_PACKAGES改寫為FLAG_INCLUDE_STOPPED_PACKAGES。

對于系統(tǒng)廣播换衬,則無能為力了痰驱。

常見系統(tǒng)廣播

ACTION_TIME_TICK

當前時間變化,每分鐘廣播一次瞳浦。只能使用Context.registerReceiver()動態(tài)注冊担映,靜態(tài)注冊無效。

值: "android.intent.action.TIME_TICK"

ACTION_TIME_CHANGED

系統(tǒng)時間被設(shè)置叫潦。

值: "android.intent.action.TIME_SET"

ACTION_TIMEZONE_CHANGED

時區(qū)被修改蝇完。帶有extra:time-zone

值: "android.intent.action.TIMEZONE_CHANGED"

ACTION_BOOT_COMPLETED

系統(tǒng)啟動完成〈H铮可用進行一些初始化工作四敞,比如安裝alarm等。

權(quán)限:RECEIVE_BOOT_COMPLETED

值: "android.intent.action.BOOT_COMPLETED"

ACTION_PACKAGE_ADDED

新的APP被安裝拔妥。(新安裝的APP不會受到此廣播)

Data:新APP的包名

可能包含的Extras:

  • EXTRA_UID 新APP的UID.
  • EXTRA_REPLACING 是否是重裝或升級。如果這個廣播緊跟在ACTION_PACKAGE_REMOVED之后达箍,并且作用的是同一個包没龙,那么這個值為true

值: "android.intent.action.PACKAGE_ADDED"

ACTION_PACKAGE_CHANGED

已安裝的APP被改動,比如禁用或使能了某個組件。

Data: 包名

Extras:

  • EXTRA_UID 包的UID
  • EXTRA_CHANGED_COMPONENT_NAME_LIST 包含了被修改的組件的類名(或包名本身)
  • EXTRA_DONT_KILL_APP 布爾量硬纤,是否覆蓋重啟APP的默認action(待確認)

值: "android.intent.action.PACKAGE_CHANGED"

ACTION_PACKAGE_REMOVED

已安裝的APP被卸載解滓。

Data:被卸載的APP的包名。

Extras:

  • EXTRA_UID 被卸載APP的uid
  • EXTRA_DATA_REMOVED 如果整個APP(包含代碼和數(shù)據(jù))被卸載筝家,其值被設(shè)為true
  • EXTRA_REPLACING 是否是重裝或升級洼裤。如果這個廣播后面緊跟著ACTION_PACKAGE_ADDED之后,并且作用的是同一個包溪王,那么這個值為true

值: "android.intent.action.PACKAGE_REMOVED"

ACTION_PACKAGE_RESTARTED

用戶重啟了這個APP腮鞍,它的所有process被kill,所有與它相關(guān)的運行時狀態(tài)被移除(包括process莹菱、alarm移国、notification等)。被重啟的APP收不到這個廣播道伟。

Data:被重啟APP的包名

Extras:

  • EXTRA_UID 被重啟APP的uid

值: "android.intent.action.PACKAGE_RESTARTED"

ACTION_PACKAGE_DATA_CLEARED

用戶清空了APP的數(shù)據(jù)迹缀。這需要發(fā)生在ACTION_PACKAGE_RESTARTED之前。在擦除該APP所有持久化數(shù)據(jù)之后蜜徽,本廣播被發(fā)出祝懂。被清空的APP收不到此廣播。

Data:被清空數(shù)據(jù)的APP的包名

Extras:

  • EXTRA_UID APP的uid

值: "android.intent.action.PACKAGE_DATA_CLEARED"

ACTION_UID_REMOVED

UID被從系統(tǒng)移除拘鞋。UID被以EXTRA_UID為鍵存儲在extras中饰抒。

值: "android.intent.action.UID_REMOVED"

ACTION_BATTERY_CHANGED

粘性廣播被聲明為過時的习勤,此處待驗證。

ACTION_POWER_CONNECTED

連接外部電源。

值: "android.intent.action.ACTION_POWER_CONNECTED"

ACTION_POWER_DISCONNECTED

外部電源被移除虾宇。

值: "android.intent.action.ACTION_POWER_DISCONNECTED"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扳剿,隨后出現(xiàn)的幾起案子宪郊,更是在濱河造成了極大的恐慌,老刑警劉巖蹭越,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件障本,死亡現(xiàn)場離奇詭異,居然都是意外死亡响鹃,警方通過查閱死者的電腦和手機驾霜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來买置,“玉大人粪糙,你說我怎么就攤上這事》尴睿” “怎么了蓉冈?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵城舞,是天一觀的道長。 經(jīng)常有香客問我寞酿,道長家夺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任伐弹,我火速辦了婚禮拉馋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惨好。我一直安慰自己煌茴,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布昧狮。 她就那樣靜靜地躺著景馁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逗鸣。 梳的紋絲不亂的頭發(fā)上合住,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音撒璧,去河邊找鬼透葛。 笑死,一個胖子當著我的面吹牛卿樱,可吹牛的內(nèi)容都是我干的僚害。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼繁调,長吁一口氣:“原來是場噩夢啊……” “哼萨蚕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蹄胰,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤岳遥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后裕寨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浩蓉,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年宾袜,在試婚紗的時候發(fā)現(xiàn)自己被綠了捻艳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡庆猫,死狀恐怖认轨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情月培,我是刑警寧澤好渠,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布昨稼,位于F島的核電站,受9級特大地震影響拳锚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寻行,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一霍掺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拌蜘,春花似錦杆烁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至举娩,卻和暖如春析校,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背铜涉。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工智玻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芙代。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓吊奢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纹烹。 傳聞我的和親對象是個殘疾皇子页滚,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容