轉載請註明出處: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。
至此廣播接收者就總結完成了。
歡迎大家關注、評論、點贊。
你們的支持是我堅持的動力。