日更挑战-安卓广播接收者


越不懂的越爱装
大家都同等:IT世界没有难不难,只有是否了解过

挑战目录

什么是安卓中的广播

是安卓程序之间或单个程序内部传递消息的机制之一。
按发送者(广播来源)分为系统广播和自定义广播。
按注册方式分为静态注册广播和动态注册广播。
按功能分为系统广播、默认广播、有序广播、粘性广播(废弃)、App应用内广播。


系统广播和自定义广播

  • 系统广播

    发送者为系统自己发送,注册和接收的实现和自定义广播一致。

  • 为什么要使用自定义广播而不是自己实现广播模式


静态注册和动态注册广播

  • 静态注册
    常驻,不受任何组件的生命周期影响

    适用于需要时刻监听的广播

    在xml文件中生命注册

    耗电,占内存

    1. 定义广播

      class 静态广播注册():BroadcastReceiver() {
      
          override fun onReceive(p0: Context?, p1: Intent?) {
              Toast.makeText(p0,"广播接收", Toast.LENGTH_SHORT).show()
          }
      }
      
    2. 注册广播

      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android">
          <application>
              <receiver android:name=".静态广播注册"
                  android:enabled="true"  <!--  -->
                  android:exported="true" <!-- 是否接收其他应用的广播 -->
                  android:permission="mypermission" <!-- 具有相应权限的发送者,才能往这个接收者发送广播 -->
                  >  
                  <intent-filter>
                      <action android:name="MyTest"/>  <!-- action -->
                  </intent-filter>
              </receiver>
          </application>
      </manifest>
      
    3. 发送广播

      class MainActivity : AppCompatActivity() {
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
          }
      
          fun sendBroadcastReceiver(view: View) {
              tv_sendBroadcastReceiver.setOnClickListener {
                  val intent = Intent()
                  intent.action = "MyTest"
                  intent.putExtra("参数","参数值")
                  sendBroadcast(intent)
              }
          }
      }
      
  • 动态注册
    非常驻广播
    在代码中动态声明
    跟随组件生命周期变化
    适用于需要特定时刻监听的广播

    class MainActivity : AppCompatActivity() {
    
        private lateinit var receiver:TestReceiver
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val intentFilter = IntentFilter()
            intentFilter.addAction("test")
            receiver = TestReceiver()
            //动态注册广播
            registerReceiver(receiver,intentFilter)
        }
    
          //xml布局中的点击事件,发送广播
        fun sendBroadcastReceiver(view: View) {
            tv_sendBroadcastReceiver.setOnClickListener {
                val intent = Intent()
                intent.action = "test"
                intent.putExtra("参数","参数值")
                sendBroadcast(intent)
            }
        }
    
          //及时注销广播,防止内存泄露
        override fun onPause() {
            super.onPause()
            unregisterReceiver(receiver) //及时注销广播,防止内存泄露
        }
    
        class TestReceiver : BroadcastReceiver() {
            override fun onReceive(p0: Context?, p1: Intent?) {
                Toast.makeText(p0,"广播接收",Toast.LENGTH_SHORT).show()
              }
          }
      }
    
    • 动态注册在何时注销比较好
      尽量在onResume注册,在onPause注销。

      因为onPause是App死亡前肯定会执行的方法。但是当系统内存不足时,App在执行完onPause后就会被销毁,来不及执行onStop、onDestory方法。


系统广播、默认广播、有序广播、粘性广播(废弃)、App应用内广播

  • 系统广播

  • 默认广播

    1. 特点:
      • 所有的接受者之间是异步的
      • 接收者相互之间不会有影响
      • 接收者无法阻止其他接收者接收
      • 优先级、setResultExtras(Bundle())、abortBroadcast等有序广播API的设置无效
  • 有序广播

    1. 特点:

      • 通过sendOrderedBroadcast(intent,null)发送,第二个参数为权限,传null表示不需要任何权限
      • 根据优先级(-1000到1000)从大到小接收广播
      • 同优先级动态注册的先接收
      • 同优先级先注册的先接收
      • 通过xml的intent-filter的priority或者intentFilter.priority=xx指定优先级
      • 在接收方法onReceive里可以使用setResultExtras(Bundle())设置下一个接收者的接收到的数据
      • 在接收方法onReceive里可以使用abortBroadcast终止广播
      • 在接收方法onReceive里可以使用resultData传递字符串数据
    2. 有序广播sendOrderedBroadcast(intent,null)的权限参数:?

  • 粘性广播(废弃)

  • App应用内广播

    1. 特点:
      • 广播不会发送
    2. 关于,发送本地广播
      • 将上面实现广播的代码的注册、取消注册、发送中的context参数改为 LocalBroadcastManager.getInstance(this)
    3. 关于,接收时防止恶意接收到特殊构造的广播攻击:
      • 将exported设置为false,使得只接收本应用广播
      • 发送和接收时,增加权限字段,也可防止
      • 发送广播时通过intent.setPackage(receiverPackageName)指定广播接收器对应的包名

onReceive(p0: Context?, p1: Intent?)方法中的Context

  • 本地广播+动态注册:Activity Context
  • 本地广播+静态注册:Application Context
  • 非本地广播+动态注册:Activity Context
  • 非本地广播+静态注册:ReceiverRestricted Context

onReceive(p0: Context?, p1: Intent?)方法中的Intent


安卓8.0后广播的改动

  • 在AndroidManifest.xml中注册无效的广播
    1. 屏幕的开、关广播
    2. 电量的变化广播
    3. 等等
  • 有序广播的接收者必须配置优先级,防止接收顺序错乱
  • 只能通过动态注册的方式,实现有序广播。

安卓广播源码实现

  • 静态广播注册原理

    1. 在系统启动的时候通过PackageManagerService扫描已安装应用进行注册。具体扫描代码如下:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android的广播机制方便了开发者接收系统及其他APP发送的广播(开机,电池电量改变等,那么如何自定义一个广播呢...
    小贱嘎嘎阅读 631评论 0 0
  • 现实中的广播:电台为了传达一些消息而发送广播,通过广播携带要传达的消息,群众只要买一个收音机,就可以收到广播了。 ...
    stevewang阅读 4,397评论 0 8
  • 广播接收者(BroadcastReceiver) 1.定义广播接受者 静态注册广播 定义类继承BroadcastR...
    ProZoom阅读 2,447评论 2 4
  • BroadcastReceiver作为Android四大组件之一,在Android日常开发中有着不可或缺的作用,主...
    陕E_沙僧阅读 1,800评论 0 1
  • 定义: 是一个全局监听器,属于Android四大组件之一 广播分为两个角色:广播发送者,广播接收者 广播接收器分为...
    LiuZhanYue阅读 660评论 0 0

友情链接更多精彩内容