-
BroadCast的定义:
广播是一种订阅--通知 事件,广播接收者向Android系统 register (订阅广播),广播发送者向Adnroid系统 sendBroadCast(发送广播),然后Android 系统通知所有注册该广播的接收者,广播接收者收到自己注册的广播之后实现自己想做的事情(该事情一般不超过10s,否则应用会出现ANR)。
BroadCast的分类:
1.无序广播:也就是普通广播,只要注册了该action的广播接收者都能收到该广播,且没有先后顺序。2.有序广播:广播接收者按照优先级高低依次接受该广播,并且优先接收的广播可以通过setResultExtras(Bundle)方法,将处理好的结果传送到下一个广播接收者那里。3.粘性广播:发送广播调用的方法 sendStickyBroadcast(Intent),和sendBroadcast(Intent)不同。粘性广播会一直保留在内存当中,直到有广播接收者注册该广播,该广播才算结束。不好解释,等会具体看例子。BroadCase的使用:
一.普通广播:根据注册方式不同可以分为 静态注册广播和动态注册广播。
1.静态注册广播使用实例
AndroidManifest.xml 如下:01.
<?xml version=
"1.0"
encoding=
"utf-8"
?>
02.
<manifest xmlns:android=
"http://schemas.android.com/apk/res/android"
03.
package
=
"com.xjp.mybroadcast"
>
04.
05.
<application
06.
android:allowBackup=
"true"
07.
android:icon=
"@drawable/ic_launcher"
08.
android:label=
"@string/app_name"
09.
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.
<!--静态注册广播,此处需要添加广播的action-->
21.
<receiver android:name=
".BroadCastReceive1"
>
22.
<intent-filter>
23.
<action android:name=
"com.xjp.mybroadcast.BroadCastReceive1"
></action>
24.
</intent-filter>
25.
</receiver>
26.
</application>
27.
28.
</manifest>
2.广播接收者实现如下:
01.
package
com.xjp.mybroadcast;
02.
03.
import
android.content.BroadcastReceiver;
04.
import
android.content.Context;
05.
import
android.content.Intent;
06.
07.
/**
08.
* Description:静态广播接收器
09.
* User: xjp
10.
* Date: 2015/5/14
11.
* Time: 14:56
12.
*/
13.
14.
public
class
BroadCastReceive1
extends
BroadcastReceiver {
15.
16.
@Override
17.
public
void
onReceive(Context context, Intent intent) {
18.
//TODO 接收到广播之后处理自己的事情
19.
String action = intent.getAction();
20.
String result = intent.getStringExtra(
"key"
);
21.
MyLog.d(
"the BroadCast action is "
+ action +
" the BroadCast receive result is "
+ result);
22.
}
23.
}
3.广播发送者实现如下:
01.
package
com.xjp.mybroadcast;
02.
03.
import
android.content.Intent;
04.
import
android.os.Bundle;
05.
import
android.support.v7.app.ActionBarActivity;
06.
import
android.view.View;
07.
import
android.widget.Button;
08.
09.
10.
public
class
MainActivity
extends
ActionBarActivity
implements
View.OnClickListener {
11.
12.
private
Button btnSend;
13.
14.
@Override
15.
protected
void
onCreate(Bundle savedInstanceState) {
16.
super
.onCreate(savedInstanceState);
17.
setContentView(R.layout.activity_main);
18.
19.
btnSend = (Button) findViewById(R.id.button);
20.
btnSend.setOnClickListener(
this
);
21.
22.
}
23.
24.
@Override
25.
public
void
onClick(View v) {
26.
switch
(v.getId()) {
27.
case
R.id.button:
28.
sendBraodCast();
29.
break
;
30.
}
31.
}
32.
33.
private
void
sendBraodCast() {
34.
35.
/**
36.
* 申明静态广播的 action 行为
37.
*/
38.
String action =
"com.xjp.mybroadcast.BroadCastReceive1"
;
39.
Intent intent =
new
Intent(action);
40.
intent.putExtra(
"key"
,
"静态广播测试"
);
41.
sendBroadcast(intent);
42.
}
43.
}
打印结果如下:
4.静态注册广播特点:
1.注册广播在 AndroidManifest.xml中。2.广播接收者需重新 继承 BroadcastReceiver 类来实现 onReceive()抽象方法。3.应用退出无需 注销广播,因此导致:即使广播退出之后,如果有其他应用发送该action行为的广播,此应用还是能接收到该广播的,也就是还会打印上面的 结果。
二.动态广播:
示例
001.
<pre name=
"code"
class
=
"java"
>
package
com.xjp.mybroadcast;
002.
003.
import
android.content.BroadcastReceiver;
004.
import
android.content.Context;
005.
import
android.content.Intent;
006.
import
android.content.IntentFilter;
007.
import
android.os.Bundle;
008.
import
android.support.v4.content.LocalBroadcastManager;
009.
import
android.support.v7.app.ActionBarActivity;
010.
import
android.view.View;
011.
import
android.widget.Button;
012.
013.
014.
public
class
MainActivity
extends
ActionBarActivity
implements
View.OnClickListener {
015.
016.
private
Button btnSend;
017.
018.
private
BroadCastReceive2 myReceive;
019.
020.
private
IntentFilter filter;
021.
022.
private
final
static
String ACTION =
"com.xjp.mybroadcast.BroadCastReceive2"
;
023.
024.
@Override
025.
protected
void
onCreate(Bundle savedInstanceState) {
026.
super
.onCreate(savedInstanceState);
027.
setContentView(R.layout.activity_main);
028.
029.
btnSend = (Button) findViewById(R.id.button);
030.
btnSend.setOnClickListener(
this
);
031.
032.
myReceive =
new
BroadCastReceive2();
033.
filter =
new
IntentFilter();
034.
filter.addAction(ACTION);
035.
036.
}
037.
038.
039.
@Override
040.
protected
void
onResume() {
041.
/**
042.
* 注册广播
043.
*/
044.
045.
LocalBroadcastManager.getInstance(
this
).registerReceiver(myReceive, filter);
//官方建议使用
046.
047.
// this.registerReceiver(myReceive, filter);
048.
049.
super
.onResume();
050.
}
051.
052.
053.
@Override
054.
protected
void
onPause() {
055.
/**
056.
* 注销广播
057.
*/
058.
059.
LocalBroadcastManager.getInstance(
this
).unregisterReceiver(myReceive);
//官方建议使用
060.
061.
// this.unregisterReceiver(myReceive);
062.
063.
super
.onPause();
064.
}
065.
066.
@Override
067.
public
void
onClick(View v) {
068.
switch
(v.getId()) {
069.
case
R.id.button:
070.
sendBraodCast();
071.
break
;
072.
}
073.
}
074.
075.
private
void
sendBraodCast() {
076.
077.
/**
078.
* 申明广播的 action 行为
079.
*/
080.
Intent intent =
new
Intent(ACTION);
081.
intent.putExtra(
"key"
,
"动态广播测试"
);
082.
083.
/**
084.
* 官方提倡使用如下发送广播,原因是更快,更安全,不会导致内存泄漏
085.
*/
086.
LocalBroadcastManager.getInstance(
this
).sendBroadcast(intent);
087.
088.
// this.sendBroadcast(intent);
089.
}
090.
091.
092.
/**
093.
* 内部类实现广播接收器
094.
*/
095.
private
class
BroadCastReceive2
extends
BroadcastReceiver {
096.
097.
@Override
098.
public
void
onReceive(Context context, Intent intent) {
099.
//TODO 接收到广播之后处理自己的事情
100.
String action = intent.getAction();
101.
String result = intent.getStringExtra(
"key"
);
102.
MyLog.d(
"the BroadCast action is "
+ action +
" the BroadCast receive result is "
+ result);
103.
}
104.
}
105.
}
1.
动态广播特点:
1.在代码中调用registerReceiver()方法 注册广播。2.广播接收者需重新 继承 BroadcastReceiver 类实现内部类。3.动态广播在应用退出时需要 调用unregisterReceiver()方法来注销广播。如果应用退出时没有注销广播,会报如下错误:因此,我们通常的做法是:在 onResume()中注册广播,在onPause中注销广播。4.当广播注销之后就接收不到任何系统发送的广播了。
三.有序广播:
示例:
001.
<pre name=
"code"
class
=
"java"
>
package
com.xjp.mybroadcast;
002.
003.
import
android.content.BroadcastReceiver;
004.
import
android.content.Context;
005.
import
android.content.Intent;
006.
import
android.content.IntentFilter;
007.
import
android.os.Bundle;
008.
import
android.support.v7.app.ActionBarActivity;
009.
import
android.view.View;
010.
import
android.widget.Button;
011.
012.
013.
public
class
MainActivity
extends
ActionBarActivity
implements
View.OnClickListener {
014.
015.
private
Button btnSend;
016.
017.
private
BroadCastReceive2 myReceive;
018.
019.
private
BroadCastReceive3 myReceive3;
020.
021.
private
IntentFilter filter;
022.
023.
private
IntentFilter filter3;
024.
025.
private
final
static
String ACTION =
"com.xjp.mybroadcast.BroadCastReceive2"
;
026.
027.
@Override
028.
protected
void
onCreate(Bundle savedInstanceState) {
029.
super
.onCreate(savedInstanceState);
030.
setContentView(R.layout.activity_main);
031.
032.
btnSend = (Button) findViewById(R.id.button);
033.
btnSend.setOnClickListener(
this
);
034.
035.
myReceive =
new
BroadCastReceive2();
036.
filter =
new
IntentFilter();
037.
filter.addAction(ACTION);
038.
filter.setPriority(
2
);
//设置广播的优先级, -1000~1000 ,数字越大,优先级越高。
039.
040.
myReceive3 =
new
BroadCastReceive3();
041.
filter3 =
new
IntentFilter();
042.
filter3.addAction(ACTION);
043.
filter3.setPriority(
1
);
044.
045.
046.
}
047.
048.
049.
@Override
050.
protected
void
onResume() {
051.
/**
052.
* 注册广播
053.
*/
054.
registerReceiver(myReceive, filter);
055.
registerReceiver(myReceive3, filter3);
056.
057.
058.
super
.onResume();
059.
}
060.
061.
062.
@Override
063.
protected
void
onPause() {
064.
/**
065.
* 注销广播
066.
*/
067.
068.
unregisterReceiver(myReceive);
069.
unregisterReceiver(myReceive3);
070.
071.
super
.onPause();
072.
}
073.
074.
@Override
075.
public
void
onClick(View v) {
076.
switch
(v.getId()) {
077.
case
R.id.button:
078.
sendBraodCast();
079.
break
;
080.
}
081.
}
082.
083.
private
void
sendBraodCast() {
084.
085.
/**
086.
* 申明广播的 action 行为
087.
*/
088.
Intent intent =
new
Intent(ACTION);
089.
intent.putExtra(
"key"
,
"有序广播测试"
);
090.
091.
this
.sendOrderedBroadcast(intent,
null
);
092.
}
093.
094.
095.
/**
096.
* 内部类实现广播接收器
097.
*/
098.
private
class
BroadCastReceive2
extends
BroadcastReceiver {
099.
100.
@Override
101.
public
void
onReceive(Context context, Intent intent) {
102.
//TODO 接收到广播之后处理自己的事情
103.
String action = intent.getAction();
104.
String result = intent.getStringExtra(
"key"
);
105.
MyLog.d(
"the BroadCast action is "
+ action +
" the BroadCast receive result is "
+ result);
106.
107.
Bundle bundle =
new
Bundle();
108.
bundle.putString(
"key"
,
"有序广播处理之后"
+
"\n"
+
"再次发送给下一个广播接收者"
);
109.
intent.putExtra(
"bundle"
, bundle);
110.
setResultExtras(bundle);
111.
//切断广播,不再让此广播继续往下发送。
112.
// abortBroadcast();
113.
}
114.
}
115.
116.
/**
117.
* 内部类实现广播接收器
118.
*/
119.
private
class
BroadCastReceive3
extends
BroadcastReceiver {
120.
121.
@Override
122.
public
void
onReceive(Context context, Intent intent) {
123.
//TODO 接收到广播之后处理自己的事情
124.
String action = intent.getAction();
125.
//要不要接受上一个广播接收器receiver2传来的的数据
126.
Bundle bundle = getResultExtras(
true
);
127.
MyLog.d(
"the BroadCast action is "
+ action +
" the BroadCast receive result is "
+ bundle.getString(
"key"
));
128.
}
129.
}
130.
}
1.
有序广播特点:
1.所有广播接收者的action是一致的,发送有序广播调用 sendOrderedBroadcast()方法。2.有序广播的接收者需要调用setPriority()方法设置广播接收者的优先级。数字越大,优先接受广播。3.有序广播如果需要终止 广播继续往下发送,可以调用 abortBroadcast()方法切断广播。4.先接收广播者可以将自己的处理结果通过setResultExtras()方法继续传递给下一个广播接收者。5.后接收者可以调用 getResultExtras(true)来自己决定是否接收上一个广播传递过来的数据。四.粘性广播:
示例 需要在 AndroidManifest.xml中添加 权限1.
<uses-permission android:name=
"android.permission.BROADCAST_STICKY"
></uses-permission>
发送广播的Activity01.
package
com.xjp.mybroadcast;
02.
03.
import
android.content.Intent;
04.
import
android.os.Bundle;
05.
import
android.support.v7.app.ActionBarActivity;
06.
import
android.view.View;
07.
import
android.widget.Button;
08.
09.
10.
/**
11.
* 发送广播的Activity
12.
*/
13.
public
class
MainActivity
extends
ActionBarActivity
implements
View.OnClickListener {
14.
15.
private
Button btnSend;
16.
17.
18.
private
final
static
String ACTION =
"com.xjp.mybroadcast.BroadCastReceive1"
;
19.
private
final
static
String ACTION1 =
"com.xjp.mybroadcast.BroadCastReceive2"
;
20.
21.
@Override
22.
protected
void
onCreate(Bundle savedInstanceState) {
23.
super
.onCreate(savedInstanceState);
24.
setContentView(R.layout.activity_main);
25.
26.
btnSend = (Button) findViewById(R.id.button);
27.
btnSend.setOnClickListener(
this
);
28.
}
29.
30.
31.
@Override
32.
public
void
onClick(View v) {
33.
switch
(v.getId()) {
34.
case
R.id.button:
35.
sendBraodCast();
36.
break
;
37.
}
38.
}
39.
40.
private
void
sendBraodCast() {
41.
42.
/**
43.
* 申明广播的 action 行为
44.
*/
45.
Intent intent =
new
Intent(ACTION);
46.
intent.putExtra(
"key"
,
"普通广播测试"
);
47.
sendBroadcast(intent);
48.
49.
Intent intent1 =
new
Intent(ACTION1);
50.
intent1.putExtra(
"key"
,
"粘性广播测试"
);
51.
sendStickyBroadcast(intent1);
52.
startActivity(
new
Intent(
this
, RecevieActivity.
class
));
53.
}
54.
}
01.
package
com.xjp.mybroadcast;
02.
03.
import
android.app.Activity;
04.
import
android.content.BroadcastReceiver;
05.
import
android.content.Context;
06.
import
android.content.Intent;
07.
import
android.content.IntentFilter;
08.
import
android.os.Bundle;
09.
10.
/**
11.
* Description:接受广播的Activity
12.
* User: xjp
13.
* Date: 2015/5/14
14.
* Time: 17:03
15.
*/
16.
17.
public
class
RecevieActivity
extends
Activity {
18.
19.
private
final
static
String ACTION1 =
"com.xjp.mybroadcast.BroadCastReceive1"
;
20.
private
final
static
String ACTION2 =
"com.xjp.mybroadcast.BroadCastReceive2"
;
21.
22.
private
Receive receive;
23.
24.
private
IntentFilter filter1;
25.
26.
@Override
27.
protected
void
onCreate(Bundle savedInstanceState) {
28.
super
.onCreate(savedInstanceState);
29.
30.
receive =
new
Receive();
31.
32.
filter1 =
new
IntentFilter();
33.
filter1.addAction(ACTION1);
34.
filter1.addAction(ACTION2);
35.
36.
}
37.
38.
@Override
39.
protected
void
onResume() {
40.
super
.onResume();
41.
registerReceiver(receive, filter1);
42.
}
43.
44.
@Override
45.
protected
void
onPause() {
46.
super
.onPause();
47.
unregisterReceiver(receive);
48.
}
49.
50.
private
class
Receive
extends
BroadcastReceiver {
51.
@Override
52.
public
void
onReceive(Context context, Intent intent) {
53.
String action = intent.getAction();
54.
String result = intent.getStringExtra(
"key"
);
55.
MyLog.d(
"the BroadCast action is "
+ action +
" the BroadCast receive result is "
+ result);
56.
}
57.
}
58.
}
打印结果如下:
从结果来看,只有粘性广播才能接收到广播信息。
粘性广播特点:
1.需要在AndroidManifest.xml中添加权限1.
<uses-permission android:name=
"android.permission.BROADCAST_STICKY"
></uses-permission>
3.一般广播都是先注册广播,才能接收到广播,而粘性广播可以做到先发送广播,哪里需要接收该广播就哪里注册,可以后注册广播拿到广播的结果。这就是 普通广播和粘性广播的区别。从示例中也看出了普通广播在跳转到ReceiveActivity中是接受不到广播发送者发出的广播的,只有粘性广播才能接收到。
有人会奇怪,平时也没看到哪里使用粘性广播??其实我也是看到Android 系统中 监测电池电量部分发现的。贴上代码如下:
01.
// Register for the battery changed event
02.
IntentFilter filter =
new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
03.
04.
/ Intent is sticky so using
null
as receiver works fine
05.
// return value contains the status
06.
Intent batteryStatus =
this
.registerReceiver(
null
, filter);
07.
08.
// Are we charging / charged?
09.
int
status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -
1
);
10.
boolean
isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
11.
|| status == BatteryManager.BATTERY_STATUS_FULL;
12.
13.
boolean
isFull = status == BatteryManager.BATTERY_STATUS_FULL;
14.
15.
// How are we charging?
16.
int
chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -
1
);
17.
boolean
usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
18.
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系统中有很多系统广播,比如:
Event | Description |
---|---|
Intent.ACTION_BOOT_COMPLETED | Boot completed. Requires the android.permission.RECEIVE_BOOT_COMPLETEDpermission. |
Intent.ACTION_POWER_CONNECTED | Power got connected to the device. |
Intent.ACTION_POWER_DISCONNECTED | Power got disconnected to the device. |
Intent.ACTION_BATTERY_LOW | Triggered on low battery. Typically used to reduce activities in your app which consume power. |
Intent.ACTION_BATTERY_OKAY | Battery status good again. |