Android四大组件——BroadcastReceiver

概念

用来互相通信(传递信息)的一种机制

  • 应用内通信
  • 进程通信

扩展1 Intent

Intent详解http://www.cnblogs.com/smyhvae/p/3959204.html

Intent的相关属性:

  • Intent由以下各个组成部分:
  • component(组件):目的组件
  • action(动作):用来表现意图的行动
  • category(类别):用来表现动作的类别
  • data(数据):表示与动作要操纵的数据
  • type(数据类型):对于data范例的描写
  • extras(扩展信息):扩展信息
  • Flags(标志位):期望这个意图的运行模式

Intent类型分为显式Intent(直接类型)、隐式Intent(间接类型)。官方建议使用隐式Intent。上述属性中,component属性为直接类型,其他均为间接类型。

扩展2 exported

android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。

总体来说它的主要作用是:是否支持其它应用调用当前组件。

默认值:如果包含有intent-filter 默认值为true; 没有intent-filter默认值为false。

即置为true表示可以被其他组件来调用。

扩展3 Bundle

Bundle在Android开发中非常常见,它的作用主要时用于传递数据。Bundle传递的数据包括:string、int、boolean、byte、float、long、double等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serialiable或Parcelable接口。

Bundle所保存的数据是以key-value(键值对)的形式保存在ArrayMap中。

发送广播

发送者 ---------Intent------------ >BroadcastReceiver

Intent intent = new Intent();
intent.setAction(ACTION_UPLOAD_RESULT);
intent.putExtra(KEY_RESULT, filePath);
sendBroadcast(intent);

接收广播

用BroadcastReceiver类,继承该类或者直接new出来,在onReceive()方法里写接收之后的操作。

创建完还需要注册(静态在Manifest,动态用Context的registerReceiver()方法)这个接收器,配置这个Action,过滤广播信息。

一个应用场景:编辑消息,编辑完成之后,发送广播通知

广播分类

  • 静态广播,是在Manifest文件中注册的广播。
    • 常驻内存中,可在App未启动时就监听广播,如监听短信、系统时间等系统广播事件。
  • 动态广播,是在代码中注册以及解除注册的广播。
    • App启动后注册,然后才能监听。解除注册(一般是Activity销毁时)后广播也随之结束。

如果采用动态注册的方式,在onDestroy时要记得解除注册nregisterReceiver();

注意:两种广播同时注册的时候,动态广播优先于静态广播。

静态广播的注册与使用

静态广播最常用的场景,接收来自系统的广播:开机完成,电量低,设置时间,检测到插入U盘等。

 

 安卓8.0以上禁止在后台执行,无法接受静态注册的隐式广播。需要明确指明目的地。

动态广播注册与使用

 不要忘记解除注册

代码实践1

静态广播

第一步创建接收器类,

public class MyBroadCast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ToastUtil.longToast(context, "静态接收,接收到广播了!");
    }
}

第二步,在Manifest里注册,还要设置过滤器来过滤action

 <receiver android:name=".MyBroadCast"
            android:exported="true">
            <intent-filter>
                <action android:name="test2"/>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
</receiver>

第三步,发送广播,显式的方式,需要指明packageName与携带的action

findViewById(R.id.btn_test2).setOnClickListener(v -> sendBroadcast(new Intent()
                .setAction("test2").setPackage(getPackageName())));

或者,设置可后台执行的flags标志位,0x01000000(可用但不推荐,还是写包名)

动态广播

第一步还是创建接收器类(同上),或者new出来:

private MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
            ToastUtil.longToast(getApplicationContext(), "接收到动态广播");
        }
    };

第二步,注册广播接收器,注意写Intentfilter的action。

IntentFilter filter = new IntentFilter();
filter.addAction("dongtai.test");
registerReceiver(myBroadcastReceiver, filter);

第三步,发送广播

sendBroadcast(new Intent("dongtai.test"));

别忘了在onDestroy()里解除注册。

无序广播与有序广播

按接收的顺序来区分,有无序广播和有序广播

 无序广播,接收器接收顺序大致相同,随机。

有序广播则按照123的顺序依次进行接收(优先级递减)

 

代码实践2

无序广播

 使用流程:

先新建三个接收器:

public class Receiver1 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        LogUtil.printLog("接收到广播1");
    }
}

再采用静态方法在manifest里注册这三个广播接收器

 <receiver
            android:name=".receiver.Receiver1"
            android:exported="true">
            <intent-filter>
                <action android:name="wuxutesst" />
            </intent-filter>
</receiver>

发送广播

findViewById(R.id.btn_test3).setOnClickListener(v -> sendBroadcast(new Intent()
                .setAction("wuxutesst").setPackage(getPackageName())));

有序广播

下面是静态和动态两种方法来设置优先级,使接收器成为有序广播接收器。

使用流程:

在注册的时候,将三者优先级设置为90,100,80,期望顺序为213。

还要注意,在发送广播的地方,要使用sendOrderedBroadcast(intent, permission),第一个参数还是intent,第二个参数是接收器想要接收广播所具备的permission。

findViewById(R.id.btn_test3).setOnClickListener(v -> 
sendOrderedBroadcast(new Intent().setAction("wuxutesst").setPackage(getPackageName()), null));

有序广播还能设置截断方法abortBroadcast(),刚刚已经将Receiver2的优先级设置为最高的,现在在其中写一行:


public class Receiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        LogUtil.printLog("接收到广播2");
        LogUtil.printLog("截断广播");
        abortBroadcast();
    }
}

当广播传到这个接收器时,被截断,后面的接收器就接收不到了。(无序广播没有这个方法)

有序广播除了阻断广播的方法,还有setResultExtras()方法,可以利用Bundle向优先级比它低的下游接收器传递信息。

 用法:传递的时候,可以是上游接收器传下来的Bundle对象,也可以是new一个Bundle出来,设置完成后,继续传递到下游。

 实操:

上面是在最上游,即Activity发送广播的时候,设置Bundle与Intent,以防空指针错误。

然后传到接收器2号的时候,再用setResultExtras()来追加信息(intent原有信息未抹除)。

if (intent != null) {
            Bundle dataBundle = intent.getExtras();
            dataBundle.putString("name", "广播接收器2号");
            setResultExtras(dataBundle);
        }

再下游的是接收器1号,在其中获取intent信息和上游传来的Bundle信息。

 if (intent != null) {
            Bundle dataBundle = intent.getExtras();
            String data = dataBundle.getString("name");
            LogUtil.printLog("intent传来的是:" + data);
        }

Bundle newBundle = getResultExtras(true);
LogUtil.printLog("上一个接收器是:"+newBundle.getString("name"));

getResultExtras()方法里面填true,指即使上游没有传Bundle过来,在这里也会新建一个ArrayMap来存数据,防止NullPointer。

最后的结果如下图:

 还可以用setResultData()方法,来直接传递字符串。

本地广播与全局广播

按照传播范围来划分。

本地广播:只在这个app内部进行传播,数据安全。

全局广播:在在整个手机所有app之间进行传播,可能有安全问题。

注意普通的广播默认是全局广播

本地广播的使用

接收器与全局广播没有区别。

在注册的时候,只能采用动态注册的方式,即app启动后再准备接收。

还要用到一个类:LocalBroadcastManager(已经废弃,仅作了解)

 解除注册:用这个manager实例来调用unregisterReceiver() 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值