一、概念
BroadCastReceiver,广播接收者,android四大组件之一,它就像是生活中的收音机可以接收电台的广播一样,可以接收系统的广播或者用户自定义的广播。简单来说,广播接收者的作用有:
1.接收系统的广播,比如系统启动完成、电池低电量或者拨打电话等,我们可以通过一定的配置接收系统发送的这些广播从而知道这些事件的发生;
2.接收应用发送的广播,可以是本应用也可以是其他应用,从而实现进程内或者进程间的通信,举个例子,如果你的手机安装了百度全家桶或者阿里全家桶或者企鹅全家桶等等这些豪华套餐,只要你启动其中一个应用,它就可以自定义一个广播然后发送出去,然后全家桶的其他成员接受到这个广播之后就可以全部在后台启动起来,干一些为人民服务的好事。(当然这只是实现方式之一,要实现这个效果还有很多其他的方式)
二、广播接收者的简单使用(静态注册广播接收者)
广播接收者作为四大组件之一,一般来说需要在清单文件中配置,但是特殊的广播接收者也可以在程序中动态注册。例子是监听打电话的事件,在用户拨打电话的时候弹出一个吐司:
1.创建广播接收者,也就是创建一个class,让它继承BroadcastReceiver
![](https://i-blog.csdnimg.cn/blog_migrate/8e9048d388c16e3c7bfe7dc7970102d8.png)
2.在清单文件中配置广播接收者,用android studio创建的四大组件IDE会自动在清单文件中注册
![](https://i-blog.csdnimg.cn/blog_migrate/575569b7a49a5fd774af51957f48b230.png)
但是广播接收者的监听事件还是需要开发者手动配置,监听外拨电话的广播接收者配置如下
<receiver
- android:name=".PhoneReceiver"
android:enabled="true"
- <intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
需要注意的是,监听广播往往需要添加响应的权限,监听外拨电话的声明如下,6.0以上需要动态申请权限:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
3.在创建的广播接收者中重写onReceive方法
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"正在打电话",Toast.LENGTH_SHORT).show();
}
大功告成,运行结果:
三、动态注册广播接收者
依然是接收打电话的广播,动态注册广播接收者的步骤如下:
1.新建class继承自BroadcasReceiver
![](https://i-blog.csdnimg.cn/blog_migrate/fae0e1ea85d851f11df157045971023e.png)
2.重写onReceive方法
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"收到广播啦~",Toast.LENGTH_SHORT).show();
}
3.在代码中注册广播接收者
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
receiver = new DynamicReceiver();
registerReceiver(receiver,filter,"android.permission.PROCESS_OUTGOING_CALLS",null);
4.动态注册的广播接收者需要在使用完成后或者activity退出的时候手动注销
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
其中registerReceiver是重载的方法,其中一个是上面带四个参数的,另一个只带有前两个参数。第一个为需要注册的广播接收者,第二个为IntentFilter实例对象,其作用与清单文件中的intent-filter对应,第三个为需要的权限,最后一个是一个handler对象,标记的是接收广播的线程,可以是null,为null时时主线程。
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/894ebf257574972dd93c2f6681919b73.jpeg)
四、自定义广播
自定义广播,主要是定义一个action,然后在广播接收者中配置这个action。代码比较简单,直接上
package com.example.study;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private MyReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//先注册广播接收者,再发广播,记得退出时注销广播接收者
IntentFilter filter = new IntentFilter("con.kwell.myaction");
receiver = new MyReceiver();
registerReceiver(receiver,filter);
//带有Action的Intent对象
Intent intent = new Intent("con.kwell.myaction");
//发送广播
sendBroadcast(intent);
}
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"收到了自己发的广播",Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播接收者
unregisterReceiver(receiver);
}
}
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/253d6a14a190e4481118625fa04d0cd9.png)
五、有序广播与无序广播
上面演示的都是无序广播,所有广播接收者接收无序广播的顺序是不确定的,其特点是效率高,但是无法使用setResult和getResult以及中断广播这些方法。发送无序广播的方法是sendBroadcast()
package com.example.study;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private MyReceiver receiver;
private MyReceiver receiver2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//先注册广播接收者,再发广播,记得退出时注销广播接收者
IntentFilter filter = new IntentFilter("con.kwell.myaction");
//设置优先级为最高
filter.setPriority(Integer.MAX_VALUE);
receiver = new MyReceiver(1);
registerReceiver(receiver,filter);
//另一个广播接收者,优先级设置为1000
IntentFilter filter2 = new IntentFilter("con.kwell.myaction");
filter2.setPriority(1);
receiver2 = new MyReceiver(2);
registerReceiver(receiver2,filter2);
//带有Action的Intent对象
Intent intent = new Intent("con.kwell.myaction");
//发送无序广播
sendBroadcast(intent);
}
class MyReceiver extends BroadcastReceiver{
private int id;
public MyReceiver(int id){
this.id = id;
}
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"广播接收者"+id+"收到了自己发的广播",Toast.LENGTH_SHORT).show();
//中断这个广播
abortBroadcast();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播接收者
unregisterReceiver(receiver);
unregisterReceiver(receiver2);
}
}
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/a3ab96bcdccef347484c848d0792bf2c.gif)
由此可以看到,我们设置的优先级以及中断广播并没有起作用,广播接收者2依旧接收到了广播。
有序广播的特点是所有的广播接收者按照优先级依次接收广播,优先级高的先接受到,它可以获取Intent的数据并且可以对其进行修改,然后再向优先级低的广播接收者进行传递,也可以中断此次广播。
对应两种注册方式,广播接收者的优先级可以在清单文件中配置,也可以在动态注册的时候设置,清单文件配置实例
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.INPUT_METHOD_CHANGED"/>
</intent-filter>
</receiver>
清单文件配置的优先级大小从-1000到1000,数值越大优先级越高。发送有序广播的方法是sendOrderedBroadcast,把上面的例子改造一下,只需要把发送广播的一行替换成
//发送有序广播
sendOrderedBroadcast(intent,null);
运行结果
![](https://i-blog.csdnimg.cn/blog_migrate/e6a67dfb05fc79d525883d5c26a65012.gif)
可以看到,优先级高的广播接收者1顺利的把本次广播中断了,2没有再接收到广播。
未完待续....
未完待续....