Android四大组件之BroadcastReceiver
BroadcastReceiver,顾名思义就是“广播接收者”的意思,它是Android四大基本组件之一,这种组件本质上是一种全局的监听器,用于监听系统全局的广播消息。它可以接收来自系统和应用的的广播。
由于BroadcastReceiver是一种全局的监听器,因此它可以非常方便地实现系统不同组件之间的通信。比如Activity与通过startService()方法启动的Service之间通信,就可以借助于BroadcastReceiver来实现。
BroadcastReceiver简介:
BroadcastReceiver用于接收程序(包括系统程序和一般应用)通过sendBroadcast()方法发出的Broadcast intents。
程序启动BroadcastReceiver的步骤(发出广播):
1) 创建需要启动BroadcastReceiver的Intent。
2) 调用Context的sendBroadcast
()或sendOrderedBroadcast
()方法来启动指定的BroadcastReceiver。其中sendBroadcast
发送的是普通广播,sendOrderedBroadcast发送的是有序广播。
当应用发出一个Broadcast Intent之后所匹配该Intent的组件都可能被启动。
创建BroadcastReceiver的步骤:
第一步:创建BroadcastReceiver的子类:
由于BroadcastReceiver本质上是一种监听器,所以创建BroadcastReceiver的方法也非常简单,只需要创建一个BroadcastReceiver的子类然后重写onReceive (Context context, Intentintent)方法即可。
具体代码如下:
1
2
3
4
5
6
7
8
9
10
|
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String msg=intent.getExtras().get( "msg" ).toString(); Toast.makeText(context, "intent.getAction()" +intent.getAction().toString(), Toast.LENGTH_LONG).show(); System.out.println( "msg:" +msg); } } |
第二步:注册BroadcastReceiver
一旦实现了BroadcastReceiver,接下就应该指定该BroadcastReceiver能匹配的Intent即注册BroadcastReceiver。注册BroadcastReceiver的方式有两种:
第一种是静态注册:这种方法是在配置AndroidManifest.xml配置文件中注册,通过这种方式注册的广播为常驻型广播,也就是说如果应用程序关闭了,有相应事件触发,程序还是会被系统自动调用运行。例如:
1
2
3
4
5
6
7
|
<!-- 在配置文件中注册BroadcastReceiver能够匹配的Intent --> <receiver android:name= "com.example.test.MyBroadcastReceiver" > <intent-filter> </action> <category android:name= "android.intent.category.DEFAULT" ></category> </intent-filter> </receiver> |
第二种是动态注册:这种方法是通过代码在.Java文件中进行注册。通过这种方式注册的广播为非常驻型广播,即它会跟随Activity的生命周期,所以在Activity结束前我们需要调用unregisterReceiver(receiver)方法移除它。例如:
1
2
3
4
5
6
|
//通过代码的方式动态注册MyBroadcastReceiver MyBroadcastReceiver receiver= new MyBroadcastReceiver(); IntentFilter filter= new IntentFilter(); filter.addAction( "android.intent.action.MyBroadcastReceiver" ); //注册receiver registerReceiver(receiver, filter); |
注意:如果我们在Activity中注册了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注册否则会出现异常。方法如下:
1
2
3
4
5
6
7
|
@Override protected void onDestroy() { // TODO Auto-generated method stub super .onDestroy(); //当Activity销毁的时候取消注册BroadcastReceiver unregisterReceiver(receiver); } |
BroadcastReceiver的生命周期:
BroadcastReceiver的生命周期,从对象调用它开始,到onReceiver方法执行完成之后结束。另外,每次广播被接收后会重新创建BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。
如果需要在BroadcastReceiver中执行耗时的操作,可以通过Intent启动Service来完成。但不能绑定Service。
特别是,您可能无法从一个BroadcastReceiver中显示一个对话框,或绑定到服务。对于前者,则应该使用NotificationManager的API。对于后者,你可以使用Context.startService()来启动一个Service。
广播的类型:
Broadcast的类型有两种:普通广播和有序广播。
Normal broadcasts(普通广播):Normal broadcasts是完全异步的可以同一时间被所有的接收者接收到。消息的传递效率比较高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播。
Ordered broadcasts(有序广播):Ordered broadcasts的接收者按照一定的优先级进行消息的接收。如:A,B,C的优先级依次降低,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。 另外Ordered broadcasts的接收者可以通过abortBroadcast()的方式取消广播的传播,也可以通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。
应用实例:
发送并接收普通和有序广播:
运行效果图:
实例代码:
MainActivity.java:发送广播:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package com.jph.broadcastreceiverdemo; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Activity; import android.content.Intent; /** * Describe:<br> * <br>本实例有两个优先级别不同的广播接收器 * <br>通过发送普通广播,和有序广播来学习 * <br>BroadcastReceiver的原理 * <br>@author jph * <br>@Date:2014.08.05 * */ public class MainActivity extends Activity { MyBroadcastReceiver receiver; Button btnSend,btnSend2; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSend=(Button)findViewById(R.id.btnSend); btnSend2=(Button)findViewById(R.id.btnSend2); receiver= new MyBroadcastReceiver(); OnClickListener listener= new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btnSend: Intent intent= new Intent(); intent.setAction( "android.intent.action.MyBroadcastReceiver" ); intent.putExtra( "msg" , "我在发送广播!这只是一个普通的广播," + "你们无法通过abortBroadcast()的方式停止广播的传播," + "也无法往Broadcast中存入数据因为它是异步的" ); sendBroadcast(intent); break ; case R.id.btnSend2: Intent intent2= new Intent(); intent2.setAction( "android.intent.action.MyBroadcastReceiver" ); intent2.putExtra( "msg" , "我在发送个有序的广播," + "你们可以通过abortBroadcast()的方式停止广播的传播," + "也可以往Broadcast中存入数据" ); sendOrderedBroadcast(intent2, null ); break ; default : break ; } } }; btnSend.setOnClickListener(listener); btnSend2.setOnClickListener(listener); } } |
MyBroadcastReceiver.java:接收广播
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.jph.broadcastreceiverdemo; import java.text.SimpleDateFormat; import java.util.Date; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; /** * Describe:<br> * <br>@author jph * <br>@Date:2014.08.05 * */ public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String msg=intent.getExtras().get( "msg" ).toString(); setResultData( "MyBroadcastReceiver接收到广播" ); Toast.makeText(context, "时间:" + new SimpleDateFormat( "yyyy-MM-dd hh.mm.ss" ).format( new Date()) + "\nMyBroadcastReceiver收到Action名为:" +intent.getAction().toString() + "的广播 \nComponent:" +intent.getComponent() + "\nmsg:" +msg, Toast.LENGTH_LONG).show(); } } |
SecondBroadcastReceiver.java接收广播
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.jph.broadcastreceiverdemo; import java.text.SimpleDateFormat; import java.util.Date; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; /** * Describe:<br> * <br>@author jph * <br>@Date:2014.08.05 * */ public class SecondBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String msg=intent.getExtras().get( "msg" ).toString(); String result=getResultData(); Toast.makeText(context, "时间:" + new SimpleDateFormat( "yyyy-MM-dd hh.mm.ss" ).format( new Date()) + "\nSecondBroadcastReceiver收到Action名为:" +intent.getAction().toString() + "的广播 \nComponent:" +intent.getComponent() + "\nmsg:" +msg+ "\n上一个接受者传来的reult:" +result, Toast.LENGTH_LONG).show(); } } |
配置文件AndroidManifest.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<!--?xml version= "1.0" encoding= "utf-8" ?--> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package = "com.jph.broadcastreceiverdemo" android:versioncode= "1" android:versionname= "1.0" > <uses-sdk android:minsdkversion= "8" android:targetsdkversion= "18" > <intent-filter> <category android:name= "android.intent.category.LAUNCHER" > </category></action></intent-filter> </activity> <!-- 在配置文件中注册MyBroadcastReceiver能够匹配的Intent --> <receiver android:name= "com.jph.broadcastreceiverdemo.MyBroadcastReceiver" > <intent-filter android:priority= "200" > </action> <category android:name= "android.intent.category.DEFAULT" ></category> </intent-filter> </receiver> <!-- 在配置文件中注册SecondBroadcastReceiver能够匹配的Intent --> <receiver android:name= "com.jph.broadcastreceiverdemo.SecondBroadcastReceiver" > <intent-filter android:priority= "100" > </action> <category android:name= "android.intent.category.DEFAULT" ></category> </intent-filter> </receiver> </application> </uses-sdk></manifest> |