Android基礎(chǔ) - BroadcastReceiver

老婆保佑,代碼無BUG

目錄

  • 什么是廣播
  • 如何使用廣播
  • 注冊廣播的方式
  • 廣播的類型
  • 不同注冊方式的廣播接收器回調(diào)
  • 不同Android API版本中廣播機(jī)制相關(guān)API重要變遷

一.什么是廣播

作為Android 4大組件之一魄衅,壓力山大雕擂。

系統(tǒng)或者本應(yīng)用程序通過發(fā)送廣播的形式告訴其他app現(xiàn)在系統(tǒng)或者本app的狀態(tài)
這種方式稱為廣播的發(fā)送

舉個(gè)例子

比如:老村長拿個(gè)喇叭喊話,誰家羊丟了哼御?(發(fā)送廣播的人),所有村名都聽到了(其他單獨(dú)的app)

二.如何使用廣播

廣播的三要素

  • 發(fā)送廣播
  • 接受廣播
  • 處理廣播

下面一一分析

如何使用廣播

public class MainActivity extends AppCompatActivity {

    private TestBroadCast broadCast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //發(fā)送廣播
        findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1.模擬發(fā)送廣播 (一般寫的都是action條件,不用組件名)
                //自定義action條件
                //在任何app,只要接收器的條件是allens都可以接收數(shù)據(jù)
                Intent intent = new Intent("allens");
                intent.putExtra("data", "測試發(fā)送廣播...");
                //核心方法
                sendBroadcast(intent);
            }
        });

        

        //動(dòng)態(tài)注冊廣播
        findViewById(R.id.register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 第一個(gè)參數(shù):自定義接收器的實(shí)例化對象
                 * 第二個(gè)參數(shù):構(gòu)建IntentFliter條件
                 */
                IntentFilter filter = new IntentFilter();
                //添加的action條件,匹配頻道使用
                filter.addAction("allens");
                //設(shè)置優(yōu)先級
                filter.setPriority(Integer.MAX_VALUE);
                broadCast = new TestBroadCast();
                registerReceiver(broadCast, filter);
            }
        });

        
        //取消注冊
        findViewById(R.id.unregister).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              if (broadCast != null) {
                    unregisterReceiver(broadCast);
                    broadCast = null;
                }
            }
        });
    }
}

public class TestBroadCast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String value = intent.getStringExtra("data");
        Log.e("TAG","data--->" + value);
    }
}

三.注冊廣播的方式

  • 動(dòng)態(tài)注冊
    在上面的例子中 可以看到 我們使用代碼動(dòng)態(tài)注冊了廣播逗余,也動(dòng)態(tài)的取消注冊廣播说榆,這是一中方式喉誊,當(dāng)然還有其他的方式

  • 靜態(tài)注冊

manifest中配置

 <receiver
            android:name=".broadcast.TestBroadCast"
            android:enabled="false"
            android:exported="true"
            android:icon="@drawable/ic_launcher_background"
            android:label="@string/app_name"
            android:permission="@string/app_name"
            android:process="@string/app_name">
            <intent-filter android:priority="2000">
                <action android:name="allens" />
            </intent-filter>
 </receiver>

參數(shù)解釋

參數(shù) 說明
intent-filter 過濾器,篩選廣播條件
android:name 這里的name 要和我們發(fā)送廣播的action 相同羔挡,不然收不到廣播
android:priority 2000到-2000 ,通過priority設(shè)置優(yōu)先級
android:enabled true (默認(rèn)的是true)設(shè)置為true廣播接收器才能夠被啟用洁奈,false該廣播接收器會被禁止實(shí)例化(不能使用)
android:exported 是否能夠接收來自應(yīng)用程序外部的消息
android:icon 定義一個(gè)代表廣播接收器的圖標(biāo)
android:label 這個(gè)屬性給廣播接收器設(shè)定一個(gè)用戶可讀的懂的文本標(biāo)簽
android:name 這個(gè)屬性值要用廣播接收器的實(shí)現(xiàn)類的類名來設(shè)置
android:permission 把消息發(fā)送給該廣播接收器的廣播器所必須要有的權(quán)限
android:process 這個(gè)屬性用于設(shè)置該廣播接收器應(yīng)該運(yùn)行在那個(gè)進(jìn)程中的進(jìn)程名

當(dāng)然這些屬性,也不用全寫上绞灼,更具實(shí)際情況睬魂,

參考
http://blog.csdn.net/think_soft/article/details/7583047

對比

類型 優(yōu)點(diǎn) 缺點(diǎn)
靜態(tài)注冊 常駐廣播,不受生命周期影響 耗電镀赌,占內(nèi)存
動(dòng)態(tài)注冊 靈活氯哮, 必須跟隨組件的生命周期,及時(shí)釋放資源
來個(gè)美女提提神商佛,不然你們都快睡覺了都喉钢,哈哈

so 繼續(xù)

四. 廣播的類型

普通廣播(Normal Broadcast)
系統(tǒng)廣播(System Broadcast)
有序廣播(Ordered Broadcast)
粘性廣播(Sticky Broadcast)
App應(yīng)用內(nèi)廣播(Local Broadcast)

1.普通廣播

定義:開發(fā)者自己定義的intent,像上面我們使用的就是普通廣播

Intent intent = new Intent();
//對應(yīng)BroadcastReceiver中intentFilter的action
intent.setAction("自定義的action");
//發(fā)送廣播
sendBroadcast(intent);
<receiver 
    //此廣播接收者類是開發(fā)者自定義的BroadcastReceiver
    android:name=".BroadcastReceiver" >
    <intent-filter>
        <action android:name="自定義的action" />
    </intent-filter>
</receiver>

總結(jié)

1.順序是無序的
2.需要在intent-filter自定義action
3.如果發(fā)送廣播時(shí)有相應(yīng)的權(quán)限要求良姆,BroadCastReceiver如果想要接收此廣播肠虽,也需要有相應(yīng)的權(quán)限

2.系統(tǒng)廣播

Android系統(tǒng)中內(nèi)置了多個(gè)系統(tǒng)廣播,只要涉及到手機(jī)的基本操作玛追,基本上都會發(fā)出相應(yīng)的系統(tǒng)廣播税课。如:開啟啟動(dòng),網(wǎng)絡(luò)狀態(tài)改變痊剖,拍照韩玩,屏幕關(guān)閉與開啟,點(diǎn)亮不足等等陆馁。每個(gè)系統(tǒng)廣播都具有特定的intent-filter找颓,其中主要包括具體的action,系統(tǒng)廣播發(fā)出后叮贩,將被相應(yīng)的BroadcastReceiver接收击狮。系統(tǒng)廣播在系統(tǒng)內(nèi)部當(dāng)特定事件發(fā)生時(shí),有系統(tǒng)自動(dòng)發(fā)出

android 系統(tǒng)廣播action

3.有序廣播

有序廣播的有序廣播中的“有序”是針對廣播接收者而言的益老,指的是發(fā)送出去的廣播被BroadcastReceiver按照先后循序接收彪蓬。有序廣播的定義過程與普通廣播無異只是其的主要發(fā)送方式變?yōu)?/p>

sendOrderedBroadcast(intent);

特點(diǎn)

1.按照Priority屬性值從大-小排序;
2.Priority屬性相同者捺萌,動(dòng)態(tài)注冊的廣播優(yōu)先档冬;
3.先接收的BroadcastReceiver可以對此有序廣播進(jìn)行截?cái)啵购竺娴腂roadcastReceiver不再接收到此廣播,也可以對廣播進(jìn)行修改捣郊,使后面的BroadcastReceiver接收到廣播后解析得到錯(cuò)誤的參數(shù)值。當(dāng)然慈参,一般情況下呛牲,不建議對有序廣播進(jìn)行此類操作,尤其是針對系統(tǒng)中的有序廣播

4.粘性廣播

定義:廣播的信息內(nèi)容系統(tǒng)會存放一段時(shí)間,任何時(shí)間內(nèi)app都可以獲取數(shù)據(jù)

sendStickyBroadCast

由于在Android5.0 & API 21中已經(jīng)失效驮配,相應(yīng)的還有粘性有序廣播,所以不建議使用娘扩,在這里也不作過多的總結(jié)。

5.App應(yīng)用內(nèi)廣播

由前文闡述可知壮锻,Android中的廣播可以跨進(jìn)程甚至跨App直接通信琐旁,且注冊是exported對于有intent-filter的情況下默認(rèn)值是true,由此將可能出現(xiàn)安全隱患如下

1 .其他App可能會針對性的發(fā)出與當(dāng)前App intent-filter相匹配的廣播猜绣,由此導(dǎo)致當(dāng)前App不斷接收到廣播并處理

2.其他App可以注冊與當(dāng)前App一致的intent-filter用于接收廣播灰殴,獲取廣播具體信息

常見改進(jìn)方式

1.對于同一App內(nèi)部發(fā)送和接收廣播,將exported屬性人為設(shè)置成false掰邢,使得非本App內(nèi)部發(fā)出的此廣播不被接收

2.在廣播發(fā)送和接收時(shí)牺陶,都增加上相應(yīng)的permission,用于權(quán)限驗(yàn)證辣之;

3.發(fā)送廣播時(shí)掰伸,指定特定廣播接收器所在的包名,具體是通過intent.setPackage(packageName)指定在怀估,這樣此廣播將只會發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中狮鸭。

說了那么多,所以才有了App應(yīng)用內(nèi)廣播,其特點(diǎn)如下

1.安全性更高多搀;
2.更加高效

如何使用呢歧蕉?

//注冊應(yīng)用內(nèi)廣播接收器
//步驟1:實(shí)例化BroadcastReceiver子類 & IntentFilter mBroadcastReceiver 
mBroadcastReceiver = new mBroadcastReceiver(); 
IntentFilter intentFilter = new IntentFilter(); 

//步驟2:實(shí)例化LocalBroadcastManager的實(shí)例
localBroadcastManager = LocalBroadcastManager.getInstance(this);

//步驟3:設(shè)置接收廣播的類型 
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

//步驟4:調(diào)用LocalBroadcastManager單一實(shí)例的registerReceiver()方法進(jìn)行動(dòng)態(tài)注冊 
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//取消注冊應(yīng)用內(nèi)廣播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

//發(fā)送應(yīng)用內(nèi)廣播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);

五. 不同注冊方式的廣播接收器回調(diào)onReceive(context, intent)中的context具體類型

類型 context具體類型
靜態(tài)注冊的ContextReceiver ReceiverRestricted Context
全局廣播的動(dòng)態(tài)注冊的ContextReceiver Activity Context
通過LocalBroadcastManager動(dòng)態(tài)注冊的ContextReceiver Application Context

注意:對于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播,只能通過LocalBroadcastManager動(dòng)態(tài)注冊的ContextReceiver才有可能接收到(靜態(tài)注冊或其他方式動(dòng)態(tài)注冊的ContextReceiver是接收不到的)

六. 不同Android API版本中廣播機(jī)制相關(guān)API重要變遷

Android 3.1開始

  • 自Android3.1開始,靜態(tài)注冊的廣播接收器康铭,app已經(jīng)退出廊谓,有相應(yīng)的廣播發(fā)出,接收不到

原因:自Android3.1開始麻削,系統(tǒng)本身則增加了對所有app當(dāng)前是否處于運(yùn)行狀態(tài)的跟蹤蒸痹。在發(fā)送廣播時(shí),不管是什么廣播類型呛哟,系統(tǒng)默認(rèn)直接增加了值為FLAG_EXCLUDE_STOPPED_PACKAGES的flag叠荠,導(dǎo)致即使是靜態(tài)注冊的廣播接收器,對于其所在進(jìn)程已經(jīng)退出的app扫责,同樣無法接收到廣播

Android 3.1開始系統(tǒng)在Intent與廣播相關(guān)的flag增加了參數(shù)榛鼎,分別是

  • FLAG_INCLUDE_STOPPED_PACKAGES:包含已經(jīng)停止的包(停止:即包所在的進(jìn)程已經(jīng)退出)

  • FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經(jīng)停止的包

android 5.0開始

  • Android5.0/API level 21開始粘滯廣播和有序粘滯廣播過期,以后不再建議使用;

android 7.0開始

  • 徹底沒有靜態(tài)注冊的方式啦者娱,哈哈 為了省電

寫在最后

關(guān)于7.0 以上的廣播方案抡笼,會在后面慢慢補(bǔ)充,實(shí)話說啊黄鳍,這東西真的好好看推姻,抽個(gè)空靜下心好好研究一下,這些細(xì)節(jié)上的事情框沟,都是平時(shí)開發(fā)時(shí)候的坑啊藏古。。忍燥。拧晕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市梅垄,隨后出現(xiàn)的幾起案子厂捞,更是在濱河造成了極大的恐慌,老刑警劉巖队丝,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔫敲,死亡現(xiàn)場離奇詭異,居然都是意外死亡炭玫,警方通過查閱死者的電腦和手機(jī)奈嘿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吞加,“玉大人裙犹,你說我怎么就攤上這事∠魏” “怎么了叶圃?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長践图。 經(jīng)常有香客問我掺冠,道長,這世上最難降的妖魔是什么码党? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任德崭,我火速辦了婚禮,結(jié)果婚禮上揖盘,老公的妹妹穿的比我還像新娘眉厨。我一直安慰自己,他們只是感情好兽狭,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布憾股。 她就那樣靜靜地躺著鹿蜀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪服球。 梳的紋絲不亂的頭發(fā)上茴恰,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音斩熊,去河邊找鬼往枣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛座享,可吹牛的內(nèi)容都是我干的婉商。 我是一名探鬼主播似忧,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼渣叛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盯捌?” 一聲冷哼從身側(cè)響起淳衙,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饺著,沒想到半個(gè)月后箫攀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幼衰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年靴跛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渡嚣。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡梢睛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出识椰,到底是詐尸還是另有隱情绝葡,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布腹鹉,位于F島的核電站藏畅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏功咒。R本人自食惡果不足惜愉阎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望力奋。 院中可真熱鬧诫硕,春花似錦、人聲如沸刊侯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至藕届,卻和暖如春挪蹭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背休偶。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工梁厉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人踏兜。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓词顾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碱妆。 傳聞我的和親對象是個(gè)殘疾皇子肉盹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

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