Android Broadcast 探索(二)— 使用

一、Android 廣播機(jī)制包括 3 個(gè)基本要素:

  • 發(fā)送廣播的 Broadcast;

  • 接受廣播的 BroadcastReceiver;

  • 用于傳遞信息的 Intent;

二、發(fā)送廣播

Android 為應(yīng)用程序發(fā)送廣播提供了三種方式:

2.1 sendOrderedBroadcast(Intent, String) — 有序廣播

sendOrderedBroadcast(Intent, String) 方法一次向一個(gè)接收器發(fā)送廣播。當(dāng)每個(gè)接收器依次執(zhí)行時(shí),它可以將結(jié)果傳播到下一個(gè)接收器,它也可以完全中止廣播,使其不會(huì)傳遞給其他接收器。receiver 的運(yùn)行順序可以通過匹配的 intent-filterandroid:priority 屬性進(jìn)行控制;具有相同優(yōu)先級的接收器將以任意順序運(yùn)行。

2.2 sendBroadcast(Intent) — 普通廣播

sendBroadcast(Intent) 方法以隨機(jī)的順序向所有接收者發(fā)送廣播。這被稱為普通廣播。這樣更有效率,但意味著 receiver 無法讀取其他 receiver 的結(jié)果、傳播從其他廣播接收的數(shù)據(jù)以及中止廣播。

2.3 LocalBroadcastManager.sendBroadcast — 本地廣播

LocalBroadcastManager.sendBroadcast() 方法將廣播發(fā)送到與發(fā)送者位于同一應(yīng)用程序中的接收者。如果你不需要跨應(yīng)用發(fā)送廣播,請使用本地廣播。實(shí)現(xiàn)效率更高(不需要進(jìn)程間通信),而且無需擔(dān)心其他應(yīng)用程序能夠接收或發(fā)送你的廣播。

以下代碼片段演示了如何通過創(chuàng)建一個(gè) Intent 并調(diào)用 sendBroadcast(Intent) 來發(fā)送廣播。

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice me senpai!");
sendBroadcast(intent);

廣播消息被包裹在一個(gè) Intent 對象中。Intent 的 action 字符串必須提供應(yīng)用程序的 Java 包名稱并唯一標(biāo)識廣播事件。你可以將附加信息通過 putExtra(String, Bundle) 添加到 intent 中。你也可以通過調(diào)用 setPackage(String) 限制發(fā)送的應(yīng)用程序。

注意:盡管 intent 用于發(fā)送廣播和啟動(dòng)活動(dòng) (startActivity(Intent)),但這些操作完全不相關(guān)。

三、使用權(quán)限限制廣播

權(quán)限允許你將廣播限制為擁有特定權(quán)限的應(yīng)用程序集。你可以對廣播的發(fā)送者或接收者實(shí)施限制。

3.1 帶權(quán)限發(fā)送

當(dāng)你調(diào)用 sendBroadcast(Intent, String) 或者 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle),你可以指定一個(gè)權(quán)限參數(shù)。只有接收方已經(jīng)在 manifest 中標(biāo)記了權(quán)限(并且授予許可,如果該權(quán)限存在危險(xiǎn))才可以接收廣播。例如,下面的代碼發(fā)送一個(gè)廣播:

sendBroadcast(new Intent("com.example.NOTIFY"),
              Manifest.permission.SEND_SMS);

要接收廣播,應(yīng)用程序必須請求權(quán)限,如下所示:

<uses-permission android:name="android.permission.SEND_SMS"/>

注意:自定義權(quán)限是在安裝應(yīng)用程序時(shí)注冊的。定義自定義權(quán)限的應(yīng)用程序必須在使用之前安裝。

3.2 帶權(quán)限接收

如果你在注冊 receiver 時(shí)指定一個(gè)權(quán)限參數(shù)(無論是在 manifest 的 <receiver> 標(biāo)簽中,還是通過 registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)),那么只有在 manifest 中通過 <uses-permission> 標(biāo)簽請求該權(quán)限的應(yīng)用程序 (并且授予許可,如果該權(quán)限存在危險(xiǎn))可以發(fā)送 intent 給該 receiver。

例如,假設(shè)你的接收應(yīng)用程序具有如下所示的接收器聲明:

<receiver android:name=".MyBroadcastReceiver"
          android:permission="android.permission.SEND_SMS">
    <intent-filter>
        <action android:name="android.intent.action.AIRPLANE_MODE"/>
    </intent-filter>
</receiver>

或者你的接收應(yīng)用程序有一個(gè)上下文注冊的接收器,如下所示:

IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null );

那么,為了能夠向這些接收方發(fā)送廣播,發(fā)送方必須請求權(quán)限,如下所示:

<uses-permission android:name="android.permission.SEND_SMS"/>

四、安全考慮和最佳做法

以下是發(fā)送和接收廣播的一些安全考慮事項(xiàng)和最佳做法:

  • 如果你不需要將廣播發(fā)送到你的應(yīng)用以外的組件,則可以使用 LocalBroadcastManager 發(fā)送和接收本地廣播。LocalBroadcastManager 效率要高得多(不需要進(jìn)程間通信),并可以讓你避免其他應(yīng)用程序能夠接收或發(fā)送你的廣播。本地廣播可以在你的應(yīng)用程序中作為通用的 pub/sub event bus,而無需系統(tǒng)廣播的任何開銷。

  • 如果許多應(yīng)用程序已經(jīng)在 manifest 中注冊相同的廣播,則可能會(huì)導(dǎo)致系統(tǒng)啟動(dòng)大量應(yīng)用程序,從而對設(shè)備性能和用戶體驗(yàn)產(chǎn)生重大影響。為了避免這種情況,優(yōu)先使用 context 方式注冊廣播。有時(shí),Android 系統(tǒng)本身會(huì)強(qiáng)制使用上下文注冊的接收器。例如,CONNECTIVITY_ACTION 廣播僅傳送給上下文注冊的接收器。

  • 不要使用隱式 intent 傳播敏感信息。任何注冊了接收該廣播的應(yīng)用程序都可以讀取信息。有三種方法可以限制哪些應(yīng)用能夠接收你的廣播:

    • 可以在發(fā)送廣播時(shí)指定權(quán)限。

    • 在 Android 4.0 及更高版本,可以通過 setPackage(String) 指定包名。

    • 可以使用 LocalBroadcastManager 發(fā)送廣播。

  • 當(dāng)你注冊 receiver 時(shí),任何應(yīng)用程序都可能將潛在的惡意廣播發(fā)送到你應(yīng)用的 receiver。有三種方法可以限制你的應(yīng)用可以收到哪些廣播:**

    • 可以在注冊廣播接收器時(shí)指定權(quán)限。

    • 對于 manifest 聲明的 receiver,可以在清單中將 android:exported 屬性設(shè)置為 “false”。這樣 receiver 就不接收來自應(yīng)用程序外部的廣播。

    • 可以通過 LocalBroadcastManager 限制只有本地廣播。

  • 廣播動(dòng)作 (action) 的命名空間是全局的。確保動(dòng)作名稱和其他字符串被寫入您擁有的名稱空間中,否則可能會(huì)無意中與其他應(yīng)用程序發(fā)生沖突。

  • 因?yàn)?receiver 的 onReceive(Context, Intent) 方法在主線程上運(yùn)行,所以它應(yīng)該快速執(zhí)行并返回。如果你需要執(zhí)行長時(shí)間運(yùn)行的工作,請注意開啟子線程或啟動(dòng)后臺服務(wù),因?yàn)橄到y(tǒng)可能會(huì)在 onReceive() 返回后終止整個(gè)進(jìn)程 。建議:

    • 在 receiver 的 onReceive() 方法中調(diào)用 goAsync() 方法并傳遞 BroadcastReceiver.PendingResult 給后臺線程。這使廣播從 onReceive() 返回后依舊保持活動(dòng)狀態(tài)。但是,即使采用這種方法,系統(tǒng)也希望你能夠很快結(jié)束廣播(不到 10 秒)。不過,它確實(shí)允許你將工作移至另一個(gè)線程以避免妨礙主線程。

    • 使用 JobScheduler 安排工作。

  • 不要從廣播接收器啟動(dòng)活動(dòng),因?yàn)楹苡绊懹脩趔w驗(yàn);特別是如果有多個(gè)接收器的話。相反,請考慮執(zhí)行顯示通知等簡單操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評論 2 374

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

  • Broadcasts Android apps can send or receive broadcast mes...
    woitaylor閱讀 6,474評論 0 12
  • 【Android 廣播】 BroadcastReceiver簡介 BroadcastReceiver(廣播接收器)...
    Rtia閱讀 3,433評論 1 17
  • 1.Android廣播機(jī)制概述 Android廣播分為兩個(gè)方面:廣播發(fā)送者和廣播接收者,通常情況下,Broadca...
    IT小魔女的故事閱讀 562評論 0 2
  • 前言:本文所寫的是博主的個(gè)人見解,如有錯(cuò)誤或者不恰當(dāng)之處,歡迎私信博主,加以改正! 原文鏈接,demo鏈接 廣播簡...
    PassersHowe閱讀 3,464評論 0 9
  • 1.資源庫 來自我內(nèi)心對一些情緒的熱愛和揮之不去的記憶是我想要寫作的源頭,我想用最美好的文字歌頌它們。 喜歡讀散文...
    迷鹿人閱讀 281評論 1 2