Android-BroadcastReceiver基础

      BroadcastReceiver是Android的四大组件之一,是用于接收来自系统和应用的广播对并对其进行响应的组件。

BroadcastReceiver的四种类型

1、普通广播

      普通广播是一种完全异步执行**的广播,在广播发出之后,所有的广播接收器几乎会同时接收到这条广播消息。此类广播效率较高而且不能截断。

自定义 intent的广播(最常用)。发送广播使用如下:

Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);

若被注册了的广播接收者中注册时intentFilter的action与上述匹配,则会接收此广播(即进行回调onReceive())。如下MBroadcastReceiver则会接收上述广播

若发送广播有相应权限,那么广播接收者也需要相应权限

<receiver 
    android:name=".MBroadcastReceiver" >
    <intent-filter>
        <action android:name="BROADCAST_ACTION" />
    </intent-filter>
</receiver>

2、有序广播

      有序广播是一种同步执行(顺序)的广播,广播发出之后,优先级高的广播接收器就可以先接收到广播消息,执行完该广播接收器的逻辑后,可以选择截断正在传递的广播或者继续传递,如果广播消息被截断,之后的广播接收器则无法收到广播消息。有序广播中的“有序”是针对广播接收者而言的。有序广播的定义过程与普通广播无异,发送有序广播方法:sendOrderedBroadcast()

      有序广播的接收者们将按照事先声明的优先级依次接收,数越大优先级越高(取值范围:-1000~10000)

android:priority 定义广播接收者的优先级

<intent-filter android:priority="n"/>

或调用ntentFilter对象的setPriority()设置

终止广播:调用abortBroadcast()方法终止广播,一旦终止后面接收者就无法接收广播

3、系统广播

      Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播。
每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:

系统操作action
监听网络变化android.net.conn.CONNECTIVITY_CHANGE
关闭或打开飞行模式Intent.ACTION_AIRPLANE_MODE_CHANGED
充电时或电量发生变化Intent.ACTION_BATTERY_CHANGED
电池电量低Intent.ACTION_BATTERY_LOW
电池电量充足(即从电量低变化到饱满时会发出广播Intent.ACTION_BATTERY_OKAY
系统启动完成后(仅广播一次)Intent.ACTION_BOOT_COMPLETED
按下照相时的拍照按键(硬件按键)时Intent.ACTION_CAMERA_BUTTON
屏幕锁屏Intent.ACTION_CLOSE_SYSTEM_DIALOGS
设备当前设置被改变时(界面语言、设备方向等)Intent.ACTION_CONFIGURATION_CHANGED
插入耳机时Intent.ACTION_HEADSET_PLUG
未正确移除SD卡但已取出来时(正确移除方法:设置–SD卡和设备内存–卸载SD卡)Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部储存装置(如SD卡)Intent.ACTION_MEDIA_CHECKING
成功安装APKIntent.ACTION_PACKAGE_ADDED
成功删除APKIntent.ACTION_PACKAGE_REMOVED
重启设备Intent.ACTION_REBOOT
屏幕被关闭Intent.ACTION_SCREEN_OFF
屏幕被打开Intent.ACTION_SCREEN_ON
关闭系统时Intent.ACTION_SHUTDOWN
重启设备Intent.ACTION_REBOOT

4、App应用内广播或本地广播(LocalBroadcast)

      Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下

  • 1、其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;
  • 2、其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。

      无论哪种情形,这些安全隐患都确实是存在的。由此,最常见的增加安全性的方案

  • 1、对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;
  • 2、在广播发送和接收时,都增加上相应的permission,用于权限验证;
  • 3、发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

注意事项:

  • 对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册,不能静态注册
  • 若在广播中启动Activity,则需要为intent加入FLAG_ACTIVITY_NEW_STACK标记,否则会报错(需要一个栈来存放一个新打开的activity)
  • 若广播中弹出AlertDialog,需要设置对话类型为TYPE_SYSTEM_ALTER,否则对话框无法弹出

BroadcastReceiver的注册

静态注册

application标签中注册

<receiver android:name=".MyReceived">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
</receiver>

android 6.0前静态申请权限,6.0后需动态申请权限

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

动态注册

		myReceived = new MyReceived();
        IntentFilter intentFilter = new IntentFilter();

        //接收网络状态发生变化的广播
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        //动态注册广播
        registerReceiver(myReceived,intentFilter);

        ...
  	protected void onDestroy() {
        super.onDestroy();
 //      一定要取消广播注册        
//        unregisterReceiver(myReceived);
    }

动态注册广播的缺点:需要程序启动才可以接收广播

实例

发送广播的简单例子

<receiver android:name=".MyReceived">
            <intent-filter>
                <action android:name="com.demo.MY_BROADCAST" />
            </intent-filter>
</receiver>
package com.demo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceived extends BroadcastReceiver {

    private final String ACTION_BOOT = "com.demo.MY_BROADCAST";
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"收到广播啦~",Toast.LENGTH_SHORT).show();
    }
}
Button send = findViewById(R.id.send);
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendBroadcast(new Intent("com.demo.MY_BROADCAST"));
            }
        });

LocalBroadcast的例子

  //创建LocalBroadcastManager(局部通知管理器)对象
        final LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

        Button send = findViewById(R.id.send);
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //发送广播
                localBroadcastManager.sendBroadcast(new Intent("com.LocalBroadcastManager"));
            }
        });

        //动态注册本地广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.LocalBroadcastManager");
        myReceived = new MyReceived();
        localBroadcastManager.registerReceiver(myReceived,intentFilter);

使用广播的注意事项

      不要在广播里添加过多逻辑或者进行任何耗时操作,因为在广播中是不允许开辟线程的, 当onReceiver( )方法运行较长时间(超过10秒)还没有结束的话,那么程序会报错(ANR), 广播更多的时候扮演的是一个打开其他组件的角色,比如启动Service,Notification提示, Activity等!

本文参考于https://www.jianshu.com/p/fc431cb981cd

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值