安卓--廣播機制總結_第1頁
安卓--廣播機制總結_第2頁
安卓--廣播機制總結_第3頁
安卓--廣播機制總結_第4頁
安卓--廣播機制總結_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1.Android廣播機制概述Android廣播分為兩個方面:廣播發(fā)送者和廣播接收者,通常情況下,BroadcastReceiver指的就是廣播接收者(廣播接收器)。廣播作為Android組件間的通信方式,可以使用的場景如下:1.同一app內部的同一組件內的消息通信(單個或多個線程之間);2.同一app內部的不同組件之間的消息通信(單個進程);3.同一app具有多個進程的不同組件之間的消息通信;4.不同app之間的組件之間消息通信;5.Android系統(tǒng)在特定情況下與App之間的消息通信。從實現(xiàn)原理看上,Android中的廣播使用了觀察者模式,基于消息的發(fā)布/訂閱事件模型。因此,從實現(xiàn)的角度來

2、看,Android中的廣播將廣播的發(fā)送者和接受者極大程度上解耦,使得系統(tǒng)能夠方便集成,更易擴展。具體實現(xiàn)流程要點粗略概括如下:1.廣播接收者BroadcastReceiver通過Binder機制向AMS(Activity Manager Service)進行注冊;2.廣播發(fā)送者通過binder機制向AMS發(fā)送廣播;3.AMS查找符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發(fā)送到BroadcastReceiver(一般情況下是Activity)相應的消息循環(huán)隊列中;4.消息循環(huán)執(zhí)行拿到此廣播,回調BroadcastReceiver中

3、的onReceive()方法。對于不同的廣播類型,以及不同的BroadcastReceiver注冊方式,具體實現(xiàn)上會有不同。但總體流程大致如上。由此看來,廣播發(fā)送者和廣播接收者分別屬于觀察者模式中的消息發(fā)布和訂閱兩端,AMS屬于中間的處理中心。廣播發(fā)送者和廣播接收者的執(zhí)行是異步的,發(fā)出去的廣播不會關心有無接收者接收,也不確定接收者到底是何時才能接收到。顯然,整體流程與EventBus非常類似。在上文說列舉的廣播機制具體可以使用的場景中,現(xiàn)分析實際應用中的適用性:第一種情形:同一app內部的同一組件內的消息通信(單個或多個線程之間),實際應用中肯定是不會用到廣播機制的(雖然可以用),無論是使用擴

4、展變量作用域、基于接口的回調還是Handler-post/Handler-Message等方式,都可以直接處理此類問題,若適用廣播機制,顯然有些“殺雞牛刀”的感覺,會顯太“重”;第二種情形:同一app內部的不同組件之間的消息通信(單個進程),對于此類需求,在有些教復雜的情況下單純的依靠基于接口的回調等方式不好處理,此時可以直接使用EventBus等,相對而言,EventBus由于是針對統(tǒng)一進程,用于處理此類需求非常適合,且輕松解耦。可以參見文件Android各組件/控件間通信利器之EventBus。第三、四、五情形:由于涉及不同進程間的消息通信,此時根據(jù)實際業(yè)務使用廣播機制會顯得非常適宜。下面

5、主要針對Android廣播中的具體知識點進行總結。2.BroadcastReceiver自定義BroadcastReceiver自定義廣播接收器需要繼承基類BroadcastReceivre,并實現(xiàn)抽象方法onReceive(context, intent)方法。廣播接收器接收到相應廣播后,會自動回到onReceive(.)方法。默認情況下,廣播接收器也是運行在UI線程,因此,onReceive方法中不能執(zhí)行太耗時的操作。否則將因此ANR。一般情況下,根據(jù)實際業(yè)務需求,onReceive方法中都會涉及到與其他組件之間的交互,如發(fā)送Notification、啟動service等。下面代碼片段是一

6、個簡單的廣播接收器的自定義: 1 public class MyBroadcastReceiver extends BroadcastReceiver 2 public static final String TAG = MyBroadcastReceiver; 3 public static int m = 1; 4 5 Override 6 public void onReceive(Context context, Intent intent) 7 Log.w(TAG, intent: + intent); 8 String name = intent.getStringExtra(na

7、me); 9 Log.w(TAG, name: + name + m= + m);10 m+;11 12 Bundle bundle = intent.getExtras();13 14 15 BroadcastReceiver注冊類型BroadcastReceiver總體上可以分為兩種注冊類型:靜態(tài)注冊和動態(tài)注冊。1).靜態(tài)注冊:直接在AndroidManifest.xml文件中進行注冊。規(guī)則如下:. . .其中,需要注意的屬性android:exported 此broadcastReceiver能否接收其他App的發(fā)出的廣播,這個屬性默認值有點意思,其默認值是由receiver中有無int

8、ent-filter決定的,如果有intent-filter,默認值為true,否則為false。(同樣的,activity/service中的此屬性默認值一樣遵循此規(guī)則)同時,需要注意的是,這個值的設定是以application或者application user id為界的,而非進程為界(一個應用中可能含有多個進程);android:name 此broadcastReceiver類名;android:permission 如果設置,具有相應權限的廣播發(fā)送方發(fā)送的廣播才能被此broadcastReceiver所接收;android:process broadcastReceiver運行所處的

9、進程。默認為app的進程。可以指定獨立的進程(Android四大基本組件都可以通過此屬性指定自己的獨立進程)常見的注冊形式有: 其中,intent-filter由于指定此廣播接收器將用于接收特定的廣播類型。本示例中給出的是用于接收網(wǎng)絡狀態(tài)改變或開啟啟動時系統(tǒng)自身所發(fā)出的廣播。當此App首次啟動時,系統(tǒng)會自動實例化MyBroadcastReceiver,并注冊到系統(tǒng)中。之前常說:靜態(tài)注冊的廣播接收器即使app已經(jīng)退出,主要有相應的廣播發(fā)出,依然可以接收到,但此種描述自Android 3.1開始有可能不再成立,具體分析詳見本文后面部分。2).動態(tài)注冊:動態(tài)注冊時,無須在AndroidManifes

10、t中注冊組件。直接在代碼中通過調用Context的registerReceiver函數(shù),可以在程序中動態(tài)注冊BroadcastReceiver。registerReceiver的定義形式如下:1 registerReceiver(BroadcastReceiver receiver, IntentFilter filter)2 registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)典型的寫法示例如下: 1 public cla

11、ss MainActivity extends Activity 2 public static final String BROADCAST_ACTION = com.example.corn; 3 private BroadcastReceiver mBroadcastReceiver; 4 5 Override 6 protected void onCreate(Bundle savedInstanceState) 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 mB

12、roadcastReceiver = new MyBroadcastReceiver();11 IntentFilter intentFilter = new IntentFilter();12 intentFilter.addAction(BROADCAST_ACTION);13 registerReceiver(mBroadcastReceiver, intentFilter);14 15 16 Override17 protected void onDestroy() 18 super.onDestroy();19 unregisterReceiver(mBroadcastReceive

13、r);20 21 22 注:Android中所有與觀察者模式有關的設計中,一旦涉及到register,必定在相應的時機需要unregister。因此,上例在onDestroy()回到中需要unregisterReceiver(mBroadcastReceiver)。當此Activity實例化時,會動態(tài)將MyBroadcastReceiver注冊到系統(tǒng)中。當此Activity銷毀時,動態(tài)注冊的MyBroadcastReceiver將不再接收到相應的廣播。3.廣播發(fā)送及廣播類型經(jīng)常說”發(fā)送廣播“和”接收“,表面上看廣播作為Android廣播機制中的實體,實際上這一實體本身是并不是以所謂的”廣播“對

14、象存在的,而是以”意圖“(Intent)去表示。定義廣播的定義過程,實際就是相應廣播”意圖“的定義過程,然后通過廣播發(fā)送者將此”意圖“發(fā)送出去。被相應的BroadcastReceiver接收后將會回調onReceive()函數(shù)。下段代碼片段顯示的是一個普通廣播的定義過程,并發(fā)送出去。其中setAction(.)對應于BroadcastReceiver中的intentFilter中的action。1 Intent intent = new Intent();2 intent.setAction(BROADCAST_ACTION);3 intent.putExtra(name, qqyumidi)

15、;4 sendBroadcast(intent);根據(jù)廣播的發(fā)送方式,可以將其分為以下幾種類型:1.Normal Broadcast:普通廣播2.System Broadcast: 系統(tǒng)廣播3.Ordered broadcast:有序廣播4.Sticky Broadcast:粘性廣播(在 android 5.0/api 21中deprecated,不再推薦使用,相應的還有粘性有序廣播,同樣已經(jīng)deprecated)5.Local Broadcast:App應用內廣播下面分別總結下各種類型的發(fā)送方式及其特點。1).Normal Broadcast:普通廣播此處將普通廣播界定為:開發(fā)者自己定義的i

16、ntent,以context.sendBroadcast_AsUser(intent, .)形式。具體可以使用的方法有:sendBroadcast(intent)/sendBroadcast(intent, receiverPermission)/sendBroadcastAsUser(intent, userHandler)/sendBroadcastAsUser(intent, userHandler,receiverPermission)。普通廣播會被注冊了的相應的感興趣(intent-filter匹配)接收,且順序是無序的。如果發(fā)送廣播時有相應的權限要求,BroadCastReceiv

17、er如果想要接收此廣播,也需要有相應的權限。2).System Broadcast: 系統(tǒng)廣播Android系統(tǒng)中內置了多個系統(tǒng)廣播,只要涉及到手機的基本操作,基本上都會發(fā)出相應的系統(tǒng)廣播。如:開啟啟動,網(wǎng)絡狀態(tài)改變,拍照,屏幕關閉與開啟,點亮不足等等。每個系統(tǒng)廣播都具有特定的intent-filter,其中主要包括具體的action,系統(tǒng)廣播發(fā)出后,將被相應的BroadcastReceiver接收。系統(tǒng)廣播在系統(tǒng)內部當特定事件發(fā)生時,有系統(tǒng)自動發(fā)出。3)Ordered broadcast:有序廣播有序廣播的有序廣播中的“有序”是針對廣播接收者而言的,指的是發(fā)送出去的廣播被BroadcastR

18、eceiver按照先后循序接收。有序廣播的定義過程與普通廣播無異,只是其的主要發(fā)送方式變?yōu)椋簊endOrderedBroadcast(intent, receiverPermission, .)。對于有序廣播,其主要特點總結如下:1多個具當前已經(jīng)注冊且有效的BroadcastReceiver接收有序廣播時,是按照先后順序接收的,先后順序判定標準遵循為:將當前系統(tǒng)中所有有效的動態(tài)注冊和靜態(tài)注冊的BroadcastReceiver按照priority屬性值從大到小排序,對于具有相同的priority的動態(tài)廣播和靜態(tài)廣播,動態(tài)廣播會排在前面。2先接收的BroadcastReceiver可以對此有序廣

19、播進行截斷,使后面的BroadcastReceiver不再接收到此廣播,也可以對廣播進行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯誤的參數(shù)值。當然,一般情況下,不建議對有序廣播進行此類操作,尤其是針對系統(tǒng)中的有序廣播。4)Sticky Broadcast:粘性廣播(在 android 5.0/api 21中deprecated,不再推薦使用,相應的還有粘性有序廣播,同樣已經(jīng)deprecated)。既然已經(jīng)deprecated,此處不再多做總結。5)Local Broadcast:App應用內廣播(此處的App應用以App應用進程為界)由前文闡述可知,Android中

20、的廣播可以跨進程甚至跨App直接通信,且注冊是exported對于有intent-filter的情況下默認值是true,由此將可能出現(xiàn)安全隱患如下:1.其他App可能會針對性的發(fā)出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收到廣播并處理;2.其他App可以注冊與當前App一致的intent-filter用于接收廣播,獲取廣播具體信息。無論哪種情形,這些安全隱患都確實是存在的。由此,最常見的增加安全性的方案是:1.對于同一App內部發(fā)送和接收廣播,將exported屬性人為設置成false,使得非本App內部發(fā)出的此廣播不被接收;2.在廣播發(fā)送和接收時,都增加

21、上相應的permission,用于權限驗證;3.發(fā)送廣播時,指定特定廣播接收器所在的包名,具體是通過intent.setPackage(packageName)指定在,這樣此廣播將只會發(fā)送到此包中的App內與之相匹配的有效廣播接收器中。App應用內廣播可以理解成一種局部廣播的形式,廣播的發(fā)送者和接收者都同屬于一個App。實際的業(yè)務需求中,App應用內廣播確實可能需要用到。同時,之所以使用應用內廣播時,而不是使用全局廣播的形式,更多的考慮到的是Android廣播機制中的安全性問題。相比于全局廣播,App應用內廣播優(yōu)勢體現(xiàn)在:1.安全性更高;2.更加高效。為此,Android v4兼容包中給出了封

22、裝好的LocalBroadcastManager類,用于統(tǒng)一處理App應用內的廣播問題,使用方式上與通常的全局廣播幾乎相同,只是注冊/取消注冊廣播接收器和發(fā)送廣播時將主調context變成了LocalBroadcastManager的單一實例。代碼片段如下: 1 /registerReceiver(mBroadcastReceiver, intentFilter); 2 /注冊應用內廣播接收器 3 localBroadcastManager = LocalBroadcastManager.getInstance(this); 4 localBroadcastManager.registerRe

23、ceiver(mBroadcastReceiver, intentFilter); 5 6 /unregisterReceiver(mBroadcastReceiver); 7 /取消注冊應用內廣播接收器 8 localBroadcastManager.unregisterReceiver(mBroadcastReceiver); 9 10 Intent intent = new Intent();11 intent.setAction(BROADCAST_ACTION);12 intent.putExtra(name, qqyumidi);13 /sendBroadcast(intent);

24、14 /發(fā)送應用內廣播15 localBroadcastManager.sendBroadcast(intent);4.不同注冊方式的廣播接收器回調onReceive(context, intent)中的context具體類型1).對于靜態(tài)注冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是ReceiverRestrictedContext;2).對于全局廣播的動態(tài)注冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是Activity Context;3).

25、對于通過LocalBroadcastManager動態(tài)注冊的ContextReceiver,回調onReceive(context, intent)中的context具體指的是Application Context。注:對于LocalBroadcastManager方式發(fā)送的應用內廣播,只能通過LocalBroadcastManager動態(tài)注冊的ContextReceiver才有可能接收到(靜態(tài)注冊或其他方式動態(tài)注冊的ContextReceiver是接收不到的)。5.不同Android API版本中廣播機制相關API重要變遷1).Android5.0/API level 21開始粘滯廣播和有序

26、粘滯廣播過期,以后不再建議使用;2).”靜態(tài)注冊的廣播接收器即使app已經(jīng)退出,主要有相應的廣播發(fā)出,依然可以接收到,但此種描述自Android 3.1開始有可能不再成立“Android 3.1開始系統(tǒng)在Intent與廣播相關的flag增加了參數(shù),分別是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。FLAG_INCLUDE_STOPPED_PACKAGES:包含已經(jīng)停止的包(停止:即包所在的進程已經(jīng)退出)FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經(jīng)停止的包主要原因如下:自Android3.1開始,系統(tǒng)本身則增加了對

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論