Android之BroadcastReceiver(接收广播消息)学习笔记(一)
BroadcastReceiver是四大组件之一,这种组件本质上就是一个全局监听器,用于监听系统全局的广播消息。这种实现,就是我们典型的观察者设计模式了,谁需要监听广播,就注册一个相应的广播即可。
BoradcastReceiver用于接收程序所有发出的Broadcast Intent,与应用程序启动Activity,Service相同的是,程序启动BoradcastReceiver也只需要两步。
1. 创建需要启动的BoradcastReceiver的Intent。
2. 掉用Context的sendBroadcast()或者sendOrderedBroadcast()方法来启动指定的BoradcastReceiver。
当应用程序发送一个Broadcast Intent只有,所有注册了该广播的Intent的BoradcastReceiver都有可能被启动。
与Activity、Service具有 完整的生命周期不同,BoradcastReceiver本质上只是一个系统级的监听器——它专门负责监听各程序所发出的Broadcast。
由于BoradcastReceiver本质上属于一个监听器,因此实现BoradcastReceiver的方法也十分简单,只要重写BoradcastReceiver的onReceive(Context context, Intent intent)方法即可。
只要实现了BoradcastReceiver,然后就是要指定该BoradcastReceiver能匹配的Intent了,对于指定Intent,我们通常有两种方式。
1. 使用代码指定:
IntentFilter filter = new IntentFilter("android.normal.first.broadcast");
MyReceiver receiver = new MyReceiver();
registerReceiver(receiver, filter);
对于上面的注册,首先建立一个IntentFilter对象,对应的参数就是我们指定的action,对于action,可以是自定义的,也可以是定义好的,这个取决与自己的具体实现。receiver对象,是我们自定义的一个BroadcastReceiver对象。最后通过添加registerReceiver(receiver, filter)即可
2. 直接在AndroidManifest.xml中配置。
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.normal.first.broadcast" />
</intent-filter>
</receiver>
每次系统Broadcast事件发生只有,系统就会创建新的对应的BroadcastReceiver实例,并自动触发它的onReceive()方法,onReceive方法执行完后,BroadcastReceiver实例就会被销毁。
BroadcastReceiver与Activity还有一个区别就是,当我们通过Intent启动指定的Activity组件时,如果系统没有找到合适的Activity组件,则会导致程序崩溃,而BroadcastReceiver找不到指定的Intent时,则不会出现任何问题。
需要注意的是,如果在BroadcastReceiver的onReceive()方法中不能在10秒内执行完成,则会出现ANR,程序无响应,所以我们也不能在BroadcastReceiver中执行耗时操作。并且我们也不能在BroadcastReceiver的onReceive()方法中去创建新的线程来完成耗时操作,因为BroadcastReceiver本身的生命周期非常短,可能出现的情况是,子线程还没有结束,BroadcastReceiver就已经退出了,如果BroadcastReceiver进程结束了,虽然该进程中还有用户启动的新线程,但由于该进程内不包含任何活动组件,因此系统可能在内存紧张时优先结束该进程。这样就可能导致BroadcastReceiver启动的子线程不能执行完成。
通常广播分为两种方式;
1. 无序广播,对于无序广播,他的优点完全是采用异步的方式进行广播,可以在同一时刻被所有的接受者收到,消息传递效率比较高。缺点是接受者不能将处理结果传递给下一个接受者,并且无法终止Broadcast Intent的传播。
2. 有序广播,按照BroadcastReceiver的优先级来一次接收Broadcast,比如A > B > C,则最先接收到的是A,其实是B,最后是C,优先级别设置有两种方式,一种是在xml中配置,一种是在代码中通过filter.setPriority()设置优先级别,具体的将在以下代码中来实现。
下面先来实现无序广播方式(通过代码方式注册广播)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
>
<Button
android:id="@+id/mNormalB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送无序广播" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mNormalB;
private boolean flag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
event();
}
private void event() {
mNormalB.setOnClickListener(this);
}
private void init() {
mNormalB = ((Button) findViewById(R.id.mNormalB));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.mNormalB:
sendNormalBroadCast1();
break;
}
}
private void sendNormalBroadCast1() {
if(flag){
//只需要注册一次即可
normalBroad();
flag = false;
}
//设置Intent
Intent intent = new Intent("android.normal.first.broadcast");
//设置传递的数据
Bundle bundle = new Bundle();
bundle.putInt("num1", 58);
bundle.putString("msg", "消息1");
intent.putExtras(bundle);
//发送无序广播
sendBroadcast(intent);
}
private void normalBroad() {
IntentFilter filter = new IntentFilter("android.normal.first.broadcast");
MyReceiver1 receiver1 = new MyReceiver1();
MyReceiver2 receiver2 = new MyReceiver2();
MyReceiver3 receiver3 = new MyReceiver3();
registerReceiver(receiver1, filter);
registerReceiver(receiver2, filter);
registerReceiver(receiver3, filter);
}
}
两个接收者:
MyReceiver1 .java
public class MyReceiver1 extends BroadcastReceiver {
public MyReceiver1() {
}
/**
* 实现该方法即可,系统会自动调用处理
* @param context 上下文
* @param intent 对应的Intent
*/
@Override
public void onReceive(Context context, Intent intent) {
//获取Intent中携带的数据
Bundle bundle = intent.getExtras();
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
Log.i("IT_Real", "onReceive1: num1 = " + num1 + "msg = " + msg);
}
}
}
MyReceiver2.java
public class MyReceiver2 extends BroadcastReceiver {
public MyReceiver2() {
}
/**
* 实现该方法即可,系统会自动调用处理
* @param context 上下文
* @param intent 对应的Intent
*/
@Override
public void onReceive(Context context, Intent intent) {
//获取Intent中携带的数据
Bundle bundle = intent.getExtras();
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
Log.i("IT_Real", "onReceive1: num1 = " + num1 + "msg = " + msg);
}
}
}
当MainActivity通过点击发送按钮,则这两个BroadcastReceiver会接收到对应的广播消息。
无序广播方式(清单方式注册广播)
MainActiviy.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mNormalB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
event();
}
private void event() {
mNormalB.setOnClickListener(this);
}
private void init() {
mNormalB = ((Button) findViewById(R.id.mNormalB));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.mNormalB:
sendNormalBroadCast1();
break;
}
}
private void sendNormalBroadCast1() {
Intent intent = new Intent("android.normal.first.broadcast");
Bundle bundle = new Bundle();
bundle.putInt("num1",58);
bundle.putString("msg","消息1");
intent.putExtras(bundle);
sendBroadcast(intent);
}
}
AndroidManifest.xml
<receiver
android:name=".MyReceiver1"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.normal.first.broadcast" />
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiver2"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.normal.first.broadcast" />
</intent-filter>
</receiver>
其中,注册的BroadcastReceiver和上面的MyReceiver1、 MyReceiver2 一样。无序广播的两种方式就实现了。非常简单。
有序广播的实现(代码注册方式)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
>
<Button
android:id="@+id/mOrderB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送有序广播" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mOrderB;
private boolean flag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
event();
}
private void event() {
mOrderB.setOnClickListener(this);
}
private void init() {
mOrderB = ((Button) findViewById(R.id.mOrderB));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.mOrderB:
sendOrderBroadCast1();
break;
}
}
private void sendOrderBroadCast1() {
if(flag){
//只需要注册一次即可
orderBroad();
flag = false;
}
//Intent
Intent intent = new Intent("android.order.first.broadcast");
//存放对应的数据
Bundle bundle = new Bundle();
bundle.putInt("num1",58);
bundle.putString("msg","消息1");
intent.putExtras(bundle);
//发送有序广播
sendOrderedBroadcast(intent,null);
}
private void orderBroad(){
IntentFilter filter = new IntentFilter("android.order.first.broadcast");
MyReceiverOrder1 receiver1 = new MyReceiverOrder1();
MyReceiverOrder2 receiver2 = new MyReceiverOrder2();
MyReceiverOrder3 receiver3 = new MyReceiverOrder3();
MyReceiverOrder4 receiver4 = new MyReceiverOrder4();
//filter.setPriority(300);
registerReceiver(receiver1, filter);
//filter.setPriority(1000);
registerReceiver(receiver2,filter);
//filter.setPriority(500);
registerReceiver(receiver3,filter);
//filter.setPriority(100);
registerReceiver(receiver4,filter);
}
}
四个自定义的广播接收者
MyReceiverOrder1 .java
public class MyReceiverOrder1 extends BroadcastReceiver {
public MyReceiverOrder1() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
Log.i("IT_Real", "onReceive1: " + num1 + "msg = " + msg);
bundle.putString("msg2","省级消息");
setResultExtras(bundle);
}
//abortBroadcast();//这里表示在某个接收者中可以中断该广播,之后的所有低于该广播接收的则都接不到广播消息。
}
}
MyReceiverOrder2.java
public class MyReceiverOrder2 extends BroadcastReceiver {
public MyReceiverOrder2() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
String msg2 = bundle.getString("msg2");
Log.i("IT_Real", "onReceive2: " + num1 + "msg = " + msg + "msg2 = " + msg2);
bundle.putString("msg3","市级消息");
setResultExtras(bundle);
}
}
}
MyReceiverOrder3 .java
public class MyReceiverOrder3 extends BroadcastReceiver {
public MyReceiverOrder3() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
String msg3 = bundle.getString("msg3");
Log.i("IT_Real", "onReceive3: " + num1 + "msg = " + msg + "msg3 = " + msg3);
bundle.putString("msg4","县级消息");
setResultExtras(bundle);
}
}
}
MyReceiverOrder4.java
public class MyReceiverOrder4 extends BroadcastReceiver {
public MyReceiverOrder4() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
if(bundle != null){
int num1 = bundle.getInt("num1");
String msg = bundle.getString("msg");
String msg4 = bundle.getString("msg4");
Log.i("IT_Real", "onReceive4: " + num1 + "msg = " + msg + "msg4 = " + msg4);
}
}
}
上面就是一个有序的广播实现,上面没有设置对应的优先级别,所以默认的级别是从registerReceiver(receiver1, filter);注册的顺序依次下来的,receiver1 > receiver2 > receiver3 > receiver4,如果要设置对应的优先级,比如 receiver2 > receiver3 > receiver1 > receiver4,则只要将上面的注释去掉即可,即setPriority(int number)里面的number数值越大,优先级别越高。这里的四个广播接受者,按照我们默认的顺序来接受广播,这里刚好模拟了一个领导发送消息的功能,国家发送消息给省级receiver1,市级receiver2接受了省级receiver1的消息,receiver1里面多加了一消息,依次到最后,receiver4为普通老百姓。即国家发消息给——省级(receiver1)——市级(receiver2)——县级(receiver3)——老百姓(receiver4)
有序广播的实现(清单注册方式)
MainActiviy.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mOrderB;
private boolean flag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
event();
}
private void event() {
mOrderB.setOnClickListener(this);
}
private void init() {
mOrderB = ((Button) findViewById(R.id.mOrderB));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.mOrderB:
sendOrderBroadCast1();
break;
}
}
private void sendOrderBroadCast1() {
//Intent
Intent intent = new Intent("android.order.first.broadcast");
//存放对应的数据
Bundle bundle = new Bundle();
bundle.putInt("num1",58);
bundle.putString("msg","消息1");
intent.putExtras(bundle);
//发送有序广播
sendOrderedBroadcast(intent,null);
}
}
AndroidManifest.xml中的注册形式
<receiver
android:name=".MyReceiverOrder1"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.order.first.broadcast"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiverOrder2"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="500">
<action android:name="android.order.first.broadcast"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiverOrder3"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="300">
<action android:name="android.order.first.broadcast"/>
</intent-filter>
</receiver>
<receiver
android:name=".MyReceiverOrder4"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="android.order.first.broadcast"/>
</intent-filter>intent-filter
</receiver>
android:priority 表示的是设置优先级别,这些注册必须在<application> </application>
内
这样就完成了有序广播的两种实现方式。