Android廣播機制詳細介紹(廣播分類、注冊方式)


Android廣播機制詳細介紹(廣播分類、注冊方式)。


(一). 安卓廣播的分類

a.標准廣播

?
1
2
3
4
5
標准廣播發出以后,所有的廣播接收器,可以幾乎在同一時刻同時接受到這條廣播。
 
優點:效率高
 
缺點:不能被截斷。

b.有序廣播

?
1
2
3
4
5
6
7
     有序廣播發出以后,同一時刻只能有一個廣播接收器收到這條廣播。優先級高的廣播先接受到這條
 
廣播。在當前廣播接收器處理完自己的邏輯以后,可以執行兩種動作:
 
     1 .繼續傳遞廣播
 
     2 .將廣播截斷

(二). 注冊廣播的方式

a. 動態注冊

?
1
2
3
在代碼中注冊的廣播,被稱為動態注冊。動態注冊的廣播,最后必須取消注冊。這類廣播,只有應用啟
 
動了,才能接收到廣播。

動態注冊廣播需要的東西

一個廣播接收器類 —— 實質就是一個繼承自BoradCastReceiver的類,只要繼承這個類,就

具體接收廣播的能力了,但是能接受什么廣播由下面的第三條決定。

重寫父類的onReceive()方法 —— 接收到廣播的時候,就會回調這個方法。因此,廣播接收

器的處理邏輯就寫在這里

一個 IntentFilter 對象,廣播接收器接收什么樣的廣播,由它的addAction()方法決定。

在代碼中注冊廣播接收器,通過registerReceiver方法。方法接受兩個參數,一個是廣播接收

實例,一個是IntentFilter實例。

取消注冊廣播 ,通過unregisterReceiver() 方法—— 在哪里取消注冊無所謂,只要保證取

消注冊就OK

如果需要權限,則在AndroidManifest.xml文件申明權限


代碼 :

布局代碼:

?
1
2
3
4
5
6
7
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<linearlayout android:layout_height= "match_parent" android:layout_width= "match_parent" android:orientation= "vertical" xmlns:android= "https://schemas.android.com/apk/res/android" ><button android:id= "@+id/btn_isNetConnect" android:layout_gravity= "center" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:text= "檢測網絡" >
 
     <textview android:gravity= "center" android:id= "@+id/txt_show" android:layout_height= "80dp" android:layout_width= "match_parent" android:textsize= "30sp" >
 
 
</textview></button></linearlayout>

這里寫圖片描述

?
1
我們寫一個簡單的判斷當前網絡是否可用的廣播。監聽網絡是一個敏感的動作,因此,需要在xml中申明權限。
?
1
<uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" ></uses-permission>

java 代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class MainActivity extends AppCompatActivity {
 
//     決定廣播接收器接收什么廣播
     private IntentFilter intentFilter ;
 
     private NetworkChangeReceiver networkChangeReceiver ;
     private TextView txt_show ;
     private Button btn_isNetConnect ;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
//        獲取控件實例
         txt_show = (TextView) findViewById(R.id.txt_show);
         btn_isNetConnect = (Button) findViewById(R.id.btn_isNetConnect);
//        在按鈕監聽器中注冊廣播
         btn_isNetConnect.setOnClickListener( new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 intentFilter = new IntentFilter() ;
//       字符串 android.net.conn.CONNECTIVITY_CHANGE
//       表明廣播接收器接收網絡變化的廣播
                 intentFilter.addAction( "android.net.conn.CONNECTIVITY_CHANGE" );
//        網絡變化廣播接收器實例
                 networkChangeReceiver = new NetworkChangeReceiver() ;
//        注冊廣播
//        別忘了,申明權限
                 registerReceiver(networkChangeReceiver,intentFilter) ;
             }
         });
     }
 
     /**
      * 動態注冊的廣播,必須在取消注冊。
      * 我們在create(),方法創建的時候,注冊了廣播
      * 這里,我們在銷毀活動中,取消注冊,
      * 當然也可以在onPause()方法取消注冊。
      */
     @Override
     protected void onDestroy() {
         super .onDestroy();
         unregisterReceiver(networkChangeReceiver);
     }
 
     /**
      * 用內部類實現一個網絡變化廣播接收器
      */
     class NetworkChangeReceiver extends BroadcastReceiver {
 
//        重寫父類的onReceive()方法,接收到對應的廣播的時候,就會回調這個方法
//        廣播接收器的處理邏輯,就寫此方法中
         @Override
         public void onReceive(Context context, Intent intent) {
//            獲取網絡管理服務類,就跟findViewById()方法一樣
             ConnectivityManager connectivityManager =
                     (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//            記住這樣寫。就好了。用到的時候,百度一下,邊邊角角,誰也記不清
             NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo() ;
//          判斷網絡狀態
             if (networkInfo != null && networkInfo.isAvailable()){
                 txt_show.setText( "當前網絡可用" );
             } else {
                 txt_show.setText( "當前網絡不可用" );
             }
 
         }
     }
}

b.靜態注冊

?
1
2
3
在AndroidManifest.xml文件中注冊的廣播。這類廣播,常駐廣播,在應用未啟動的時候,即可接收
 
到廣播,處理相應的邏輯。

靜態廣播需要的東西

?
1
相比於動態注冊的廣播,靜態廣播需要的東西,就很少了。

依然需要一個廣播接收器類

繼續需要重寫父類的onReceive()方法

在AndroidManifest.xml文件中注冊廣播

如果需要權限,則在AndroidManifest.xml文件申明權限


?
1
talk is cheap,show me code ! Or shut up

代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
  * 這里寫將廣播寫為內部類
  * 目的;記住一個知識點:
  * 靜態注冊的廣播,廣播接收器為內部類的時候,必須是pubic static
 
  * 實現開機自啟動
  * Created by MaiBenBen on 2017/10/16.
  */
public class Outter {
 
// 必須是public static
     public static class BootCompleteReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
//        調啟主活動,來打開應用程序
//        context參數,就是此時的上下文
             Intent intent1 = new Intent(context,MainActivity. class );
             context.startActivity(intent1);
         }
     }
 
}

?
1
2
3
4
5
6
7
8
9
10
<!--
在AndroidManifest.xml文件中注冊廣播
內部類廣播接收器的名字,寫全了
-->
  <receiver android:enabled= "true" android:exported= "true" android:name= ".Outter$BootCompleteReceiver" >
             <intent-filter>
             <!--寫明廣播接收器接收的廣播-->
                 </action>
             </intent-filter>
         </receiver>

?
1
2
監聽開機廣播 權限申明:
<uses-permission android:name= "android.permission.RECEIVE_BOOT_COMPLETED" ></uses-permission>

至此,已經成功完成了開機自啟動。


(三). 發送廣播

?
1
總是接受廣播,也沒勁。下面,我們自己來發送一些廣播。發送的廣播是自定義的。

a. 發送標准廣播

?
1
2
3
4
5
廣播是使用Intent,進行傳遞的。因此,我們可以在Intent中攜帶一些數據傳遞給廣播接收器。
 
注意:這里只是在活動中發送廣播,在服務或者廣播中發送廣播,代碼有所不同:需要在intent中加上
 
標志。
?
1
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)。
?
1
2
3
該標志表明:首先尋找是否有與要啟動的activity具有相同affinity的task。若沒有,則生成一個新
 
的task,並將該activity放入其中;若有,則將該activity添加到該task的棧頂。
?
1
2
3
4
5
6
//        自定義廣播內容
        String broadcast = "allbet.broad.cn.broadcasttest.MY_BROADCAST" ;
//        綁定到Intent中
        Intent intent = new Intent(broadcast) ;
//        發送廣播,調用Context的sendBroadcast()方法
        sendBroadcast(intent);

b. 發送有序廣播

?
1
有序廣播與標准廣播的發送方式,在代碼中只有一句代碼有差別,就是發送廣播的方法不同。
?
1
2
3
4
5
6
7
8
//         自定義廣播內容
       String broadcast = "allbet.broad.cn.broadcasttest.MY_BROADCAST" ;
//         綁定到Intent中
       Intent intent = new Intent(broadcast) ;
//         發送有序廣播
//         第一個參數依然是Intent
//         第二個參數是代表權限的字符串,這里寫null就好了
        sendOrderedBroadcast(intent, null );

有序廣播發送完畢以后,優先級高的廣播接收器會先收到

個廣播。它們甚至可以將廣播截,下面我們講一下優先級的

問題


<☆> 廣播接收器優先級

1.) 靜態廣播的優先級

跟目錄的順序有關,如下所示,目錄越靠前,優先級越高,其中,第三方APP都在data/app

錄下:

  system/framework
  
  system/app

  vendor/app

  data/app

  drm/app-private

當處於同一目錄下時:按照file.list()的返回順序。因為在data/app下的應用都是用戶安裝的,

並且都是以com.xxx.xxx-1.apk 的形式出現,它們的順序,就是包名的順序,因此,想要你的

應用的靜態廣播優先級高,就需要好好研究包名了,讓你的應用包名靠前。但是這個順序不是

絕對的,還依賴被掃描的先后順序,先掃描的當然優先級高一點啦。即同一優先級的靜態廣播

接收器,先掃描的優先級高。一般都是包名排在前面的先被掃描。但是有人也說,是按照應用

安裝的先后順序。。。。有待考證

上面說的都是靜態注冊的時候,使用了相同優先級的情況。設置了優先級的,優先級越高,越

先接收到廣播。


2.) 動態廣播的優先級

一大影響因素,動態廣播的注冊時間。同一優先級的動態廣播,先注冊的優先級高。

動態注冊的廣播接收器的優先級永遠高於靜態注冊的廣播接收器。


綜上所述,做個總結:

其實當接收廣播的時候,廣播接收器都會排隊,無論是標准廣播,還是有序廣播,都是要排隊

的,只不過,有序廣播可能會被截斷。

因此我們可以將,所有能接收該廣播的廣播接收器,理解為排隊等着廣播傳遞,排在前面的

人,當然就先接收到廣播啦。那么誰排在前面呢?毫無疑問,一定是動態注冊的廣播,動態注

冊的廣播接收器們根據優先級排隊,相同優先級的,就按照被掃描的先后順序排隊。排在隊伍

后面的就只剩下靜態注冊的廣播接收器了,也先根據優先級排序,相同優先級的,按照被掃描

的先后順序排隊。

上述的情況是,所有的廣播接收器都不缺席的情況,但是總有廣播接收器,由於種種原因(比

如,動態注冊的廣播,應用未啟用)會缺席,缺席的話,那后面的廣播接收器就自動補全空

位。


(四).為廣播接收器設定優先級

a.為靜態廣播接收器設定優先級

?
1
在xml文件中設定
?
1
2
3
4
5
6
<receiver android:enabled= "true" android:exported= "true" android:name= ".Outter$BootCompleteReceiver" >
            <!--在這里添加屬性-->
            <intent-filter android:priority= "100" >
                </action>
            </intent-filter>
        </receiver>

b.為動態廣播設置優先級

?
1
在intentFilter對象上設置
?
1
2
3
4
5
6
7
8
9
10
11
         intentFilter = new IntentFilter() ;
//       字符串 android.net.conn.CONNECTIVITY_CHANGE
//       表明廣播接收器接收網絡變化的廣播
                 intentFilter.addAction( "android.net.conn.CONNECTIVITY_CHANGE" );
//         設置優先級
                 intentFilter.setPriority( 1000 );
//        網絡變化廣播接收器實例
                 networkChangeReceiver = new NetworkChangeReceiver() ;
//        注冊廣播
//        別忘了,申明權限
                 registerReceiver(networkChangeReceiver,intentFilter) ;

(五).截斷有序廣播

?
1
2
3
有序廣播在傳送中,是可以被截斷,甚至可以修改廣播攜帶的數據。
 
截斷廣播,就是在廣播接收器的onReceive()方法中調用abortBroadcast();
?
1
2
3
4
5
6
7
public void onReceive(Context context, Intent intent) {
/*
     處理邏輯
*/
//     邏輯處理結束,截斷廣播。
     abortBroadcast();
}

(六) 本地廣播

?
1
2
3
之前我們發送的廣播,都是系統全局廣播,即我們發送的廣播,能被系統的其他程序也接收到。這樣是
 
很不安全的,因為,廣播上說不定會攜帶着關鍵數據。或者,其他程序,不停的向我們發生垃圾廣播。

本地廣播,是無法再通過靜態注冊的廣播接收器收到的。很好理解,靜態注冊,是為了程序未啟動的

時候接收廣播,而本地廣播,程序已然啟動可了。當然,也不能注冊本地廣播。

因此,我們需要本地廣播,顧名思義,廣播,只能在本程序中發送和接收。


a.本地廣播需要的東西

對比全局廣播,本地廣播需要一個LocalBroadcastManger對象,來對廣播進行管理。
?
1
2
3
4
5
6
//       獲取本地廣播管理 實例
         localBroadcastManager = LocalBroadcastManager.getInstance( this );
  intentFilter = new IntentFilter( "com.yaz.QQQ" ) ;
         myLocalBr  = new MyLocalBr() ;
         localBroadcastManager.registerReceiver(myLocalBr,intentFilter);
         break ;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM