Android面試收集錄2 Broadcast Receiver詳解

來源:互聯網
上載者:User

標籤:問題   使用   mode   main   相同   enabled   android面試   直接   兩種   


1.Broadcast Receiver廣播接收器簡單介紹

1.1.定義

  • Broadcast Receiver(廣播接收器),屬於Android四大組件之一
  • 在Android開發中,Broadcast Receiver的應用情境非常多。廣播,是一個全域的監聽器,屬於Android四大組件。

  Android 廣播分為兩個角色:廣播寄件者,廣播接收者。

 

 

 

1.2.作用

  • 用於監聽/接收 應用發出的廣播訊息,並做出響應。
  • 應用情境

    a.不同組件之間通訊(包括應用內/不同應用之間)

    b.與Android系統在特定情況下的通訊(如當電話呼入時、網路可用時)

    c.多線程通訊

 

 

 

1.3.實現原理

  Android中的廣播使用了設計模式中的觀察者模式:基於訊息的發布/訂閱事件模型。

  因此,Android將廣播的寄件者和接收者解耦,使得系統方便整合,更易擴充。

 

  模型中有3個角色:

  i.訊息訂閱者(廣播接收者)

  ii.訊息發行者(廣播發行者)

  iii.訊息中心(AMS,即Activity Manager Service)

  

 

  原理描述:

  i.廣播接收者 通過Binder機制在AMS註冊

  ii.廣播寄件者通過Binder機制向AMS發送廣播

  iii.AMS根據廣播寄件者要求,在登入列表中,尋找合適的廣播接收者

    尋找依據:IntentFilter/Permission

  iv.AMS將廣播發送到合適的廣播接收者相應的訊息迴圈隊列中

  v.廣播接收者通過訊息迴圈拿到此廣播,並回調onReceiver()

  

  特別注意:

  廣播寄件者和廣播接收者的執行是非同步,發出去的廣播不會關心有無接收者接收,也不確定接收者到底是何時才能接收到;

  


2.Broadcast Receiver使用方法

具體使用流程如下:

 

  接下來一步一步介紹中開發人員手動完成部分:

  

 

 

4.1.自訂廣播接收者BroadcastReceiver

  • 繼承自BroadcastReceiver基類
  • 必須複寫抽象方法onReceive()方法

    i.廣播接收器接收到相應廣播後,會自動回調onReceive()方法。

    ii.一般情況下,onReceive方法會涉及與其他組件之間的互動,如發送Notification,啟動Service等

    iii.預設情況下,廣播接收器運行在UI線程,因此,onReceive方法不能執行耗時操作,否則將導致ANR。

  • 代碼範例 mBroadcastReceiver.java

   

public class mBroadcastReceiver extends BroadcastReceiver {  //接收到廣播後自動調用該方法  @Override  public void onReceive(Context context, Intent intent) {    //寫入接收廣播後的操作    }}

 

 

 

 

4.2.廣播接收器註冊

  註冊的方式分為兩種:靜態註冊、動態註冊

  

  靜態註冊:

    在AndroidManifest.xml通過<receive>標籤聲明

    屬性說明:

<receiver  android:enabled=["true" | "false"]  //此broadcastReceiver能否接收其他App的發出的廣播  //預設值是由receiver中有無intent-filter決定的:如果有intent-filter,預設值為true,否則為false  android:exported=["true" | "false"]  android:icon="drawable resource"  android:label="string resource"  //繼承BroadcastReceiver子類的類名  android:name=".mBroadcastReceiver"  //具有相應許可權的廣播寄件者發送的廣播才能被此BroadcastReceiver所接收;  android:permission="string"  //BroadcastReceiver運行所處的進程  //預設為app的進程,可以指定獨立的進程  //註:Android四大基本組件都可以通過此屬性指定自己的獨立進程  android:process="string" >  //用於指定此廣播接收器將接收的廣播類型  //本樣本中給出的是用於接收網路狀態改變時發出的廣播  <intent-filter>    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />  </intent-filter></receiver>

  註冊樣本:

<receiver  //此廣播接收者類是mBroadcastReceiver  android:name=".mBroadcastReceiver" >  //用於接收網路狀態改變時發出的廣播  <intent-filter>      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />  </intent-filter></receiver>

  當此APP初次開機時,系統會自動執行個體化mBroadcastReceiver類,並註冊到系統中。

 

 

  動態註冊:

  在代碼中通過調用Context的*registerReceiver()*方法進行動態註冊BroadcastReceiver,具體代碼如下:

  

@Overrideprotected void onResume() {    super.onResume();    //執行個體化BroadcastReceiver子類 &  IntentFilter    mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();    IntentFilter intentFilter = new IntentFilter();    //設定接收廣播的類型    intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);    //調用Context的registerReceiver()方法進行動態註冊    registerReceiver(mBroadcastReceiver, intentFilter);}//註冊廣播後,要在相應位置記得銷毀廣播//即在onPause() 中unregisterReceiver(mBroadcastReceiver)//當此Activity執行個體化時,會動態將MyBroadcastReceiver註冊到系統中//當此Activity銷毀時,動態註冊的MyBroadcastReceiver將不再接收到相應的廣播。@Overrideprotected void onPause() {    super.onPause();    //銷毀在onResume()方法中的廣播    unregisterReceiver(mBroadcastReceiver);}

 

  特別注意:

    動態廣播最好在Activity的onResume()註冊,onPause()登出。

  原因:

    對於動態廣播,有註冊就必然得有登出,否則會導致記憶體流失。重複註冊,重複登出也不允許。

 

 

  兩種註冊方式的區別:

  

 

 

 

4.3.廣播寄件者向AMS發送廣播

 

  廣播的發送:

  • 廣播是用”意圖(Intent)“標識
  • 定義廣播的本質:定義廣播所具備的“意圖(Intent)”
  • 廣播發送:廣播寄件者將此廣播的”意圖“通過sendBroadcast()方法發送出去

 

  廣播的類型:

  廣播的類型主要分為5類:

  • 普通廣播(Normal Broadcast)
  • 系統廣播(System Broadcast)
  • 有序廣播(Ordered Broadcast)
  • 粘性廣播(Sticky Broadcast)
  • App應用內廣播(Local Broadcast)

 

  具體說明如下:

  

  ①. 普通廣播(Normal Broadcast)

    即開發人員自身定義intent的廣播(最常用)。發送廣播使用如下:

    

Intent intent = new Intent();//對應BroadcastReceiver中intentFilter的actionintent.setAction(BROADCAST_ACTION);//發送廣播sendBroadcast(intent);

  若被註冊了的廣播接收者中註冊時intentFilter的action與上述匹配,則會接收此廣播(即進行回調onReceive())。

  如下mBroadcastReceiver則會接收上述廣播

  

<receiver     //此廣播接收者類是mBroadcastReceiver    android:name=".mBroadcastReceiver" >    //用於接收網路狀態改變時發出的廣播    <intent-filter>        <action android:name="BROADCAST_ACTION" />    </intent-filter></receiver>

  

  若發送廣播有相應許可權,那麼廣播接收者也需要相應許可權

 

  

  ②. 系統廣播(System Broadcast)

  

  • Android中內建了多個系統廣播:只要涉及到手機的基本操作(如開機、網路狀態變化、拍照等等),都會發出相應的廣播
  • 每個廣播都有特定的Intent - Filter(包括具體的action),Android系統廣播action如下:

 

系統操作 action
監聽網路變化 android.net.conn.CONNECTIVITY_CHANGE
關閉或開啟飛航模式 Intent.ACTION_AIRPLANE_MODE_CHANGED
充電時或電量發生變化 Intent.ACTION_BATTERY_CHANGED
電池電量低 Intent.ACTION_BATTERY_LOW
電池電量充足(即從電量低變化到飽滿時會發出廣播 Intent.ACTION_BATTERY_OKAY
系統啟動完成後(僅廣播一次) Intent.ACTION_BOOT_COMPLETED
按下照相時的拍照按鍵(硬體按鍵)時 Intent.ACTION_CAMERA_BUTTON
螢幕鎖屏 Intent.ACTION_CLOSE_SYSTEM_DIALOGS
裝置當前設定被改變時(介面語言、裝置方向等) Intent.ACTION_CONFIGURATION_CHANGED
插入耳機時 Intent.ACTION_HEADSET_PLUG
未正確移除SD卡但已取出來時(正確移除方法:設定--SD卡和裝置記憶體--卸載SD卡) Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部儲存裝置(如SD卡) Intent.ACTION_MEDIA_CHECKING
成功安裝APK Intent.ACTION_PACKAGE_ADDED
成功刪除APK Intent.ACTION_PACKAGE_REMOVED
重啟裝置 Intent.ACTION_REBOOT
螢幕被關閉 Intent.ACTION_SCREEN_OFF
螢幕被開啟 Intent.ACTION_SCREEN_ON
關閉系統時 Intent.ACTION_SHUTDOWN
重啟裝置 Intent.ACTION_REBOOT

 

  注意:

    當使用系統廣播時,只需要在註冊廣播接收者時定義相關的action即可,

    並不需要手動發送廣播,當系統有相關操作時會自動進行系統廣播。

 

 

  ③. 有序廣播(Ordered Broadcast)

 

  定義發送出去的廣播被廣播接收者按照先後順序接收,有序是針對廣播接收者而言的。

 

  廣播接受者接收廣播的順序規則(同時面向靜態和動態註冊的廣播接受者)

    i.按照Priority屬性值從大到小排序;

    ii.Priority屬性相同者,動態註冊的廣播優先;

  特點:

    i.接收廣播按順序接收

     ii.先接收的廣播接收者可以對廣播進行截斷,即後接收的廣播接收者不再接收到此廣播;

    iii.先接收的廣播接收者可以對廣播進行修改,那麼後接收的廣播接收者將接收到被修改後的廣播

 

  具體使用:

    有序廣播的使用過程與普通廣播非常類似,差異僅在於廣播的發送方式:

    

sendOrderedBroadcast(intent);

 

 

  ④. App應用內廣播(Local Broadcast)

 

  背景:

     Android中的廣播可以跨App直接通訊(exported對於有intent-filter情況下預設值為true)

 

  衝突:

    可能出現的問題

    其他App針對性發出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收廣播並處理;

    其他App註冊與當前App一致的intent-filter用於接收廣播,擷取廣播具體資訊; 即會出現安全性 & 效率性的問題。

 

  解決方案:

    使用APP應用內廣播(Local Broadcast)  

    App應用內廣播可理解為一種局部廣播,廣播的寄件者和接收者都同屬於一個App。

    相比於全域廣播(普通廣播),App應用內廣播優勢體現在:安全性高 & 效率高

 

  具體使用1-將全域廣播設定成局部廣播

    註冊廣播時將exported屬性設定為false,使得非本App內部發出的此廣播不被接收;

    在廣播發送和接收時,增設相應許可權permission,用於許可權驗證;

    發送廣播時指定該廣播接收器所在的包名,此廣播將只會發送到此包中的App內與之相匹配的有效廣播接收器中。

    通過intent.setPackage(packageName)指定報名

 

  

  具體使用2 - 使用封裝好的LocalBroadcastManager類 使用方式上與全域廣播幾乎相同,

    只是註冊/取消註冊廣播接收器和發送廣播時將參數的context變成了LocalBroadcastManager的單一執行個體

    注意:

      對於LocalBroadcastManager方式發送的應用內廣播,只能通過LocalBroadcastManager動態註冊,不能靜態註冊

    

//註冊應用內廣播接收器//步驟1:執行個體化BroadcastReceiver子類 & IntentFilter mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); //步驟2:執行個體化LocalBroadcastManager的執行個體localBroadcastManager = LocalBroadcastManager.getInstance(this);//步驟3:設定接收廣播的類型 intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);//步驟4:調用LocalBroadcastManager單一執行個體的registerReceiver()方法進行動態註冊 localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);//取消註冊應用內廣播接收器localBroadcastManager.unregisterReceiver(mBroadcastReceiver);//發送應用內廣播Intent intent = new Intent();intent.setAction(BROADCAST_ACTION);localBroadcastManager.sendBroadcast(intent);

 

  

  ⑤. 粘性廣播(Sticky Broadcast)

    由於在Android5.0 & API 21中已經失效,所以不建議使用,在這裡也不作過多的總結。

  


3.參考文章

3.1.以上內容全部來自於以下網址

  https://github.com/LRH1993/android_interview/blob/master/android/basis/broadcastreceiver.md

 


Android面試收集錄2 Broadcast Receiver詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.