Broadcast

http://blog.csdn.net/jiangwei0910410003/article/details/19150705
http://blog.csdn.net/as02446418/article/details/46930005

     廣播(Broadcast):顧名思義,就是一處發出通知,多處得到通知後分別進行處理。和觀察者模式有相似之處。一般Activity發送廣播。當需要App應用內通信時,優先選擇觀察者或者Eventbus,當需要進程間通信或者監聽系統廣播事件時,選擇Broadcast。
依據Broadcast的作用,可以將廣播分爲三種:
1,一般廣播:完全異步的,可以在同一時刻(邏輯上)被所有廣播接收者接收到,消息傳遞的效率比較高    Context.sendBroadcast()   
2,有序廣播,所有receiver只能按照一定的優先級(靜態廣播:聲明在intent-filter元素的android:priority屬性中,數越大優先級別越高,取值範圍:-1000到1000。動態廣播:調用IntentFilter對象的setPriority()進行設置)順序,依次接收並且處理;不僅如此,前面的receiver不僅可以將額外的信息塞入廣播還可以終止廣播。   Context.sendOrderedBroadcast()
abortBroadcast();//終止此次廣播的傳輸
3,粘性廣播: 可以保證“在廣播遞送時尚未註冊的receiver”,一旦日後註冊進系統,就能夠馬上接到“錯過”的sticky廣播。這是一種很神奇的廣播,我覺得關機時的來電(開機後,收到錯過電話的通知)應該就是這種廣播。(BatteryService通過sendIntentLocke 來告知用戶電量發生變化。系統發出這個廣播並不是時刻在發,而我們卻能立即得到系統當前電量。broadcastStickyIntent)
二、廣播接收器:
第一步:定義廣播接收器,繼承BroadcastReceiver,並重寫onReceive()方法。
    public class IncomingSMSReceiver extends BroadcastReceiver {  
      @Override public void onReceive(Contextcontext, Intentintent) {  
      }  
    }  
第二步:訂閱感興趣的廣播Intent,訂閱方法有兩種:
1.使用代碼進行訂閱(動態訂閱)當應用程序結束了,廣播自然就沒有了,比如你在activity中的onCreate或者onResume中訂閱廣播,同時你必須在onDestory或者onPause中取消廣播訂閱。不然會報異常。
//註冊廣播
IntentFilter filter = newIntentFilter("android.provider.Telephony.SMS_RECEIVED");  
IncomingSMSReceiver receiver = newIncomingSMSReceiver();  
registerReceiver(receiver, filter);
//取消廣播  
unregisterReceiver(receiver);
2.在AndroidManifest.xml文件中的<application>節點裏進行訂閱(靜態訂閱):常駐型廣播,當你的應用程序關閉了,如果有廣播信息來,你寫的廣播接收器同樣的能接受到。
    <receiver android:name=".IncomingSMSReceiver">  
       <intent-filter>  
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
       </intent-filter>  
    </receiver>  

<receiver android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</receiver>
android:exported ——此broadcastReceiver能否接收其他App的發出的廣播,這個屬性默認值有點意思,其默認值是由receiver中有無intent-filter決定的,如果有intent-filter,默認值爲true,否則爲false。(同樣的,activity/service中的此屬性默認值一樣遵循此規則)同時,需要注意的是,這個值的設定是以application或者application user id爲界的,而非進程爲界(一個應用中可能含有多個進程);
android:name —— 此broadcastReceiver類名;
android:permission ——如果設置,具有相應權限的廣播發送方發送的廣播才能被此broadcastReceiver所接收;
android:process ——broadcastReceiver運行所處的進程。默認爲app的進程。可以指定獨立的進程(Android四大基本組件都可以通過此屬性指定自己的獨立進程)

1.廣播接收者BroadcastReceiver通過Binder機制向AMS(Activity Manager Service)進行註冊;
2.廣播發送者通過binder機制向AMS發送廣播;
3.AMS查找符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發送到BroadcastReceiver(一般情況下是Activity)相應的消息循環隊列中;
4.消息循環執行拿到此廣播,回調BroadcastReceiver中的onReceive()方法。

廣播發送者和廣播接收者分別屬於觀察者模式中的消息發佈和訂閱兩端,AMS屬於中間的處理中心。廣播發送者和廣播接收者的執行是異步的,發出去的廣播不會關心有無接收者接收,也不確定接收者到底是何時才能接收到。顯然,整體流程與EventBus非常類似。

發送廣播時,指定特定廣播接收器所在的包名,具體是通過intent.setPackage(packageName)指定在,這樣此廣播將只會發送到此包中的App內與之相匹配的有效廣播接收器中。

對於靜態註冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是ReceiverRestrictedContext;對於全局廣播的動態註冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是Activity Context;對於通過LocalBroadcastManager動態註冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是Application Context。對於LocalBroadcastManager方式發送的應用內廣播,只能通過LocalBroadcastManager動態註冊的ContextReceiver纔有可能接收到(靜態註冊或其他方式動態註冊的ContextReceiver是接收不到的)。
本地廣播的優勢
1.可以明確的知道正在發送的廣播不會離開我們的程序,因此不用擔心機密數據泄露問題
2.其他程序無法將廣播發送到我們程序的內部,因此不需要擔心會有安全漏洞的隱患
3.發送本地廣播要比全局廣播更加高效
封裝好的LocalBroadcastManager類,用於統一處理App應用內的廣播問題,使用方式上與通常的全局廣播幾乎相同,只是註冊/取消註冊廣播接收器和發送廣播時將主調context變成了LocalBroadcastManager的單一實例。
 //registerReceiver(mBroadcastReceiver, intentFilter);
  //註冊應用內廣播接收器

localBroadcastManager = LocalBroadcastManager.getInstance(this);    //獲取本地廣播管理器的實例
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
mBroadcastReceiver = new mBroadcastReceiver();
localBroadcastManager.registerReceiver(mBroadcastReceiver,intentFilter);

  //取消註冊應用內廣播接收器
  localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

 Intent intent = new Intent();
 intent.setAction(BROADCAST_ACTION);
 intent.putExtra("name", "qqyumidi");
 //sendBroadcast(intent);


 //unregisterReceiver(mBroadcastReceiver);

BroadcastReceiver的使用場景:
  • App全局監聽,這種主要用於在AndroidManifest中靜態註冊的廣播接收器,一般我們在收到該消息後,需要做一些相應的動作,而這些動作與當前App的組件,比如Activity或者Service的是否運行無關,比如我們在集成第三方Push SDK時,一般都會添加一個靜態註冊的BroadcastReceiver來監聽Push消息,當有Push消息過來時,會在後臺做一些網絡請求或者發送通知等等。
  • 組件局部監聽,這種主要是在Activity或者Service中使用registerReceiver()動態註冊的廣播接收器,因爲當我們收到一些特定的消息,比如網絡連接發生變化時,我們可能需要在當前Activity頁面給用戶一些UI上的提示,或者將Service中的網絡請求任務暫停。所以這種動態註冊的廣播接收器適合特定組件的特定消息處理。
關於BroadcastReceiver使用需要注意的幾點:
  • onReceive中不能執行耗時操作,如果耗時超過10s會彈出ANR。
  • onReceive中context參數,如果是靜態註冊的廣播,context爲ReceiverRestrictedContext,所在如果在這裏要啓動一個Activity的話(調用startActivity),需要在intent中添加Intent.FLAG_ACTIVITY_NEW_TASK;如果是動態註冊的廣播,context爲當前註冊時所在的組件,比如Activity或者Service。
  • 監聽系統廣播,需要在AndroidManifest中申請權限,此外,Android高版本系統對於一些重要的系統廣播,比如開機啓動,網絡連接,電量變化,鎖屏等做了限制,如果需要監聽這些廣播,需要做系統兼容性處理。





































發佈了40 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章