一篇就够了系列之BroadcastReceiver全解析

前言:

上一篇一篇就够了系列之Service全解析,介绍了Android四大组件的Service,本篇继续来介绍Android四大组件之BroadcastReceiver(广播接收者)。

Broadacast(广播):

Google官方文档广播

首先,我们应该清楚在Android系统中,Broadcast(广播)是什么?

广播是一种可以在不同App之间,类似订阅者模式(publish-subscribe design pattern)的信息交流的方式。比如当系统的 开机,电量的变化 都会发送广播,对这些广播进行了订阅的广播接收者此时会接收到相关的通知然后就可以在其中做出相应的处理操作。这些系统的广播很有用,但是你也要十分小心不要滥用广播这种方式,会有导致系统运行缓慢的可能。

分类

  • 普通广播(Normal Broadacast)
  • 有序广播(Order Broadcast)
  • 本地广播(LocalBroadcast)
  • 粘性广播(StickyBroadcast):已经废弃了该API,不做讨论。

英文原文:

  • The sendBroadcast(Intent) method sends broadcasts to all receivers in an undefined order. This is called a Normal Broadcast. This is more efficient, but means that receivers cannot read results from other receivers, propagate data received from the broadcast, or abort the broadcast.

  • The sendOrderedBroadcast(Intent, String) method sends broadcasts to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won’t be passed to other receivers. The order receivers run in can be controlled with the android:priority attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.

  • The LocalBroadcastManager.sendBroadcast method sends broadcasts to receivers that are in the same app as the sender. If you don’t need to send broadcasts across apps, use local broadcasts. The implementation is much more efficient (no interprocess communication needed) and you don’t need to worry about any security issues related to other apps being able to receive or send your broadcasts.

普通广播
一般的广播,即发送一个广播后,所有监听该广播的接收者都可以接收到,同时接收并且不能阻止别人接收
代码为:

sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));

有序广播
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。优先级在manifest中进行设置,代码为:

sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"), "interview.permission.MY_BROADCAST_PERMISSION);  

或者

sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
       scheduler, initialCode, initialData, initialExtras)

注意,在两个参数的方法中,使用sendOrderedBroadcast方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。
所以我们在AndroidMainfest.xml中定义和声明一个权限:

    //定义
    <permission 
        android:protectionLevel="normal"
        android:name="interview.permission.MY_BROADCAST_PERMISSION"/>
    //声明
    <uses-permission android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

在七个参数的方法中:
resultReceiver :BroadcastReceiver类型,即指定最后的广播接收器。
scheduler:Handler类型,调度自定义处理程序,用以安排 resultReceiver 回调 ; 如果为 null 将在语境中的主线程举行。
initialCode :int类型,一种结果代码的初始值。通常为 Activity.RESULT_OK 。这个值是 -1 ;为其他 int 型 也可以,如 0,1,2;
initialData :String类型,一种结果数据的初始值。通常情况下为空 ;
initialExtras :Bundle类型,一种结果额外的初始值。通常情况下为空;

本地广播:即发送的广播只有该App可以接收到,信息更加安全,效率更高,推荐使用。

  LocalBroadcastManager.getInstance(BroadcastActivity.this).sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));

总结:通过以上可知,广播的发送很简单,在Activity或者Service中直接调用即可,下面来看看接收者。

BroadcastReceiver(广播接收者)

广播接收者作为四大组件之一,使用的时候需要进行注册,不同于其他的组件,BroadcastReceiver除了在Manifest中进行注册外,还可以用Java代码直接注册。

Manifest注册:

manifest:

            <permission 
        android:protectionLevel="normal"
        android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

    <uses-permission android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

        <receiver android:name=".FourComponet.broadcast.MyReceiver1"
            >
            <intent-filter android:priority="-1000">
                <action android:name="com.wenyi.interview.mynormalb"/>
            </intent-filter>
        </receiver>

        <receiver android:name=".FourComponet.broadcast.MyReceiver2">
            <intent-filter android:priority="1000">
                <action android:name="com.wenyi.interview.mynormalb"/>
            </intent-filter>
        </receiver>

Activity:

public class BroadcastActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broadcast);


        findViewById(R.id.normal_broadcast).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));
            }
        });

        findViewById(R.id.ordered_broadcast).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"),"interview.permission.MY_BROADCAST_PERMISSION");
            }
        });
        findViewById(R.id.ordered_broadcast_2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"),"interview.permission.MY_BROADCAST_PERMISSION"
                ,new MyReceiver1(),null,0,"",null);
            }
        });

    }
}

Receiver1:

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

        Log.i("wy", "MyReceiver1    time:"+System.currentTimeMillis());
    }
}

Receiver2:

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

        Log.i("wy", "MyReceiver2    time:"+System.currentTimeMillis());

        abortBroadcast();

    }
}

代码十分的简单,主要可简单总结为:

  1. 继承Broadcast,重写onReceiver方法
  2. 在manifest进行注册,需要定义action,这是广播的依据,有序广播需要定义和申明权限
  3. 普通广播都能接收,有序广播按照优先级接收,可以销毁,调用 abortBroadcast()方法
  4. 打印log,尝试加深理解

Java代码注册:

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

        //动态注册receiver的Intent过滤器和action
        IntentFilter filter = new IntentFilter();
        filter.addAction("dynamic_register");
        mMyReceiver3=new MyReceiver3();
        registerReceiver(mMyReceiver3, filter);

        Intent intent = new Intent();
        //这条广播的标志
        intent.setAction("dynamic_register");
        //发送广播
        sendBroadcast(intent);

        //动态注册receiver的Intent过滤器和action
        IntentFilter filter1 = new IntentFilter();
        filter1.addAction("dynamic_register_2");
        mMyReceiver4=new MyReceiver4();
        manager=LocalBroadcastManager.getInstance(BroadcastActivity.this);
        manager.registerReceiver(mMyReceiver4, filter1);

        Intent intent1 = new Intent();
        //这条广播的标志
        intent1.setAction("dynamic_register_2");
        //发送广播
        manager.sendBroadcast(intent1);
    }

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

        unregisterReceiver(mMyReceiver3);
        manager.unregisterReceiver(mMyReceiver4);
    }

说明:

  1. 代码进行注册,一般是在onResume中进行注册,onPause中进行解注册,一定要解注册。
  2. 注册代码逻辑也就是设置filter的action,然后调用注册方法。
  3. 本地广播只能这样进行动态注册,注册的调用对象是LocalBroadcastManager,解注册也是如此。

最后:

  • onReceiver中不能做耗时操作,超过十秒钟会异常
  • 生命周期十分简单,创建,运行,结束

常见的系统广播:

1.开机启动服务

action:android.intent.action.BOOT_COMPLETED
category :android.intent.category.DEFAULT
同时申明权限:

2.网络状态变化

action:android.net.conn.CONNECTIVITY_CHANGE
category :android.intent.category.DEFAULT
同时申明权限:

3.电量变化

action:android.intent.action.BATTERY_CHANGED
category :android.intent.category.DEFAULT

4.监听SD卡状态

清单文件中定义广播接收者接收的类型,监听SD卡常见的三种状态,所以广播接收者需要接收三种广播

 <receiver android:name="com.itheima.sdcradlistener.SDCardReceiver">
    <intent-filter >
        <action android:name="android.intent.action.MEDIA_MOUNTED"/>
        <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
        <action android:name="android.intent.action.MEDIA_REMOVED"/>
        <data android:scheme="file"/>
    </intent-filter>
</receiver>

5监听应用的安装、卸载、更新

原理:应用在安装卸载更新时,系统会发送广播,广播里会携带应用的包名
清单文件定义广播接收者接收的类型,因为要监听应用的三个动作,所以需要接收三种广播

<receiver android:name="com.itheima.app.AppReceiver">
    <intent-filter >
        <action android:name="android.intent.action.PACKAGE_ADDED"/>
        <action android:name="android.intent.action.PACKAGE_REPLACED"/>
        <action android:name="android.intent.action.PACKAGE_REMOVED"/>
        <data android:scheme="package"/>
    </intent-filter>
</receiver>

欢迎阅读其他系列文章:

一篇就够了系列之Activity全解析

一篇就够了系列之Service全解析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值