国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android BroadcastReceiver廣播機(jī)制概述

2019-12-12 05:29:02
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

Android廣播機(jī)制概述
Android廣播分為兩個(gè)方面:廣播發(fā)送者和廣播接收者,通常情況下,BroadcastReceiver指的就是廣播接收者(廣播接收器)。廣播作為Android組件間的通信方式,可以使用的場(chǎng)景如下:

1.同一app內(nèi)部的同一組件內(nèi)的消息通信(單個(gè)或多個(gè)線程之間);
2.同一app內(nèi)部的不同組件之間的消息通信(單個(gè)進(jìn)程); 
3.同一app具有多個(gè)進(jìn)程的不同組件之間的消息通信; 
4.不同app之間的組件之間消息通信; 
5.Android系統(tǒng)在特定情況下與App之間的消息通信。 

從實(shí)現(xiàn)原理看上,Android中的廣播使用了觀察者模式,基于消息的發(fā)布/訂閱事件模型。因此,從實(shí)現(xiàn)的角度來(lái)看,Android中的廣播將廣播的發(fā)送者和接受者極大程度上解耦,使得系統(tǒng)能夠方便集成,更易擴(kuò)展。具體實(shí)現(xiàn)流程要點(diǎn)粗略概括如下:
1.廣播接收者BroadcastReceiver通過(guò)Binder機(jī)制向AMS(Activity Manager Service)進(jìn)行注冊(cè); 
2.廣播發(fā)送者通過(guò)binder機(jī)制向AMS發(fā)送廣播; 
3.AMS查找符合相應(yīng)條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發(fā)送到BroadcastReceiver(一般情況下是Activity)相應(yīng)的消息循環(huán)隊(duì)列中; 
4.消息循環(huán)執(zhí)行拿到此廣播,回調(diào)BroadcastReceiver中的onReceive()方法。

對(duì)于不同的廣播類型,以及不同的BroadcastReceiver注冊(cè)方式,具體實(shí)現(xiàn)上會(huì)有不同。但總體流程大致如上。 

由此看來(lái),廣播發(fā)送者和廣播接收者分別屬于觀察者模式中的消息發(fā)布和訂閱兩端,AMS屬于中間的處理中心。廣播發(fā)送者和廣播接收者的執(zhí)行是異步的,發(fā)出去的廣播不會(huì)關(guān)心有無(wú)接收者接收,也不確定接收者到底是何時(shí)才能接收到。顯然,整體流程與EventBus非常類似。 

在上文說(shuō)列舉的廣播機(jī)制具體可以使用的場(chǎng)景中,現(xiàn)分析實(shí)際應(yīng)用中的適用性: 

第一種情形:同一app內(nèi)部的同一組件內(nèi)的消息通信(單個(gè)或多個(gè)線程之間),實(shí)際應(yīng)用中肯定是不會(huì)用到廣播機(jī)制的(雖然可以用),無(wú)論是使用擴(kuò)展變量作用域、基于接口的回調(diào)還是Handler-post/Handler-Message等方式,都可以直接處理此類問(wèn)題,若適用廣播機(jī)制,顯然有些“殺雞牛刀”的感覺(jué),會(huì)顯太“重”; 

第二種情形:同一app內(nèi)部的不同組件之間的消息通信(單個(gè)進(jìn)程),對(duì)于此類需求,在有些教復(fù)雜的情況下單純的依靠基于接口的回調(diào)等方式不好處理,此時(shí)可以直接使用EventBus等,相對(duì)而言,EventBus由于是針對(duì)統(tǒng)一進(jìn)程,用于處理此類需求非常適合,且輕松解耦。可以參見文件《Android各組件/控件間通信利器之EventBus》。 

第三、四、五情形:由于涉及不同進(jìn)程間的消息通信,此時(shí)根據(jù)實(shí)際業(yè)務(wù)使用廣播機(jī)制會(huì)顯得非常適宜。下面主要針對(duì)Android廣播中的具體知識(shí)點(diǎn)進(jìn)行總結(jié)。

2.BroadcastReceiver 

自定義BroadcastReceiver 

自定義廣播接收器需要繼承基類BroadcastReceivre,并實(shí)現(xiàn)抽象方法onReceive(context, intent)方法。廣播接收器接收到相應(yīng)廣播后,會(huì)自動(dòng)回到onReceive(..)方法。默認(rèn)情況下,廣播接收器也是運(yùn)行在UI線程,因此,onReceive方法中不能執(zhí)行太耗時(shí)的操作。否則將因此ANR。一般情況下,根據(jù)實(shí)際業(yè)務(wù)需求,onReceive方法中都會(huì)涉及到與其他組件之間的交互,如發(fā)送Notification、啟動(dòng)service等。
下面代碼片段是一個(gè)簡(jiǎn)單的廣播接收器的自定義: 

public class MyBroadcastReceiver extends BroadcastReceiver {  public static final String TAG = "MyBroadcastReceiver";  public static int m = 1;  @Override  public void onReceive(Context context, Intent intent) {    Log.w(TAG, "intent:" + intent);    String name = intent.getStringExtra("name");    Log.w(TAG, "name:" + name + " m=" + m);    m++;        Bundle bundle = intent.getExtras();      }}

BroadcastReceiver注冊(cè)類型 
BroadcastReceiver總體上可以分為兩種注冊(cè)類型:靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)。 
1).靜態(tài)注冊(cè):
直接在AndroidManifest.xml文件中進(jìn)行注冊(cè)。規(guī)則如下: 

<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的發(fā)出的廣播,這個(gè)屬性默認(rèn)值有點(diǎn)意思,其默認(rèn)值是由receiver中有無(wú)intent-filter決定的,如果有intent-filter,默認(rèn)值為true,否則為false。(同樣的,activity/service中的此屬性默認(rèn)值一樣遵循此規(guī)則)同時(shí),需要注意的是,這個(gè)值的設(shè)定是以application或者application user id為界的,而非進(jìn)程為界(一個(gè)應(yīng)用中可能含有多個(gè)進(jìn)程);
android:name  ―― 此broadcastReceiver類名;
android:permission  ――如果設(shè)置,具有相應(yīng)權(quán)限的廣播發(fā)送方發(fā)送的廣播才能被此broadcastReceiver所接收;
android:process  ――broadcastReceiver運(yùn)行所處的進(jìn)程。默認(rèn)為app的進(jìn)程??梢灾付í?dú)立的進(jìn)程(Android四大基本組件都可以通過(guò)此屬性指定自己的獨(dú)立進(jìn)程) 

常見的注冊(cè)形式有: 

<receiver android:name=".MyBroadcastReceiver" >  <intent-filter>    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />  </intent-filter>  <intent-filter>    <action android:name="android.intent.action.BOOT_COMPLETED" />  </intent-filter></receiver> 

其中,intent-filter由于指定此廣播接收器將用于接收特定的廣播類型。本示例中給出的是用于接收網(wǎng)絡(luò)狀態(tài)改變或開啟啟動(dòng)時(shí)系統(tǒng)自身所發(fā)出的廣播。當(dāng)此App首次啟動(dòng)時(shí),系統(tǒng)會(huì)自動(dòng)實(shí)例化MyBroadcastReceiver,并注冊(cè)到系統(tǒng)中。 

之前常說(shuō):靜態(tài)注冊(cè)的廣播接收器即使app已經(jīng)退出,主要有相應(yīng)的廣播發(fā)出,依然可以接收到,但此種描述自Android 3.1開始有可能不再成立,具體分析詳見本文后面部分。 

2).動(dòng)態(tài)注冊(cè):
動(dòng)態(tài)注冊(cè)時(shí),無(wú)須在AndroidManifest中注冊(cè)<receiver/>組件。直接在代碼中通過(guò)調(diào)用Context的registerReceiver函數(shù),可以在程序中動(dòng)態(tài)注冊(cè)BroadcastReceiver。registerReceiver的定義形式如下: 

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

典型的寫法示例如下: 

public class MainActivity extends Activity {  public static final String BROADCAST_ACTION = "com.example.corn";  private BroadcastReceiver mBroadcastReceiver;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mBroadcastReceiver = new MyBroadcastReceiver();    IntentFilter intentFilter = new IntentFilter();    intentFilter.addAction(BROADCAST_ACTION);    registerReceiver(mBroadcastReceiver, intentFilter);  }    @Override  protected void onDestroy() {    super.onDestroy();    unregisterReceiver(mBroadcastReceiver);  }}

注:Android中所有與觀察者模式有關(guān)的設(shè)計(jì)中,一旦涉及到register,必定在相應(yīng)的時(shí)機(jī)需要unregister。因此,上例在onDestroy()回到中需要unregisterReceiver(mBroadcastReceiver)。 

當(dāng)此Activity實(shí)例化時(shí),會(huì)動(dòng)態(tài)將MyBroadcastReceiver注冊(cè)到系統(tǒng)中。當(dāng)此Activity銷毀時(shí),動(dòng)態(tài)注冊(cè)的MyBroadcastReceiver將不再接收到相應(yīng)的廣播。

3.廣播發(fā)送及廣播類型

 經(jīng)常說(shuō)”發(fā)送廣播“和”接收“,表面上看廣播作為Android廣播機(jī)制中的實(shí)體,實(shí)際上這一實(shí)體本身是并不是以所謂的”廣播“對(duì)象存在的,而是以”意圖“(Intent)去表示。定義廣播的定義過(guò)程,實(shí)際就是相應(yīng)廣播”意圖“的定義過(guò)程,然后通過(guò)廣播發(fā)送者將此”意圖“發(fā)送出去。被相應(yīng)的BroadcastReceiver接收后將會(huì)回調(diào)onReceive()函數(shù)。 

下段代碼片段顯示的是一個(gè)普通廣播的定義過(guò)程,并發(fā)送出去。其中setAction(..)對(duì)應(yīng)于BroadcastReceiver中的intentFilter中的action。

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

根據(jù)廣播的發(fā)送方式,可以將其分為以下幾種類型:
1.Normal Broadcast:普通廣播 
2.System Broadcast: 系統(tǒng)廣播 
3.Ordered broadcast:有序廣播 
4.Sticky Broadcast:粘性廣播(在 android 5.0/api 21中deprecated,不再推薦使用,相應(yīng)的還有粘性有序廣播,同樣已經(jīng)deprecated) 
5.Local Broadcast:App應(yīng)用內(nèi)廣播 

下面分別總結(jié)下各種類型的發(fā)送方式及其特點(diǎn)。 
1).Normal Broadcast:普通廣播 
此處將普通廣播界定為:開發(fā)者自己定義的intent,以context.sendBroadcast_"AsUser"(intent, ...)形式。具體可以使用的方法有:
sendBroadcast(intent)/sendBroadcast(intent, receiverPermission)/sendBroadcastAsUser(intent, userHandler)/sendBroadcastAsUser(intent, userHandler,receiverPermission)。
普通廣播會(huì)被注冊(cè)了的相應(yīng)的感興趣(intent-filter匹配)接收,且順序是無(wú)序的。如果發(fā)送廣播時(shí)有相應(yīng)的權(quán)限要求,BroadCastReceiver如果想要接收此廣播,也需要有相應(yīng)的權(quán)限。 

2).System Broadcast: 系統(tǒng)廣播
Android系統(tǒng)中內(nèi)置了多個(gè)系統(tǒng)廣播,只要涉及到手機(jī)的基本操作,基本上都會(huì)發(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ā)出。 

3)Ordered broadcast:有序廣播 
有序廣播的有序廣播中的“有序”是針對(duì)廣播接收者而言的,指的是發(fā)送出去的廣播被BroadcastReceiver按照先后循序接收。有序廣播的定義過(guò)程與普通廣播無(wú)異,只是其的主要發(fā)送方式變?yōu)椋簊endOrderedBroadcast(intent, receiverPermission, ...)。

 對(duì)于有序廣播,其主要特點(diǎn)總結(jié)如下: 
1>多個(gè)具當(dāng)前已經(jīng)注冊(cè)且有效的BroadcastReceiver接收有序廣播時(shí),是按照先后順序接收的,先后順序判定標(biāo)準(zhǔn)遵循為:將當(dāng)前系統(tǒng)中所有有效的動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)的BroadcastReceiver按照priority屬性值從大到小排序,對(duì)于具有相同的priority的動(dòng)態(tài)廣播和靜態(tài)廣播,動(dòng)態(tài)廣播會(huì)排在前面。 

2>先接收的BroadcastReceiver可以對(duì)此有序廣播進(jìn)行截?cái)?,使后面的BroadcastReceiver不再接收到此廣播,也可以對(duì)廣播進(jìn)行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯(cuò)誤的參數(shù)值。當(dāng)然,一般情況下,不建議對(duì)有序廣播進(jìn)行此類操作,尤其是針對(duì)系統(tǒng)中的有序廣播。 

4)Sticky Broadcast:粘性廣播(在 android 5.0/api 21中deprecated,不再推薦使用,相應(yīng)的還有粘性有序廣播,同樣已經(jīng)deprecated)。 

既然已經(jīng)deprecated,此處不再多做總結(jié)。 

5)Local Broadcast:App應(yīng)用內(nèi)廣播(此處的App應(yīng)用以App應(yīng)用進(jìn)程為界) 

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

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

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

無(wú)論哪種情形,這些安全隱患都確實(shí)是存在的。由此,最常見的增加安全性的方案是: 

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

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

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

App應(yīng)用內(nèi)廣播可以理解成一種局部廣播的形式,廣播的發(fā)送者和接收者都同屬于一個(gè)App。實(shí)際的業(yè)務(wù)需求中,App應(yīng)用內(nèi)廣播確實(shí)可能需要用到。同時(shí),之所以使用應(yīng)用內(nèi)廣播時(shí),而不是使用全局廣播的形式,更多的考慮到的是Android廣播機(jī)制中的安全性問(wèn)題。 

相比于全局廣播,App應(yīng)用內(nèi)廣播優(yōu)勢(shì)體現(xiàn)在: 

1.安全性更高; 

2.更加高效。 

為此,Android v4兼容包中給出了封裝好的LocalBroadcastManager類,用于統(tǒng)一處理App應(yīng)用內(nèi)的廣播問(wèn)題,使用方式上與通常的全局廣播幾乎相同,只是注冊(cè)/取消注冊(cè)廣播接收器和發(fā)送廣播時(shí)將主調(diào)context變成了LocalBroadcastManager的單一實(shí)例。 

代碼片段如下: 

//registerReceiver(mBroadcastReceiver, intentFilter);//注冊(cè)應(yīng)用內(nèi)廣播接收器localBroadcastManager = LocalBroadcastManager.getInstance(this);localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);    //unregisterReceiver(mBroadcastReceiver);//取消注冊(cè)應(yīng)用內(nèi)廣播接收器localBroadcastManager.unregisterReceiver(mBroadcastReceiver);Intent intent = new Intent();intent.setAction(BROADCAST_ACTION);intent.putExtra("name", "qqyumidi");//sendBroadcast(intent);//發(fā)送應(yīng)用內(nèi)廣播localBroadcastManager.sendBroadcast(intent);

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

1).對(duì)于靜態(tài)注冊(cè)的ContextReceiver,回調(diào)onReceive(context, intent)中的context具體指的是ReceiverRestrictedContext; 

2).對(duì)于全局廣播的動(dòng)態(tài)注冊(cè)的ContextReceiver,回調(diào)onReceive(context, intent)中的context具體指的是Activity Context; 

3).對(duì)于通過(guò)LocalBroadcastManager動(dòng)態(tài)注冊(cè)的ContextReceiver,回調(diào)onReceive(context, intent)中的context具體指的是Application Context。 

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

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

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

2).”靜態(tài)注冊(cè)的廣播接收器即使app已經(jīng)退出,主要有相應(yīng)的廣播發(fā)出,依然可以接收到,但此種描述自Android 3.1開始有可能不再成立“ 

Android 3.1開始系統(tǒng)在Intent與廣播相關(guān)的flag增加了參數(shù),分別是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。 
FLAG_INCLUDE_STOPPED_PACKAGES:包含已經(jīng)停止的包(停止:即包所在的進(jìn)程已經(jīng)退出) 
FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經(jīng)停止的包

主要原因如下:

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

詳情參加Android官方文檔:http://developer.android.com/about/versions/android-3.1.html#launchcontrols 

由此,對(duì)于系統(tǒng)廣播,由于是系統(tǒng)內(nèi)部直接發(fā)出,無(wú)法更改此intent flag值,因此,3.1開始對(duì)于靜態(tài)注冊(cè)的接收系統(tǒng)廣播的BroadcastReceiver,如果App進(jìn)程已經(jīng)退出,將不能接收到廣播。 

但是對(duì)于自定義的廣播,可以通過(guò)復(fù)寫此flag為FLAG_INCLUDE_STOPPED_PACKAGES,使得靜態(tài)注冊(cè)的BroadcastReceiver,即使所在App進(jìn)程已經(jīng)退出,也能能接收到廣播,并會(huì)啟動(dòng)應(yīng)用進(jìn)程,但此時(shí)的BroadcastReceiver是重新新建的。
 Intent intent = new Intent();
 intent.setAction(BROADCAST_ACTION);
 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
 intent.putExtra("name", "qqyumidi");
 sendBroadcast(intent);

注1:對(duì)于動(dòng)態(tài)注冊(cè)類型的BroadcastReceiver,由于此注冊(cè)和取消注冊(cè)實(shí)在其他組件(如Activity)中進(jìn)行,因此,不受此改變影響。 

注2:在3.1以前,相信不少app可能通過(guò)靜態(tài)注冊(cè)方式監(jiān)聽各種系統(tǒng)廣播,以此進(jìn)行一些業(yè)務(wù)上的處理(如即時(shí)app已經(jīng)退出,仍然能接收到,可以啟動(dòng)service等..),3.1后,靜態(tài)注冊(cè)接受廣播方式的改變,將直接導(dǎo)致此類方案不再可行。于是,通過(guò)將Service與App本身設(shè)置成不同的進(jìn)程已經(jīng)成為實(shí)現(xiàn)此類需求的可行替代方案。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 清流县| 彰武县| 绥德县| 定日县| 青神县| 鄂温| 鄂托克前旗| 璧山县| 崇文区| 济阳县| 梁平县| 海门市| 浑源县| 洛浦县| 岳普湖县| 榆林市| 旺苍县| 朝阳市| 甘洛县| 兴安盟| 胶州市| 礼泉县| 柯坪县| 太保市| 濮阳市| 禄劝| 元朗区| 东乡族自治县| 怀柔区| 平安县| 香河县| 化隆| 陇南市| 鲁甸县| 岳阳市| 永安市| 舟曲县| 恭城| 木兰县| 浏阳市| 武鸣县|