編輯:關於android開發
BroadcastReceiver 廣播是一種訂閱–通知 事件,廣播接收者向Android系統 register (訂閱廣播),廣播發送者向Adnroid系統 sendBroadCast(發送廣播),然後Android 系統通知所有注冊該廣播的接收者,廣播接收者收到自己注冊的廣播之後實現自己想做的事情(該事情一般不超過10s,否則應用會出現ANR)。
無序廣播:也就是普通廣播,只要注冊了該action的廣播接收者都能收到該廣播,且沒有先後順序。
有序廣播:廣播接收者按照優先級高低依次接受該廣播,並且優先接收的廣播可以通過setResultExtras(Bundle)方法,將處理好的結果傳送到下一個廣播接收者那裡。
粘性廣播:發送廣播調用的方法 sendStickyBroadcast(Intent),和sendBroadcast(Intent)不同。
粘性廣播會一直保留在內存當中,直到有廣播接收者注冊該廣播,該廣播才算結束。不好解釋,等會具體看例子。
根據注冊方式不同可以分為 靜態注冊廣播和動態注冊廣播。
AndroidManifest.xml 如下:
package com.xjp.mybroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Description:靜態廣播接收器
* User: xjp
* Date: 2015/5/14
* Time: 14:56
*/
public class BroadCastReceive1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到廣播之後處理自己的事情
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}
package com.xjp.mybroadcast;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private Button btnSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
}
private void sendBraodCast() {
/**
* 申明靜態廣播的 action 行為
*/
String action = "com.xjp.mybroadcast.BroadCastReceive1";
Intent intent = new Intent(action);
intent.putExtra("key", "靜態廣播測試");
sendBroadcast(intent);
}
}
打印結果如下:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private Button btnSend;
private BroadCastReceive2 myReceive;
private IntentFilter filter;
private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this);
myReceive = new BroadCastReceive2();
filter = new IntentFilter();
filter.addAction(ACTION);
}
@Override
protected void onResume() {
/**
* 注冊廣播
*/
LocalBroadcastManager.getInstance(this).registerReceiver(myReceive, filter);//官方建議使用
// this.registerReceiver(myReceive, filter);
super.onResume();
}
@Override
protected void onPause() {
/**
* 注銷廣播
*/
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceive);//官方建議使用
// this.unregisterReceiver(myReceive);
super.onPause();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
}
private void sendBraodCast() {
/**
* 申明廣播的 action 行為
*/
Intent intent = new Intent(ACTION);
intent.putExtra("key", "動態廣播測試");
/**
* 官方提倡使用如下發送廣播,原因是更快,更安全,不會導致內存洩漏
*/
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
// this.sendBroadcast(intent);
}
/**
* 內部類實現廣播接收器
*/
private class BroadCastReceive2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//TODO 接收到廣播之後處理自己的事情
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}
}
示例:
package com.xjp.mybroadcast; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.Button; public class MainActivity extends ActionBarActivity implements View.OnClickListener { private Button btnSend; private BroadCastReceive2 myReceive; private BroadCastReceive3 myReceive3; private IntentFilter filter; private IntentFilter filter3; private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive2"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.button); btnSend.setOnClickListener(this); myReceive = new BroadCastReceive2(); filter = new IntentFilter(); filter.addAction(ACTION); filter.setPriority(2);//設置廣播的優先級, -1000~1000 ,數字越大,優先級越高。 myReceive3 = new BroadCastReceive3(); filter3 = new IntentFilter(); filter3.addAction(ACTION); filter3.setPriority(1); } @Override protected void onResume() { /** * 注冊廣播 */ registerReceiver(myReceive, filter); registerReceiver(myReceive3, filter3); super.onResume(); } @Override protected void onPause() { /** * 注銷廣播 */ unregisterReceiver(myReceive); unregisterReceiver(myReceive3); super.onPause(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: sendBraodCast(); break; } } private void sendBraodCast() { /** * 申明廣播的 action 行為 */ Intent intent = new Intent(ACTION); intent.putExtra("key", "有序廣播測試"); this.sendOrderedBroadcast(intent, null); } /** * 內部類實現廣播接收器 */ private class BroadCastReceive2 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO 接收到廣播之後處理自己的事情 String action = intent.getAction(); String result = intent.getStringExtra("key"); MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result); Bundle bundle = new Bundle(); bundle.putString("key", "有序廣播處理之後" + "\n" + "再次發送給下一個廣播接收者"); intent.putExtra("bundle", bundle); setResultExtras(bundle); //切斷廣播,不再讓此廣播繼續往下發送。 // abortBroadcast(); } } /** * 內部類實現廣播接收器 */ private class BroadCastReceive3 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO 接收到廣播之後處理自己的事情 String action = intent.getAction(); //要不要接受上一個廣播接收器receiver2傳來的的數據 Bundle bundle = getResultExtras(true); MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + bundle.getString("key")); } } }
示例 需要在 AndroidManifest.xml中添加 權限:
發送廣播的Activity
package com.xjp.mybroadcast;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
/**
* 發送廣播的Activity
*/
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private Button btnSend;
private final static String ACTION = "com.xjp.mybroadcast.BroadCastReceive1";
private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSend = (Button) findViewById(R.id.button);
btnSend.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
sendBraodCast();
break;
}
}
private void sendBraodCast() {
/**
* 申明廣播的 action 行為
*/
Intent intent = new Intent(ACTION);
intent.putExtra("key", "普通廣播測試");
sendBroadcast(intent);
Intent intent1 = new Intent(ACTION1);
intent1.putExtra("key", "粘性廣播測試");
sendStickyBroadcast(intent1);
startActivity(new Intent(this, RecevieActivity.class));
}
}
接受廣播的Activity
package com.xjp.mybroadcast;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
/**
* Description:接受廣播的Activity
* User: xjp
* Date: 2015/5/14
* Time: 17:03
*/
public class RecevieActivity extends Activity {
private final static String ACTION1 = "com.xjp.mybroadcast.BroadCastReceive1";
private final static String ACTION2 = "com.xjp.mybroadcast.BroadCastReceive2";
private Receive receive;
private IntentFilter filter1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receive = new Receive();
filter1 = new IntentFilter();
filter1.addAction(ACTION1);
filter1.addAction(ACTION2);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(receive, filter1);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receive);
}
private class Receive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String result = intent.getStringExtra("key");
MyLog.d("the BroadCast action is " + action + " the BroadCast receive result is " + result);
}
}
}
打印結果如下:
從結果來看,只有粘性廣播才能接收到廣播信息。
需要在AndroidManifest.xml中添加權限
粘性廣播發送除了調用方法不同sendStickyBroadcast(intent1),其他都一樣。
一般廣播都是先注冊廣播,才能接收到廣播,而粘性廣播可以做到先發送廣播,哪裡需要接收該廣播就哪裡注冊,可以後注冊廣播拿到廣播的結果。這就是 普通廣播和粘性廣播的區別。從示例中也看出了普通廣播在跳轉到ReceiveActivity中是接受不到廣播發送者發出的廣播的,只有粘性廣播才能接收到。有人會奇怪,平時也沒看到哪裡使用粘性廣播??其實我也是看到Android 系統中 監測電池電量部分發現的。貼上代碼如下:
// Register for the battery changed event
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
/ Intent is sticky so using null as receiver works fine
// return value contains the status
Intent batteryStatus = this.registerReceiver(null, filter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL;
boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
當廣播接收者接收到廣播調用完onReceive()方法之後,廣播的生命周期就結束了。
因此廣播接收器不能執行超過10s耗時任務,也不能在onReceive()方法中創建Thread 來執行耗時任務,你可以開啟一個Service來執行後台耗時任務,具體可以參考Android 四大組件之Service 的生命周期和使用。
我們知道,只有先注冊了某個廣播之後,廣播接收者才能收到該廣播。廣播注冊的一個行為是將自己感興趣的IntentFilter注冊到Android系統的AMS(ActivityManagerService)中,裡面保存了一個IntentFilter列表。廣播發送者將自己的IntentFilter 的action行為發送到AMS中,然後遍歷AMS中的IntentFilter列表,看誰訂閱了該廣播,然後將消息遍歷發送到注冊了相應IntentFilter的Activity或者Service中—–也就是會調用抽象方法onReceive()方法。其中AMS起到了中間橋梁作用。
Android系統中有很多系統廣播,比如:
Android進程通信之兩種序列化方式分析 2月下旬辭職了,去海南度假到現在,領略了一把三亞風情也算任性和 然而這樣任性帶來的後果就是。。不行了我必須吐槽一句。。 沒
淺談 EventBus,淺談eventbus概述: EventBus是一款針對Android優化的發布/訂閱事件總線。 主要功能是替代Intent,Handler,Bro
我們在使用某個系統進行開發時,有必要先大體了解下它的框架結構。Android開
Android菜單項內容大全,android菜單項大全一、介紹: 菜單是許多應用中常見的用戶界面組件。 Android3.0版本以前,Android設備會提供一個專用“菜