Android 四大組件(四)BroadcastReceiver

轉載請註明出處:http://blog.csdn.net/vnanyesheshou/article/details/75449100

Andorid四大組件Activity、Service、ContentProvider都已經總結了,詳情可以參考如下:
Android 四大組件(一)Activity
Android 四大組件(二)Service
Android 四大組件(三)ContentProvider
這篇說四大組件中的最後一個BroadcastReceiver。


廣播接收者

BroadcastReceiver,”廣播接受者”的意思。用來接收系統、應用的廣播。
該組件應用非常廣泛,許多地方都有用到,比如:wifi的連接斷開,系統會發送廣播,廣播接受者可以獲取wifi的連接狀態;電量變化也會發送廣播,通過廣播接受者監聽電量的變化。

創建BroadcastReceiver。

BroadcastReceiver是抽象類,所以使用它需要繼承BroadcastReceiver,並實現其抽象方法onReceive()。

package com.zpengyong.receiver;  

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.util.Log;  

public class MyBroadcastReceiver extends BroadcastReceiver {        
    private static final String TAG = "MyBroadcastReceiver";       
    @Override  
    public void onReceive(Context context, Intent intent) {  
        String msg = intent.getStringExtra("msg");  
        Log.i(TAG, msg);  
    }  

} 

當接收到廣播,系統會回調onReceive方法,通過參數intent可以獲取其攜帶的數據。創建好廣播接收者,還需要進行註冊,否則不會接收到廣播。

註冊

BroadcastReceiver註冊方法分爲兩種:

1.靜態註冊
在AndroidManifest.xml文件中註冊。這種方式和應用是否可見沒有關係,收到廣播就可以運行。intent-filter用來指定接收的廣播。

<receiver android:name=".MyBroadcastReceiver">  
    <intent-filter>  
        <action android:name="android.intent.action.zpengyong"/>  
        <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver>

2.動態註冊
通常在代碼中進行註冊。在註冊之後就可以接受指定的廣播了。

MyBroadcastReceiver mReceiver = new MyBroadcastReceiver();          
IntentFilter filter = new IntentFilter();  
filter.addAction("android.intent.action.zpengyong");  

registerReceiver(mReceiver, filter); 

動態註冊一般是在Activity和Service中進行註冊(當然也可以通過context在普通類裏面註冊),既然register了,就需要unregister。在Activity、Service銷燬前,應及時取消註冊,否則會報異常如下所示:

Activity com.zpengyong.receiver.Mainactivity has leaked IntentReceiver ...BroadcastReceiver,that was originally register here.
Are you misssing a call to unregisterReceiver()?

取消註冊方法如下:

@Override  
protected void onDestroy() {  
    super.onDestroy();  
    unregisterReceiver(mReceiver);  
} 

兩種註冊方式的區別
1. 靜態註冊:
常駐型、不受組件生命週期的影響,應用程序關閉後,接收到廣播,依然可以運行。
2. 動態註冊
非常駐、受Activity、Service生命週期的影響,在其生命週期結束前,必須移除廣播接收者。

現在的廣播接收器就可以接收廣播了。


發送廣播

發送廣播有兩種方式:

  • sendBroadcast 普通廣播
  • sendOrderedBroadcast 有序廣播

普通廣播

普通廣播的發送方式如下:

Intent intent = new Intent("android.intent.action.zpengyong");
sendBroadcast(intent);

發送普通廣播,對於多個註冊該action的廣播,都能一塊接收到,並沒有接收的先後順序。由於是一同接收到的,所以一個接收者是沒有辦法阻止另一個接收者接收這個廣播的。

有序廣播

有序廣播的發送方式如下:

Intent intent = new Intent("android.intent.action.zpengyong");
intent.putExtra("msg", "hello");
sendOrderedBroadcast(intent, null);

發送有序廣播,多個廣播接收者,按順序接收廣播,高優先級的先收到,然後是低優先級的。優先級從-1000~1000,數越大,優先級越高。

不同優先級

清單文件如下所示:

<receiver android:name=".MyBroadcastReceiver">  
    <intent-filter android:priority="10">  
      <action android:name="android.intent.action.zpengyong"/>  
      <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver>

<receiver android:name=".SecondReceiver">  
    <intent-filter android:priority="100">  
      <action android:name="android.intent.action.zpengyong"/>  
      <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver>

兩個廣播接收者
MyBroadcastReceiver代碼如下:

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(TAG, "action="+action);
        String msg = intent.getStringExtra("msg");
        Log.i(TAG, "msg="+msg);

        //接收通過setResultExtras傳過來的msg  
        String result = getResultExtras(true).getString("msg");    
        Log.i(TAG, "result:" + result);
    }
}

SecondReceiver代碼如下:

public class SecondReceiver extends BroadcastReceiver {
    private static final String TAG = "SecondReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(TAG, "action="+action);
        String msg = intent.getStringExtra("msg");
        Log.i(TAG, "msg="+msg);

        //向低優先級的廣播接收者發送消息 
        Bundle bundle = new Bundle();    
        bundle.putString("msg", "haha");    
        setResultExtras(bundle); 
    }
}

接收有序廣播打印:
優先級不同
SecondReceiver優先級爲100,MyBroadcastReceiver優先級爲10,這說明優先級高的先接收廣播,然後是優先級低的。優先級高的廣播可以通過setResultExtras向優先級低的傳遞數據,但不會更改intent中攜帶的數據。

高優先級的BroadcastReceiver調用abortBroadcast();可以阻止低優先級的BroadcastReceiver接收廣播。

相同優先級

對於相同優先級(priority)的BroadcastReceiver,有序廣播的接收順序是如何呢?
清單文件註冊兩個BroadcastReceiver,使用默認優先級

<receiver android:name=".MyBroadcastReceiver">  
    <intent-filter>  
          <action android:name="android.intent.action.zpengyong"/>  
          <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver>

<receiver android:name=".SecondReceiver">  
    <intent-filter>  
          <action android:name="android.intent.action.zpengyong"/>  
          <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</receiver>

兩個廣播接收者
MyBroadcastReceiver代碼如下:

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(TAG, "action="+action);
        String msg = intent.getStringExtra("msg");
        Log.i(TAG, "msg="+msg);
    }
}

SecondReceiver代碼如下:

public class SecondReceiver extends BroadcastReceiver {
    private static final String TAG = "SecondReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(TAG, "action="+action);
        String msg = intent.getStringExtra("msg");
        Log.i(TAG, "msg="+msg); 
    }
}

接收到有序廣播的打印如下:
相同優先級

如上是兩個BroadcastReceiver是使用默認優先級,如果AndroidManifest.xml中顯示的設置相同的優先級,效果和上圖一樣。
這裏猜想相同優先級的BroadcastReceiver接收順序和清單文件中註冊的先後順序有關係。
更改AndroidManifest.xml中兩個BroadcastReceiver的順序。接收順序確實有變化,打印如下:
相同優先級
這樣就是證明了我的猜測是爭取的,對於相同優先級的BroadcastReceiver,先註冊的先接收到有序廣播。如果在先註冊的BroadcastReceiver中調用abortBroadcast(),也是會起作用,導致後面的接收不到廣播。

sendOrderedBroadcast(Intent intent, String receiverPermission)方法中的第二個參數用來設置接收者是否需要申請權限。如果參數爲null,則接收者不需要申請權限就可以接收廣播。如果不爲空則需要申請權限,否則接收不到廣播。
發送廣播

Intent intent = new Intent("android.intent.action.zpengyong");
intent.putExtra("msg", "hello");
sendOrderedBroadcast(intent, "zpengyong.permission.broadcast");

接收者申請權限方式:

//定義權限
<permission android:protectionLevel="normal"   
                android:name="zpengyong.permission.broadcast"/>
//聲明使用該權限
<uses-permission android:name="zpengyong.permission.broadcast" />

生命週期

BroadcastReceiver對象僅對調用onReceive()的持續時間有效。一旦您的代碼從此函數返回,系統會將該對象視爲完成並且不再處於活躍狀態。
這對於在onReceive()實現中可以做什麼有重要的影響:任何需要異步操作的事情都不可用,因爲您需要從函數返回以處理異步操作,但是在這一點上BroadcastReceiver是不再活躍的,因此係統可以在異步操作完成之前自由地終止其進程。
特別地,您可能不會在BroadcastReceiver內顯示對話框或綁定到服務。對於前者,您應該使用{android.app.NotificationManager} API。對於後者,您可以使用{android.content.Context#startService Context.startService()}向服務發送命令。

當前正在執行BroadcastReceiver(即當前正在運行其onReceive()方法)的進程被認爲是一個前臺進程,除非是極端內存壓力的情況,否則系統將繼續運行該進程。
從onReceive()返回後,BroadcastReceiver不再處於活動狀態,其進程與其中運行的任何其他應用程序組件一樣重要。這一點尤爲重要,因爲如果這個進程只保持BroadcastReceiver(一個常見的例子,就是用戶從來沒有或最近沒有交互過的應用程序),那麼在從onReceive()返回時,系統會把它看成是空的進程,所以資源可用於其他更重要的流程。這意味着對於長時間運行的操作,應經常將{@link android.app.Service}與BroadcastReceiver結合使用,以便在整個操作過程中保持進程的活動狀態。


總結

通過廣播接收者可以在同一進程中使用,也可以在進程間使用。這也是進程間通信的一種方式。但是對於同一進程推薦使用LocalBroadcastManager
至此廣播接收者就總結完成了。


歡迎大家關注、評論、點贊
你們的支持是我堅持的動力。

我新申請的簡書

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章