Android开发之BroadcastReceiver

BroadcastReceiver介绍

        BroadcastReceiver是Android四大组件之一,是Android开发中使用最频繁的类之一,是一种广泛运用的在应用之间消息传输机制。
        Android的广播机制是一个典型的发布-订阅模式,就是观察者模式,它最大的特点就是发送方不关心接收方是否接收到数据,也不关心接收方是如何处理数据。通过这样的形式来达到接收双方的完全解耦。一个广播可以有一个或多个接收者。
        广播机制主要用来监听系统或者应用发出的广播信息,然后根据广播信息做出相应的逻辑处理,也可以用来传输少量的低频数据。
        Android中的广播机制包含三部分,分别是用于发送广播的Broadcast、接收广播的BroadcastReceiver和用于传递消息的Intent。BroadcastReceiver自身不实现图形界面,当它收到某个通知后可以启动Activity、Service或Notification来提醒用户。在实际开发过程中开机启动服务、网络状态变化、电量变化、短信和来电通知都可以通过接收系统的广播来让我们自己的应用做出相应的处理。



广播的种类

标准广播(Normal Broadcast)

        标准广播是完全异步的。广播发出之后所有的广播接收器几乎都会在同一时刻接收到这条广播消息,顺序不分先后。
        这种广播的优点是传播的效率高,但是所有receiver的执行顺序是不确定的。缺点是接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有与之匹配的广播接收器为止。

发送一条广播
receiver01
receiver02
receiver03
有序广播(Ordered Broadcast)

        有序广播是一种同步执行的广播。在有序广播发出之后同一时刻只会有一个广播接收器能收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传播。
        此时的广播是有先后顺序的,所有的广播接收器按照优先级顺序依次执行,优先级高的先执行,低的后执行。广播接收器的优先级通过清单文件AndroidManifest.xml中receiver标签下intent-filter中的android:priority属性来设置,数值越大优先级越高,数值越小优先级越低。
        有序广播可以在广播传递的过程中对广播进行中断操作,通过在onReceiver()方法中调用abortBroadcast()方法实现,这样后面的广播接收器就无法收到广播消息了。

发送一条广播
receiver01
receiver02
receiver03
本地广播(Local Broadcast)

        为了解决广播的安全性问题,Android引入了本地广播机制,该机制能够在引用内部进行传递,并且广播接收器也只能接收来自本应用发出的广播。
        标准、有序广播都是属于系统全局的广播,就是发出的广播可以被其他任何应用都接收到,并且我们也可以接收到来自其他任何应用的广播,这样就会带来一定的安全隐患,例如我们发送的一些携带关键性数据的广播就很有可能被其他应用截获,或者其他应用不停地向我们的广播接收器发送各种垃圾广播。
        本地广播主要是一个LocalBroadcastManager对广播进行管理,并提供发送跟注册广播接收器的方法。


粘性广播(Sticky Broadcast)

        粘性广播通发送的广播会一直滞留,当有匹配此广播的广播接收器被注册后,该广播接收器就会收到这条广播。
        sendStickyBroadcast()只保留最后一条广播,并且一直保留下去,这样即使已经有广播接收器处理了该广播,当再有匹配的广播接收器被注册时,此广播仍会被接收。
        使用Sticky Broadcast发送广播之前需要获取到BROADCAST_STICKY权限;

<uses-permission android:name="android.permission.BROADCAST_STICKY">



本地广播的优势

  1. 明确地知道正在发送的广播不会离开我们的程序,不需要担心机密数据泄漏;
  2. 其他程序无法将广播发送到我们程序的内部,不需要担心会有安全漏洞的隐患;
  3. 发送本地广播比起发送系统全局广播将会更加高效;


注册广播的方式

        广播注册的方式有两种,分别是静态注册和动态注册;


静态注册

        静态注册就是将广播的注册行为在清单文件AndroidManifest.xml中进行。静态注册的广播接收者只要App在系统中运行则一直可以接收到广播消息。
        application标签内出现了一个新的标签receiver,所有静态注册的广播接收器都是在这里进行注册的。通过android:name来指定具体注册哪一个广播接收器。然后在intent-filter标签里加入想要接收的广播。
        应用里所有的receiver都可以在清单文件中查看。
        要销毁静态注册的广播接收器可以通过PackageManager的Receiver禁用。

<application>
       ......
       <receiver android:name=".BootCompleteReceiver">
           <intent-filter>
               <action android:name="android.intent.action.BOOT_COMPLETED"/>
           </intent-filter>
       </receiver>
</application>   

动态注册

        动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大优势。它的缺点是必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate()方法里的。动态注册的广播接收者当注册的Activity或Service销毁了就接收不到广播了。

BrodacastReceiver receiver = new BroadcastReceiver(); 
IntentFilter intentFilter = new IntentFilter(); 
intentFilter.addAction(CALL_ACTION); 
context.registerReceiver(receiver, intentFilter);



动态注册和静态注册的区别

        1.静态注册的广播接收器一经安装就常驻在系统之中,不需要重新启动唤醒接收者;
        动态注册的广播接收器随着应用的生命周期,由registerReceiver开始监听,由unregisterReceiver撤销监听,如果应用退出后没有撤销已经注册的接收器应用将会报错
        2.当广播接收器通过intent启动一个Activity或者Service时,如果intent中无法匹配到相应的组件。动态注册的广播接收器将会导致应用报错,静态注册的广播接收器不会有任何报错,因为自从应用安装完成后,广播接收器跟应用就脱离了关系。


广播的发送

发送标准广播

        发送广播之前需要定义一个广播接收器用来准备接收此广播;

public class MyBroadcastReceiver extends BroadcastReceiver{}

        发送标准广播需要通过Context.sendBroadcast()实现。

Context.sendBroadcast();

        然后对该receiver进行注册,注册分为动态注册和静态注册,我们既可以选择在Java代码中直接对目标receiver进行注册,也可以在清单文件AndroidManifest.xml中对该receiver进行注册;

<application>
       ......
       <receiver android:name=".BootCompleteReceiver">
           <intent-filter>
               <action android:name="android.intent.action.BOOT_COMPLETED"/>
           </intent-filter>
       </receiver>
</application>   

        在Activity或Fragment中使用广播发送广播,最后在onDestroy()方法中对广播进行销毁资源回收。


发送有序广播

        发送有序广播通过调用方法Context.sendOrderedBroadcast()方法去实现,该方法接收两个参数,Intent & 权限相关的字符串,无特殊要求可置为null。

Context.sendOrderedBroadcast(intent,null);

        当广播接收器接收到广播后可以用setResult()将结果传递给下一个广播接收器,通过getResult()获取上个广播接收器返回的内容,可以通过abortBroadcast()让系统中止该广播,使得该广播不再继续传送到别的广播接收器了。


发送本地广播

        本地广播的使用需要通过LocalBroadcastManager(Context context)的sendBroadcast()、registerReceiver()、、unregisterReceiver()等方法去实现。
        本地广播和普通广播只是操作的类不一样,其他的接口基本上都累死,因此替换为本地广播的成本相对较低。为了程序的安全,建议在不需要其他进程接收广播的情况下使用本地广播。

//注册Receiver
LocalBroadcastManager.getInstance(Context context)
.registerReceiver(receiver,intentFilter);

//注销Receiver
LocalBroadcastManager.getInstance(Context context)
.unregisterReceiver(receiver);	

//发送异步广播	
LocalBroadcastManager.getInstance(Context context)
.sendBroadcast(new Intent(HELLO_ACTION));

//同步广播
LocalBroadcastManager.getInstance(Context context)
.sendBroadcastSync(new Intent());			

        本地广播无法通过静态注册方式接收。静态注册主要是为了让程序在未启动的情况下也能收到广播,而发送本地广播时我们的应用肯定已经启动了,因此完全不需要使用静态注册的功能。


发送Sticky广播

        粘性广播Sticky Broadcast通过Context.sendStickyBroadcast()方法来发送。如果只想处理一遍该广播,可以通过removeStickyBroadcast()函数实现。

Context.sendStickyBroadcast();
Context.removeStickyBroadcast();



BroadcastReceiver使用注意

        当系统或应用发出广播时,将会扫描系统中的所有广播接收者,通过action匹配将广播发送给相应的接收者,接收者收到广播后将会产生一个广播接收者的实例,执行其中的onReceiver()这个方法,这个实例的生命周期只有10秒,10秒内没有执行结束onReceiver()系统将会报错;
        在onReceiver()执行完毕之后,该实例将会被销毁,所以不要在onReceiver()中执行耗时操作,也不要在里面创建子线程处理业务(可能子线程没处理完,接收者就被回收了,子线程也会跟着被回收掉);正确的处理方法就是通过in调用Activity或者Service处理业务。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值