越不懂的越爱装
大家都同等:IT世界没有难不难,只有是否了解过
挑战目录
什么是安卓中的广播
是安卓程序之间或单个程序内部传递消息的机制之一。
按发送者(广播来源)分为系统广播和自定义广播。
按注册方式分为静态注册广播和动态注册广播。
按功能分为系统广播、默认广播、有序广播、粘性广播(废弃)、App应用内广播。
系统广播和自定义广播
-
系统广播
发送者为系统自己发送,注册和接收的实现和自定义广播一致。
-
为什么要使用自定义广播而不是自己实现广播模式
静态注册和动态注册广播
-
静态注册
常驻,不受任何组件的生命周期影响适用于需要时刻监听的广播
在xml文件中生命注册
耗电,占内存
-
定义广播
class 静态广播注册():BroadcastReceiver() { override fun onReceive(p0: Context?, p1: Intent?) { Toast.makeText(p0,"广播接收", Toast.LENGTH_SHORT).show() } }
-
注册广播
<?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>
-
发送广播
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应用内广播
-
系统广播
-
默认广播
- 特点:
- 所有的接受者之间是异步的
- 接收者相互之间不会有影响
- 接收者无法阻止其他接收者接收
- 优先级、setResultExtras(Bundle())、abortBroadcast等有序广播API的设置无效
- 特点:
-
有序广播
-
特点:
- 通过sendOrderedBroadcast(intent,null)发送,第二个参数为权限,传null表示不需要任何权限
- 根据优先级(-1000到1000)从大到小接收广播
- 同优先级动态注册的先接收
- 同优先级先注册的先接收
- 通过xml的intent-filter的priority或者intentFilter.priority=xx指定优先级
- 在接收方法onReceive里可以使用setResultExtras(Bundle())设置下一个接收者的接收到的数据
- 在接收方法onReceive里可以使用abortBroadcast终止广播
- 在接收方法onReceive里可以使用resultData传递字符串数据
-
有序广播sendOrderedBroadcast(intent,null)的权限参数:?
-
-
粘性广播(废弃)
-
App应用内广播
- 特点:
- 广播不会发送
- 关于,发送本地广播
- 将上面实现广播的代码的注册、取消注册、发送中的context参数改为 LocalBroadcastManager.getInstance(this)
- 关于,接收时防止恶意接收到特殊构造的广播攻击:
- 将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中注册无效的广播
- 屏幕的开、关广播
- 电量的变化广播
- 等等
- 有序广播的接收者必须配置优先级,防止接收顺序错乱
- 只能通过动态注册的方式,实现有序广播。
安卓广播源码实现
-
静态广播注册原理
-
在系统启动的时候通过PackageManagerService扫描已安装应用进行注册。具体扫描代码如下:
-
网友评论