广播接收者与广播发送者复习

时间:2020-12-04 10:10:32

广播接收者的本质就是一个全局的监听器,用于监听系统全局的广播消息,比如:拨打电话、收发短信、屏幕解锁等事件产生了,系统会发送广播,只要应用程序接受到这条广播,就知道系统发生了相应的事件,从而执行相应的代码。

创建一个广播接收者:

  1. 声明一个类继承自BroadcastReceiver,重写BroadcastReceiver的onReceiver方法即可。
  2. 指定BroadcastReceiver可以匹配的Intent:

    a.在清单文件中进行指定

    b.使用代码动态指定(特殊的广播接收者必须使用代码的方式进行动态指定)

下面创建一个广播接收者:

1.声明一个类继承自BroadcastReceiver,重写BroadcastReceiver的onReceiver方法即可。


/**
* Created by 春水碧于天 on 2017/1/22.
*/


public class SmsReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if(action.equals("android.provider.Telephony.SMS_RECEIVED")){

Toast.makeText(context,"来信息了!",Toast.LENGTH_SHORT).show();



}else if(action.equals("android.intent.action.PHONE_STATE")){


Toast.makeText(context,"来电话了!",Toast.LENGTH_SHORT).show();

}

}
}

2.在清单文件中进行配置(application节点下):

 <receiver android:name=".SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>

注:一个广播接收者可以监听多个事件,此处监听了电话状态的改变,接收短信。此处还需要添加上两个权限:

   <uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

当配置的action 的事件发生了 onReceive方法就会执行

运行效果:

广播接收者与广播发送者复习

对于一些比较频繁的广播事件比如屏幕解锁,锁屏,电池电量变化,这样的广播接收者在清单文件里面注册无效。需要使用代码进行动态注册

监听屏幕锁屏事件的广播接收者:

1.声明一个类继承自BroadcastReceiver,重写BroadcastReceiver的onReceiver方法即可。

/**
* Created by 春水碧于天 on 2017/1/22.
*/


public class SpecialReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if(action.equals("android.intent.action.SCREEN_ON")){

Toast.makeText(context,"屏幕解锁了",Toast.LENGTH_SHORT).show();

}else if(action.equals("android.intent.action.SCREEN_OFF")){

Toast.makeText(context,"屏幕锁屏了",Toast.LENGTH_SHORT).show();
}

}
}

2.在MainActivity中对要监听的事件进行动态的注册:

public class MainActivity extends AppCompatActivity {

private SpecialReceiver specialReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//动态的去注册屏幕解锁和锁屏的广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.SCREEN_ON");
intentFilter.addAction("android.intent.action.SCREEN_OFF");

//创建一个广播接收者的实例
specialReceiver = new SpecialReceiver();

/**
* 参数1:BroadcastReceiver receiver:
* 参数2:IntentFilter filter
*/

registerReceiver(specialReceiver,intentFilter);
}


@Override
protected void onDestroy() {
super.onDestroy();

//动态注册的广播收者一定都要取消注册才行
unregisterReceiver(specialReceiver);

}
}

在MainActivity销毁的时候,一定unregisterReceiver(specialReceiver)
,对广播接收者取消注册。

否则会报下面的错误:

Activity com.example.reviewbroadcastreciver.MainActivity has leaked IntentReceiver com.example.reviewbroadcastreciver.SpecialReceiver@752c889 that was originally registered here. Are you missing a call to unregisterReceiver()?

运行效果:

广播接收者与广播发送者复习

这样子做的话如果MainActivity销毁之后,也就是广播接收者取消注册了,就不会再监听到锁屏状态的变化了,这应该也是谷歌出于保证系统流畅度的设计,避免程序间的唤醒以达到节省内存的目的,如果需要时刻监听这种比较频繁的广播事件则可以再Service中进行动态注册。


广播发送者:

广播既可以由Android系统进行发送,也可以由我们自己的程序来向外发送广播。
在程序中发送广播十分简单,只需要调用Context的sendBroadcast(Intent intent)
方法即可,这条广播将会启动intent参数所对应的BroadcastReceiver.

广播分为:

  1. 无序广播:通过Context.sendBroadcast()方法来发送,所有的广播接收者(BroadcastReceiver)的接收顺序不确定,这种方式的效率更高,但是但BroadcastReceiver无法使用setResult系列、getResult系列及abort(中止)系列API。

  2. 有序广播:是通过Context.sendOrderedBroadcast来发送,所有的receiver依次执行。
    BroadcastReceiver可以使用setResult系列函数来结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以abort系列函数来让系统丢弃该广播,使用该广播不再传送到别的BroadcastReceiver。
    可以通过在intent-filter中设置android:priority属性来设置receiver的优先级,优先级相同的receiver其执行顺序不确定。
    如果BroadcastReceiver是代码中注册的话,且其intent-filter拥有相同android:priority属性的话,先注册的将先收到广播。

简要概述:

  1. 无序广播:广播不可以被终止 数据不可以被修改

  2. 有序广播:按照优先级一级一级的接收 有序广播可以被终止 数据可以被修改

发送一个无序广播:

  //发送一个无序广播
public void Click(View v){
Intent intent = new Intent();
intent.setAction("com.example.reviewbroadcastreciver");
intent.putExtra("msg","你妈叫你们回家吃饭啦……");
sendBroadcast(intent);
}

发送一个有序广播:

    //发送一个有序广播
//发送一个有序广播
public void OrderClick(View v){

Intent intent = new Intent();
intent.setAction("com.example.reviewbroadcastreciver");
//第三个参数为最终要执行的广播接收者
sendOrderedBroadcast(intent, null, new FinalReceiver(), null, 1, "你妈叫你回家吃饭了!", null);
}

}

FinalReceiver.java

/**
* 最终执行的Receiver,不需要在清单文件中配置
* Created by 春水碧于天 on 2017/1/23.
*/

public class FinalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

String msg = getResultData();

Toast.makeText(context,"报告奶奶,爸爸妈妈都叫我回家吃饭了!",Toast.LENGTH_SHORT).show();

}
}

接收一个有序广播:

创建4个广播接收者用于测试:

广播接收者与广播发送者复习

在清单文件中进行配置:

 <receiver android:name=".FirstReceiver">
<!--设置接收广播的优先级-->
<intent-filter android:priority="1000">

<action android:name="com.example.reviewbroadcastreciver" />

</intent-filter>

</receiver>

<receiver android:name=".SecondReceiver">
<!--设置接收广播的优先级-->
<intent-filter android:priority="600">

<action android:name="com.example.reviewbroadcastreciver" />

</intent-filter>

</receiver>

<receiver android:name=".ThirdReceiver">
<!--设置接收广播的优先级-->
<intent-filter android:priority="200">

<action android:name="com.example.reviewbroadcastreciver" />

</intent-filter>

</receiver>

<receiver android:name=".FourthReceiver">
<!--设置接收广播的优先级-->
<intent-filter android:priority="0">

<action android:name="com.example.reviewbroadcastreciver" />

</intent-filter>

</receiver>

<intent-filter android:priority="1000">配置接收广播的优先级priority的取值从-1000到1000,数值越大优先级越高。

这里只写出第一个广播接收者,其它的代码与之相同。


/**
* Created by 春水碧于天 on 2017/1/23.
*/


public class FirstReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

String msg = getResultData();

Toast.makeText(context,"FirstReceiver"+msg,Toast.LENGTH_SHORT).show();

}
}

运行效果:
广播接收者与广播发送者复习
可以看到每个广播接收者按照清单文件中配置的优先级依次接收

使用setResult修改广播发送的内容:
SecondReceiver.Java

/**
* Created by 春水碧于天 on 2017/1/23.
*/


public class SecondReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

String msg = getResultData();

setResultData("你爸爸叫你回家吃饭啦…………");

Toast.makeText(context,"SecondReceiver"+msg,Toast.LENGTH_SHORT).show();


}
}

使用abortBroadcast( )进行广播的截断
ThirdReceiver.Java

/**
* Created by 春水碧于天 on 2017/1/23.
*/


public class ThirdReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {


String msg = getResultData();
Toast.makeText(context,"ThirdReceiver"+msg,Toast.LENGTH_SHORT).show();

abortBroadcast(); //进行广播拦截,不再向下传递


}
}

运行效果:
广播接收者与广播发送者复习
可见在 ThirdReceiver 获取的内容为SecondReceiver修改过
的,FourthReceiver因为广播在ThirdReceiver中被截断了,所以没有收到广播,FinalReceiver为最后执行的广播。

┭┮﹏┭┮ O(∩_∩)O