1、Broadcast 广播
功能:可以跨进程的通信方式,用于应用间或应用内通信。
种类:
-
标准广播/无序广播:异步接收,不可取消。
Intent().also { it.setAction(Constants.Broadcast.NormalBroadcast) //设置包名,限定在该包名内广播 sendBroadcast(it) }
-
有序广播:同步接收,按照优先级(priority)从高到低接收广播,可取消。
Intent().also { it.setAction(Constants.Broadcast.OrderBroadcast) //sendOrderedBroadcast(it,null) //指定广播接收器 sendOrderedBroadcast(it,null,broadcastReceiver,null,0,null,null) }
-
本地广播:只在应用内传播。
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) } //注册本地广播接收器 localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter) //发送本地广播 Intent().also { it.setAction(Constants.Broadcast.LocalBroadcast) localBroadcastManager.sendBroadcast(it) }
-
粘性广播(Android5.0已被废弃)
2、BroadcastReceiver 广播接收器
功能:用于接收广播信息
注册方式:
-
静态注册,创建广播接收器后在Manifest清单中注册,程序未启动也能接收到广播
<receiver android:name=".UserPresentReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> </intent-filter> </receiver>
-
动态注册,创建广播接收器,需要启动程序后注册后才能接收到广播,调用
context.registerReceiver(broadcastReceiver, intentFilter)
进行注册,调用context.unregisterReceiver(broadcastReceiver)
注销广播接收器//动态注册广播接收器 class MainActivity : AppCompatActivity() { private val broadcastReceiver: BroadcastReceiver by lazy { UserPresentReceiver() } //广播接收器 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val intentFilter = IntentFilter().apply { //过滤器 addAction(Intent.ACTION_USER_PRESENT) //添加一个用户回到前台的活动 } registerReceiver(broadcastReceiver, intentFilter) //注册广播接收器 } override fun onDestroy() { super.onDestroy() unregisterReceiver(broadcastReceiver) //注销广播接收器 } }
//广播接收器 class UserPresentReceiver : BroadcastReceiver() { private val TAG = javaClass.simpleName override fun onReceive(context: Context, intent: Intent) { when (intent.action) { Intent.ACTION_USER_PRESENT -> "screen on,user present!".logd(TAG) } } }
3、广播实现机制
系统广播实现机制
-
实现广播接收器BroadcastReceiver,重写onReceiver()方法;
-
广播接收器通过Binder机制向AMS进行注册;
-
广播发送者通过Binder机制向AMS发送广播;
-
AMS查询符合条件(IntentFilter/Permission等)的BroasdcastReceiver,将广播发送到对应的BroadcastReceiver的消息队列中;
-
消息循环执行拿到此广播,回调BroadcastReceiver中的onReceiver()方法。
本地广播实现机制: 本地广播主要通过Handler进行发送,其实是通过Handler发送Message。
4、系统变更
Android8.0(API26)开始,大多数广播不能使用隐式接收器接收,即所有隐式广播不能使用使用静态注册的方式来接收。静态注册的广播接收器无法接收隐式广播,默认情况下我们发出的广播都是隐式的,需要通过intentFilter.setPackage(String)
指定目标程序,让它变成显式的广播,否则静态注册的广播接收器无法接收到这条广播。
5、对进程状态的影响:
当执行onReceiver()
时是前台进程,当进程只有一个静态广播接收器在运行且从onReceiver
返回,则变为后台进程。系统可能回收后台进程,同时回收该进程的派生线程。因此不要在广播接收器中直接启动长时间运行的后台线程,可以调用 goAsync()
或者使用 JobScheduler
从接收器调度 JobService
,这样系统就会知道该进程将继续活跃地工作。
//goAsync()的使用
class UserPresentReceiver : BroadcastReceiver() {
private val TAG = javaClass.simpleName
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
Intent.ACTION_USER_PRESENT -> {
"screen on,user present!".logd(TAG)
Task(goAsync() as PendingResult).execute()
}
}
}
private inner class Task(val pendingIntent: PendingResult) :
AsyncTask<String, Int, String>() {
override fun doInBackground(vararg p0: String?): String {
VUiKit.sleep(8000)
return "screen on,await!"
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
result?.logd(TAG)
pendingIntent.finish()
}
}
}