Android从入门到放弃——四大组件之广播 BroadcastReceiver

今天来认识一下Android4大组件中应该是最简单的一个组件:广播BroadcastReceiver

它的作用就跟名字一样,就是一个广播,把要通知的消息告诉所有正在关注、接收这类消息的接收者。

所以这里至少有2方:发送消息的一方和接收消息的一方。发送方不知道要发给谁,只管把这条消息发出去,具体谁接收呢?谁关注谁接收。所以发送的消息需要一个标识,标识这一条是什么消息。

发送方:发送一条带标识的消息

接收方:先注册消息监听,只监听自己感兴趣的消息

上面说到接收方要监听消息,就需要先注册,Android支持2种注册方式:静态注册和动态注册。

静态注册:在Manifest中注册。

优点:可以不用启动apk就能监听到。可以设置优先级

缺点:缺乏灵活性

动态注册:在代码中注册

优点:灵活性高,可以动态的添加。并且在需要的地方注册监听。

缺点:必须启动apk而且启动相关界面。

下面先来看看静态注册:

        <receiver
            android:name=".MyReceiver1"
            android:enabled="true">
            <intent-filter>
                <action android:name="MyReceiverTest" />
            </intent-filter>
        </receiver>

receiver表示声明一个广播,android:name=’’是声明广播的类。enable表示是否开启。Intent-filter标签表示我们需要关心的广播消息是什么;下面的action中的内容就是上面提到的消息标识。表示当前这个广播接收器只接收action为MyReceiverTest的消息。这里的action可以有很多条,表示这些消息我们都关注。

下面看看广播接收器的MyReceiver1的内容

class MyReceiver1 : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Toast.makeText(context, "onReceive: ${intent!!.action}", Toast.LENGTH_SHORT).show()
    }
}

声明一个广播接收器很简单,只需要继承BroadcastReceiver就可以了。然后重写onReceiver方法,当这个方法被调用的时候就表示我们关注的广播有消息来了。

加入我们监听了多条消息,怎么区分呢? 注意第二个参数intent,这里就有带action。我们只要对它做判断就可以了。

下面看看发送消息的地方:

    private val BROAD_ACTION = "MyReceiverTest"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        acMainBtSend.setOnClickListener {
            val intent = Intent(BROAD_ACTION)
            intent.setPackage(packageName)
            sendBroadcast(intent)
        }
    }

布局很简单,就是一个按钮,这里按钮点击发送一条消息。

发送消息也非常简单,只需要调用context的sendBroadcast即可。参数是Intent,Intent有一个构造方法,接收一个String作为action。

注意intent.setPackage(packageName)这一行,在Android8.0以后的手机版本必须添加这一行,不然是收不到消息的。我想Google的这个设置也是为了能监听到广播的来源,不然整个系统里面各种广播满天飞也不好管理。

这样一条消息就发送出去了。大家可以看到这里发送的一方是不需要指定接收者的,那就意味着只要在系统里注册MyReceiverTest这条消息的接收者就都可以收到这条消息。

下面来看看运行的效果

接下来看看动态注册

广播接收器不用改动,主要是在启动apk后要在代码中注册

    private val BROAD_ACTION = "MyReceiverTest"

    private val myReceiver = MyReceiver1()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //注册广播
        val intentFilter = IntentFilter(BROAD_ACTION)
        registerReceiver(myReceiver, intentFilter)

        acMainBtSend.setOnClickListener {
            val intent = Intent(BROAD_ACTION)
            intent.setPackage(packageName)
            sendBroadcast(intent)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        //退出的时候必须注销
        unregisterReceiver(myReceiver)
    }

注册的时候先创建一个IntentFilter,并且设置action,可以使用intentFilter.addAction来继续添加action。然后调用registerReceiver来注册。注意,注册和注销必须成对出现,我们这里在onDestroy的时候调用了unregisterReceiver来注销。这样就不会再接收到广播了。

效果跟之前的是一样的就不截图了。

之前的广播都是标准的广播用法,Android还提供了一种有序广播,及接收者是有顺序的,并且还可以在中途截断不再继续向后传递。

这类有序广播必须使用静态注册的方式,只需要增加一个参数来表示自己的优先级即可。

为了验证我这里创建了3个广播接收器

        <receiver
            android:name=".MyReceiver1"
            android:enabled="true">
            <intent-filter android:priority="100">
                <action android:name="MyReceiverTest" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiver2"
            android:enabled="true">
            <intent-filter android:priority="200">
                <action android:name="MyReceiverTest" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiver3"
            android:enabled="true"
            android:permission="test">
            <intent-filter android:priority="500">
                <action android:name="MyReceiverTest" />
            </intent-filter>
        </receiver>

注意看每个广播的intent-filter里面都增加了一个android:priority属性,其值越大表示优先级越高。

我们在每个广播里面都只是做一个打印,不做任何操作。

修改发送广播,改为发送顺序广播:

val intent = Intent(BROAD_ACTION)
intent.setPackage(packageName)
sendOrderedBroadcast(intent,null)

运行看结果:

可以看到接收的顺序跟我们设置的优先级一样。

那么怎么截断呢?很简单,只需要在接收器里面调用abortBroadcast()就可以了。

我们在MyReceiver2中调用这个方法

class MyReceiver2 : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Log.d("ZLog MyReceiver2", "onReceive: ${intent!!.action}")
        abortBroadcast()
    }
}

发送的方法不用改变

看看运行效果:

可以看到MyReceiver1并没有接收到消息。

到这里怎么发送广播就差不多这些了。其实广播不只是简单的发送一条消息,还可以携带数据的。大家注意我们发送广播的参数和接收到广播的回调参数都是intent,看过我的Activity详解2应该知道,intent是可以带数据的。通过它我们可以实现线程、进程之间的通讯和传递数据。后面我们会讲到Android的进程间通讯,广播就是其中一种方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值