Broadcast Receiver顾名思义是指广播接收器,它和事件处理机制类似,只不过事件处理机制是程序组件级别的,而广播事件处理机制是系统级别的。我们可以使用Intent来启动一个程序组件,我们可以通过使用sendBroadcast()方法来发起一个系统级别的事件广播来传递消息。我们可以在应用程序中实现Broadcast Receiver来监听和响应这些广播的Intent。
事件的广播比较简单,同样还是构建Intent对象,然后调用sendBroadcast()方法将广播发出。事件的接收是通过定义一个继承BroadcastReceiver的类来实现的,继承该类后覆盖其onReceive()方法,在该方法中响应事件。
1、系统广播事件
Android系统中定义了很多标准的Broadcast Action来响应系统广播事件。例如,ACTION_TIME_CHANGED(时间改变时触发)、ACTION_BOOT_COMLETED(系统启动完成后触发)这些广播是系统自动发出的,我们直接定义事件接收器进行接收就可以使用这些系统消息。常见的标准广播Action常量如下表:
常量名称 | 常量值 | 意义 |
ACTION_BOOT_COMLETED | android.intent.action. BOOT_COMLETED | 系统启动完成后触发 |
ACTION_TIME_CHANGED | android.intent.action. ACTION_TIME_CHANGED | 时间改变 |
ACTION_DATE_CHANGED | android.intent.action. ACTION_DATE_CHANGED | 日期改变 |
ACTION_TIMEZONE_CHANGED | android.intent.action.ACTION_TIMEZONE_CHANGED | 时区改变 |
ACTION_BATTERY_LOW | android.intent.action. ACTION_BATTERY_LOW | 电量低 |
ACTION_MEDIA_EJECT | android.intent.action. ACTION_MEDIA_EJECT | 插入或拔出外部媒体 |
ACTION_MEDIA_BUTTON | android.intent.action. ACTION_MEDIA_BUTTON | 按下媒体按钮 |
ACTION_PACKAGE_ADDED | android.intent.action. ACTION_PACKAGE_ADDED | 添加包 |
ACTION_PACKAGE_REMOVED | android.intent.action. ACTION_PACKAGE_REMOVED | 删除包 |
/**
* 显示系统启动完成广播接收器
*/
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
//显示接收到的广播
Log.i("MyReceiver","BOOT_COMPLETED-----------------------");
}
}
在AndroidManifest.xml配置文件中注册该接收器,注意这里<intent-filter>中的<action>属性必须是“android.intent.action. BOOT_COMLETED”才能接收系统启动完成广播事件。
<receiver android:name=".MyReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
2、自定广播事件
自定义一个广播是比较简单的,首先在程序组件里构件所有广播的Intent,使用sendBroadcast方法发送出去。其次定义一个广播接收器,该接收器类继承BroadcastReceiver,并覆盖onReceiver方法来响应事件。最后注册该广播接收器,我们可以在使用动态方式注册(在代码中注册),也可以使用静态方式注册(在AndroidManifest.xml配置文件中注册)。
静态注册
静态注册是在AndroidManifest.xml文件中配置的,我们就来为MyReceiver注册一个广播地址:
<receiver android:name=".MyReceiver">
<intent-filter >
<action android:name="android.intent.action.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
配置了以上信息之后,只要是android.intent.action.MY_BROADCAST这个地址的广播,MyReceiver都能够接收的到。注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyReceiver也会被系统调用而自动运行。
动态注册
动态注册需要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播,一般是在Activity的onResume()方法中使用registerReceiver()方法来注册一个广播,在Activity的onPause()方法中使用unregisterReceiver()方法来注销一个广播接收器。下面我们就来看一下注册的代码:
public class TestReceiverActivity extends Activity{
private MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onResume() {
super.onResume();
//实例化Receiver
receiver = new MyReceiver();
//实例化IntentFilter
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.MY_BROADCAST");
//注册Receiver
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
//注销Receiver
unregisterReceiver(receiver);
}
}
这种注册方式与静态注册相反,不是常驻型的,也就是说广播会跟随程序的生命周期。
有序广播(Ordered Broadcast)
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。
public class TestReceiverActivity extends Activity{
private Button btnButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnButton= (Button) findViewById(R.id.btnButton);
btnButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//发送广播
Intent intent = new Intent
("com.igood.broadcastreceiver.test.MY_BROADCAST");
intent.putExtra("msg", "TestReceiverActivity");
//发送有序广播
sendOrderedBroadcast(intent, null);
/*sendBroadcast(intent); //发送普通广播(无序广播)*/
}
});
}
}
//FirstReceiver.java
public class FirstReceiver extends BroadcastReceiver {
private static final String TAG = "orderedBroadcast";
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
//显示接收到的广播
Log.d(TAG, "FirstReceiver: " + msg);
Bundle bundle = new Bundle();
bundle.putString("msg", msg+" add FirstReceiver");//重新修改消息内容
setResultExtras(bundle);
}
}
//SecondReceiver.java
public class SecondReceiver extends BroadcastReceiver {
private static final String TAG = "orderedBroadcast";
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = this.getResultExtras(false);//true:前一个广播没有结果时创建新的Bundle;false:不创建Bundle
String msg = bundle.getString("msg");
//显示接收到的广播
Log.d(TAG, "SecondReceiver: " + msg);
bundle.putString("msg", msg+" add SecondReceiver");//重新修改消息内容
setResultExtras(bundle);
//停止广播,优先级比SecondReceiver低的广播接收器将收不到此广播
abortBroadcast();
}
}
//ThirdReceiver.java
public class ThirdReceiver extends BroadcastReceiver {
private static final String TAG = "orderedBroadcast";
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = this.getResultExtras(false);//true:前一个广播没有结果时创建新的Bundle;false:不创建Bundle
String msg = bundle.getString("msg");
//显示接收到的广播
Log.d(TAG, "ThirdReceiver: " + msg);
bundle.putString("msg", msg+" add ThirdReceiver");//重新修改消息内容
setResultExtras(bundle);
}
}
我们注意到,在FirstReceiver和SecondReceiver中最后都使用了setResultExtras方法将一个Bundle对象设置为结果集对象,传递到下一个接收者那里,这样以来,优先级低的接收者可以用getResultExtras获取到最新的经过处理的信息集合。
我们需要在AndroidMainfest.xml文件里为三个接收者注册广播:
<receiver android:name=".FirstReceiver">
<intent-filter android:priority="100">
<action android:name="com.igood.broadcastreceiver.test.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".SecondReceiver">
<intent-filter android:priority="90">
<action android:name="com.igood.broadcastreceiver.test.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".ThirdReceiver">
<intent-filter android:priority="80">
<action android:name="com.igood.broadcastreceiver.test.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
我们看到,现在这三个接收者的<intent-filter>多了一个android:priority属性,并且依次减小。这个属性的范围在-1000到1000,数值越大,优先级越高。优先级高的广播接收器先执行。(这里先执行FirstReceiver再执行SecondReceiver,最后执行ThirdReceiver)。在前一个执行的广播中设置结果值,传给下一个广播。也可以通过BroadcastReceiver.abortBroadcast()终止广播,后面的广播接收器不会得到执行。
运行效果如下:
由于在SecondReceiver里调用了abortBroadcast方法将广播进行终止,因此优先级比SecondReceiver低的ThirdReceiver接收器接收不到这条广播。
3、Notification和NotificationManager的使用
Broadcast Receiver组件并没有提供可视化界面来显示广播信息。这里我们可以使用Notification和NotificationManager来实现可视化的信息显示。通过使用它们我们可以显示广播信息的内容、图标、声音以及震动等信息。
使用Notification和NotificationManager比较简单,一般获得系统级的服务NotificationManager,然后实例化Notification,设置其属性,通过NotificationManager发出通知就可以了。
我们下面定义一个TestReceiverActivity发出广播,顶一个MyReceiver类接收广播,当接收到广播后,启动一个服务DisplayService,在该类中使用Notification和NotificationManager来可视化显示广播通知。
//TestReceiverActivity.java
public class TestReceiverActivity extends Activity{
private Button btnButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnButton= (Button) findViewById(R.id.btnButton);
btnButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//发送广播
Intent intent = new Intent("com.igood.broadcastreceiver.test.MY_BROADCAST");
intent.putExtra("msg", "TestReceiverActivity");
//发送广播
sendBroadcast(intent, null);
}
});
}
}
//MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
//显示接收到的广播
Log.d(TAG, "MyReceiver----------------- ");
Intent ien = new Intent();
ien.putExtra("msg", "MyReceiver接收到广播,我有一个秘密告诉你.........");
ien.setAction("com.igood.test.DisplayService");
//启动Service
context.startService(ien);
}
}
//DisplayService.java
public class DisplayService extends Service{
private Notification notify;
private NotificationManager nm;
public static final int ID = 1;
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//获得NotificationManager实例
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
//实例化Notification
notify = new Notification();
//设置显示图标,该图标会在状态栏显示
notify.icon = R.drawable.ic_launcher;
//设置显示提示信息,该信息会在状态栏显示
notify.tickerText = "你有新的消息";
//显示时间
notify.when = System.currentTimeMillis();
Intent i = new Intent(this,TestReceiverActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
//设置事件信息
notify.setLatestEventInfo(this, "MyReceiver接收到广播.....", intent.getStringExtra("msg"), pi);
//发出通知
nm.notify(ID,notify);
}
@Override
public void onCreate() {
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
AndroidManifest.xml清单如下:
<activity android:name=".TestReceiverActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="com.igood.broadcastreceiver.test.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name=".DisplayService">
<intent-filter>
<action android:name="com.igood.test.DisplayService"/>
</intent-filter>
</service>
运行效果如下: