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

本文详细介绍了Android中的广播接收者概念,包括如何创建广播接收者、配置不同类型的广播事件及其监听方式,同时对比了无序广播与有序广播的区别,并提供了具体的实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

创建一个广播接收者:

  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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值