最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android BroadcastReceiver廣播機制概述

 更新時間:2021年04月22日 09:53:12   作者:Windstep  
這篇文章主要為大家詳細介紹了Android BroadcastReceiver廣播機制,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

Android廣播機制概述

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

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

從實現(xiàn)原理看上,Android中的廣播使用了觀察者模式,基于消息的發(fā)布/訂閱事件模型。因此,從實現(xiàn)的角度來看,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í)行拿到此廣播,回調(diào)BroadcastReceiver中的onReceive()方法。

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

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

在上文說列舉的廣播機制具體可以使用的場景中,現(xiàn)分析實際應用中的適用性:

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

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

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

2.BroadcastReceiver

自定義BroadcastReceiver

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

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注冊類型

BroadcastReceiver總體上可以分為兩種注冊類型:靜態(tài)注冊和動態(tài)注冊。 

1).靜態(tài)注冊:

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

常見的注冊形式有:

<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)絡狀態(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)注冊時,無須在AndroidManifest中注冊<receiver/>組件。直接在代碼中通過調(diào)用Context的registerReceiver函數(shù),可以在程序中動態(tài)注冊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中所有與觀察者模式有關的設計中,一旦涉及到register,必定在相應的時機需要unregister。因此,上例在onDestroy()回到中需要unregisterReceiver(mBroadcastReceiver)。

當此Activity實例化時,會動態(tài)將MyBroadcastReceiver注冊到系統(tǒng)中。當此Activity銷毀時,動態(tài)注冊的MyBroadcastReceiver將不再接收到相應的廣播。

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

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

下段代碼片段顯示的是一個普通廣播的定義過程,并發(fā)送出去。其中setAction(..)對應于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,不再推薦使用,相應的還有粘性有序廣播,同樣已經(jīng)deprecated) 
5.Local Broadcast:App應用內(nèi)廣播 

下面分別總結下各種類型的發(fā)送方式及其特點。

1).Normal Broadcast:普通廣播

此處將普通廣播界定為:開發(fā)者自己定義的intent,以context.sendBroadcast_"AsUser"(intent, ...)形式。具體可以使用的方法有:
sendBroadcast(intent)/sendBroadcast(intent, receiverPermission)/sendBroadcastAsUser(intent, userHandler)/sendBroadcastAsUser(intent, userHandler,receiverPermission)。
普通廣播會被注冊了的相應的感興趣(intent-filter匹配)接收,且順序是無序的。如果發(fā)送廣播時有相應的權限要求,BroadCastReceiver如果想要接收此廣播,也需要有相應的權限。 

2).System Broadcast: 系統(tǒng)廣播

Android系統(tǒng)中內(nèi)置了多個系統(tǒng)廣播,只要涉及到手機的基本操作,基本上都會發(fā)出相應的系統(tǒng)廣播。如:開啟啟動,網(wǎng)絡狀態(tài)改變,拍照,屏幕關閉與開啟,點亮不足等等。每個系統(tǒng)廣播都具有特定的intent-filter,其中主要包括具體的action,系統(tǒng)廣播發(fā)出后,將被相應的BroadcastReceiver接收。系統(tǒng)廣播在系統(tǒng)內(nèi)部當特定事件發(fā)生時,有系統(tǒng)自動發(fā)出。 

3)Ordered broadcast:有序廣播 

有序廣播的有序廣播中的“有序”是針對廣播接收者而言的,指的是發(fā)送出去的廣播被BroadcastReceiver按照先后循序接收。有序廣播的定義過程與普通廣播無異,只是其的主要發(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可以對此有序廣播進行截斷,使后面的BroadcastReceiver不再接收到此廣播,也可以對廣播進行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯誤的參數(shù)值。當然,一般情況下,不建議對有序廣播進行此類操作,尤其是針對系統(tǒng)中的有序廣播。

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

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

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

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

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

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

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

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

2.在廣播發(fā)送和接收時,都增加上相應的permission,用于權限驗證;

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

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

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

1.安全性更高;

2.更加高效。

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

代碼片段如下:

//registerReceiver(mBroadcastReceiver, intentFilter);
//注冊應用內(nèi)廣播接收器
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
    
//unregisterReceiver(mBroadcastReceiver);
//取消注冊應用內(nèi)廣播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
intent.putExtra("name", "qqyumidi");
//sendBroadcast(intent);
//發(fā)送應用內(nèi)廣播
localBroadcastManager.sendBroadcast(intent);

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

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

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

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

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

5.不同Android API版本中廣播機制相關API重要變遷

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

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)本身則增加了對所有app當前是否處于運行狀態(tài)的跟蹤。在發(fā)送廣播時,不管是什么廣播類型,系統(tǒng)默認直接增加了值為FLAG_EXCLUDE_STOPPED_PACKAGES的flag,導致即使是靜態(tài)注冊的廣播接收器,對于其所在進程已經(jīng)退出的app,同樣無法接收到廣播。 

詳情參加Android官方文檔

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

但是對于自定義的廣播,可以通過復寫此flag為FLAG_INCLUDE_STOPPED_PACKAGES,使得靜態(tài)注冊的BroadcastReceiver,即使所在App進程已經(jīng)退出,也能能接收到廣播,并會啟動應用進程,但此時的BroadcastReceiver是重新新建的。

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

注1:對于動態(tài)注冊類型的BroadcastReceiver,由于此注冊和取消注冊實在其他組件(如Activity)中進行,因此,不受此改變影響。 

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

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Android編程之陰影(Shadow)制作方法

    Android編程之陰影(Shadow)制作方法

    這篇文章主要介紹了Android編程之陰影(Shadow)制作方法,結合實例形式分析了Android陰影效果實現(xiàn)函數(shù)setShadowLayer的具體使用技巧,需要的朋友可以參考下
    2016-10-10
  • Android pcm轉wav格式方法

    Android pcm轉wav格式方法

    本篇文章主要給大家講述了在Android開發(fā)中將pcm格式轉wav格式的方法和代碼實例,需要的朋友跟著學習下吧。
    2017-12-12
  • Android中Fragment的生命周期與返回棧的管理

    Android中Fragment的生命周期與返回棧的管理

    這篇文章主要介紹了Android中Fragment的生命周期與返回棧的管理,舉例講解了Fragment中addToBackStack()方法的使用,需要的朋友可以參考下
    2016-02-02
  • Android 屬性動畫ValueAnimator與插值器詳解

    Android 屬性動畫ValueAnimator與插值器詳解

    這篇文章主要介紹了Android 屬性動畫ValueAnimator與插值器詳解的相關資料,需要的朋友可以參考下
    2017-05-05
  • Android實現(xiàn)大圖滾動顯示效果

    Android實現(xiàn)大圖滾動顯示效果

    這篇文章主要為大家詳細介紹了Android實現(xiàn)大圖滾動顯示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android 破解視頻App去除廣告功能詳解及解決辦法總結

    Android 破解視頻App去除廣告功能詳解及解決辦法總結

    這篇文章主要介紹了Android 破解視頻App去除廣告功能詳解及解決辦法總結的相關資料,這里對視頻播放原理及破解去除廣告幾種方法進行了總結,需要的朋友可以參考下
    2016-12-12
  • android仿微信聯(lián)系人索引列表功能

    android仿微信聯(lián)系人索引列表功能

    這篇文章主要為大家詳細介紹了android仿微信聯(lián)系人索引列表功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Android編程之四種Activity加載模式分析

    Android編程之四種Activity加載模式分析

    這篇文章主要介紹了Android編程之四種Activity加載模式,簡要分析了Android編程中涉及的Activity的四種加載模式,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-01-01
  • Android開發(fā)獲取系統(tǒng)中已安裝程序信息的方法

    Android開發(fā)獲取系統(tǒng)中已安裝程序信息的方法

    這篇文章主要介紹了Android開發(fā)獲取系統(tǒng)中已安裝程序信息的方法,可實現(xiàn)Android針對系統(tǒng)中已安裝程序名稱、路徑、大小、圖標、是否為系統(tǒng)app等信息的獲取功能,需要的朋友可以參考下
    2017-12-12
  • Android內(nèi)存優(yōu)化操作方法梳理總結

    Android內(nèi)存優(yōu)化操作方法梳理總結

    這篇文章主要介紹了Android 內(nèi)存優(yōu)化知識點梳理總結,Android 操作系統(tǒng)給每個進程都會分配指定額度的內(nèi)存空間,App 使用內(nèi)存來進行快速的文件訪問交互,長時間如此便需要優(yōu)化策略,文章分享優(yōu)化知識點總結,需要的朋友可以參考一下
    2022-11-11

最新評論

寿光市| 庆城县| 揭阳市| 临城县| 广东省| 松江区| 竹溪县| 榆林市| 拉孜县| 巴中市| 雅江县| 四子王旗| 大英县| 鸡泽县| 临汾市| 万年县| 文登市| 乌兰县| 鲁山县| 和田市| 吉安市| 凌云县| 崇礼县| 钦州市| 三穗县| 如皋市| 商都县| 衢州市| 鲁甸县| 绥化市| 蓬莱市| 修文县| 泾源县| 商洛市| 介休市| 铅山县| 东兰县| 隆子县| 漯河市| 梁河县| 铜山县|