歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 四大組件之BroadcastReceiver

Android 四大組件之BroadcastReceiver

日期:2017/3/1 9:31:10   编辑:Linux編程

1.BroadcastReceiver簡介:

  BroadcastReceiver 廣播接收器,這個組件本質上就是一種全局監聽器,用於監聽全局廣播(Broadcast)消息,因此它可以非常方便的實現系統不同組件之間的通信。

  BroadcastReceiver這個監聽器與普通的onXxxListener監聽器是不同的,onXxxListener是屬於應用程序級別的監聽器,當程序退出的時候那麼這個監聽器也就隨之結束了。而BroadcastReceiver(配置文件中注冊)屬於系統級別的監聽器,它擁有自己的進程,只要存在與之匹配的Broadcast以intent形式傳遞過來,那麼BroadcastReceiver就會被激活。

  與Activity不同的是,當系統通過Intent啟動指定的Activity組件時,如果系統沒有找到目標Activity組件,這時就會發生程序異常中斷,但系統通過Intent激活BroadcastReceiver時,即使沒有找到目標BroadcastReceiver時,系統也不會有任何問題

2.創建BroadcastReceiver

  2.1 首先需要繼承BroadcastReceiver類,重寫這個類裡面的onReceive()方法,代碼如下:

 1 package com.example.administrator.broadcastreceivertest;
 2 
 3 import Android.content.BroadcastReceiver;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 import android.util.Log;
 7 import android.widget.Toast;
 8 
 9 
10 public class MyBroadcastReceiver extends BroadcastReceiver{
11     public MyBroadcastReceiver() {
12         Log.i("tag","創建構造器...");
13     }
14 
15     @Override
16     public void onReceive(Context context, Intent intent) {
17         String msg = intent.getStringExtra("msg");
18         Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
19     }
20 }

    當一個BroadcastReceiver被激活之後,系統會為之創建一個BroadcastReceiver實例,並自動觸發它的onReceive()方法,onReceive()方法被執行完後,BroadcastReceiver實例就會被銷毀。如果BroadcastReceiver的onReceive()方法不能在10s內執行完成,Android會認為該程序無響應,所以不要在onReceive()方法中執行耗時操作,否則會彈出ANR(Application No Response)對話框。

    如果在onReceive()方法中需要執行耗時操作,可以考慮使用Intent啟動一個Service來完成操作,此時不應該考慮啟動一個新的線程去處理耗時操作,因為BroadcastReceiver的生命周期很短,可能子線程還沒有結束,BroadcastReceiver就已經退出了。而如果BroadcastReceiver所在的進程結束了,那麼該線程就會標記為一個空線程。根據Android內存管理策略,在系統內存緊張時,會根據優先級首先結束優先級低的線程,而空線程優先級無疑是擁有最低的優先級,系統回收後,線程就無法完成相關操作了

  2.2 注冊BroadcastReceiver

    注冊BroadcastReceiver的兩種方式:

      1>使用代碼進行指定(動態注冊),調用Context類提供的registerReceiver(BroadcastReceiver receiver,IntentFilter filter);代碼如下

        

1      MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
2         IntentFilter filter = new IntentFilter(SHOW_MESSAGE);
3         registerReceiver(myBroadcastReceiver,filter);

      IntentFilter 是根據SHOW_MESSAGE用來匹配Broadcast的,SHOW_MESSAGE是一個自定義的靜態字符串常量。

      要注意的是,BroadcastReceiver注冊的地方,google 官方指出:

      Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.

      意思大概是:如果你要在Activity類中的onResume()方法中注冊一個receiver,你也應該在Activity類onPause()方法中取消注冊。不要在onSaveInstanceState()方法中取消注冊,因為如果用戶退出當前Activity(從task中移除Activity)時,那麼這個BroadcastReceiver也將不能被激活。

      特點:當應用程序關閉後,就不再監聽。對於我們開發的App來說,越省電就會越受用戶的歡迎,所以對於那些沒有必要在應用程序退出後仍然進行監聽的receiver,在代碼中注冊是一個不錯的選擇

      2>在AndroidManifest.xml中注冊(靜態注冊),代碼如下:

      

1       <receiver android:name=".MyBroadcastReceiver">
2             <intent-filter>
3                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
4             </intent-filter>
5         </receiver>

       特點:不管應用程序是否處於活動狀態,都會進行監聽。比如某個應用程序監聽內存使用情況,當在手機上安裝好之後,不管其處於什麼狀態都會監聽內存狀態。

  2.3 生命周期

    BroadcastReceiver的生命周期很簡單,如下圖

    

3.Broadcast介紹

  3.1Broadcast被分為兩種:

    1>Normal Broadcast(普通廣播):

      Normal Broadcast是完全異步的,可以在同一時刻,被所有接收者接收到(邏輯上),消息傳遞效率比較高。缺點是接收者不能將結果傳給下一個接收者,並且無法阻止Broadcast Intent的傳播

    2>Ordered Broadcast(有序廣播):

      Ordered Broadcast的接收者將按照預先聲明的優先級次序依次接收Broadcast。如果priority:A>B>C,那麼Broadcast先傳給A->B->C。

  3.2 發送廣播的兩種方式:

    1>sendBroadcast():發送Normal Broadcast

    2>sendOrderedBroadcast():發送Ordered Broadcast     

    對於Ordered Broadcast而言系統會根據接收者聲明的優先級別按順序依次執行接收者,優先收到Broadcast的接收者可以終止Broadcast(調用BroadcastReceiver的abortBroadcast()方法),那麼後面的接收者將無法取到Broadcast.

    不僅如此,對於Ordered Broadcast而言,優先級別高的接收者,可以通過setResultExtras(Bundle bundle)將結果存到Broadcast中,下一個接收者可以通過Bundle bundle = getResultExtras(true)獲取上一個數據

    TIP:系統接收短信,發出的Broadcast屬於Ordered Broadcast.如果想攔截用戶收到短信,可以設置優先級,讓自定義的BroadcastReceiver先接收到短信,然後終止broadcast。

4.下面是一個Ordered Broadcast廣播例子,代碼如下:

  MainActivity類:

 1 package com.example.administrator.broadcastreceivertest;
 2 
 3 import android.app.Activity;
 4 import android.content.Intent;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 
 8 
 9 public class MainActivity extends Activity {
10 
11     private static final String SHOW_MESSAGE = "com.example.administrator.broadcastreceiver.SEND_MESSAGE";
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16     }
17 
18     public void sendOrderedBroadcast(View view){
19         Intent intent = new Intent(SHOW_MESSAGE);
20         intent.putExtra("msg","Ordered Broadcast");
21         sendOrderedBroadcast(intent,null);
22     }
23 
24 }

  MyBroadcastReceiver類

 1 package com.example.administrator.broadcastreceivertest;
 2 
 3 import android.content.BroadcastReceiver;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 import android.util.Log;
 7 import android.widget.Toast;
 8 
 9 
10 public class MyBroadcastReceiver extends BroadcastReceiver{
11 
12     @Override
13     public void onReceive(Context context, Intent intent) {
14         String msg = intent.getStringExtra("msg");
15         Log.i("tag","MyBroadcastReceiver:"+msg);
16         Toast.makeText(context,"MyBroadcastReceiver:"+msg,Toast.LENGTH_SHORT).show();
17     }
18 } 

  MyBroadcastReceiver2類

 1 package com.example.administrator.broadcastreceivertest;
 2 
 3 import android.content.BroadcastReceiver;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 import android.util.Log;
 7 import android.widget.Toast;
 8 
 9 
10 public class MyBroadcastReceiver2 extends BroadcastReceiver{
11 
12     @Override
13     public void onReceive(Context context, Intent intent) {
14         String msg = intent.getStringExtra("msg");
15         Log.i("tag","MyBroadcastReceiver2:"+msg);
16         Toast.makeText(context,"MyBroadcastReceiver2:"+msg,Toast.LENGTH_LONG).show();
17     }
18 } 

  activity_main.xml

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
 3     android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
 4     android:paddingRight="@dimen/activity_horizontal_margin"
 5     android:paddingTop="@dimen/activity_vertical_margin"
 6     android:orientation="vertical"
 7     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
 8 
 9 
10     <Button
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:text="發送 Ordered Broadcast "
14         android:onClick="sendOrderedBroadcast"/>
15 </LinearLayout> 

  AndroidManifest.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.administrator.broadcastreceivertest" >
 4 
 5     <application
 6         android:allowBackup="true"
 7         android:icon="@drawable/ic_launcher"
 8         android:label="@string/app_name"
 9         android:theme="@style/AppTheme" >
10         <activity
11             android:name=".MainActivity"
12             android:label="@string/app_name" >
13             <intent-filter>
14                 <action android:name="android.intent.action.MAIN" />
15 
16                 <category android:name="android.intent.category.LAUNCHER" />
17             </intent-filter>
18         </activity>
19 
20 
21         <receiver android:name=".MyBroadcastReceiver">
22             <intent-filter  android:priority="1">
23                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
24             </intent-filter>
25         </receiver>
26 
27         <receiver android:name=".MyBroadcastReceiver2">
28             <intent-filter android:priority="2">
29                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
30             </intent-filter>
31         </receiver>
32     </application>
33 
34 </manifest>

運行結果:

控制台輸出結果:

從運行結果可以看出先是MyBroadcastReceiver2先接收到Broadcast,接著才是MyBroadcastReceiver,因為我在注冊時將MyBroadcastReceiver2的優先級設置為2,MyBroadcastReceiver優先級為1。

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved