Android 中的每个应用程序都可以对自己 感兴趣的广播进行注册,这样该程序就只会收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的。Android 提供了一套完整的API,允许应用程序自由地发送和接收广播。
广播类型
Android 中的广播主要可以分为两种类型:标准广播和有序广播。
- 标准广播(normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver 几乎会在同一时刻收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
- 有序广播(ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个BroadcastReceiver 能够收到这条广播消息,当这个BroadcastReceiver 中的逻辑执行完毕后,广播才会继续传递。所以此时的BroadcastReceiver 是有先后顺序的, 优先级高的BroadcastReceiver 就可以先收到广播消息,并且前面的BroadcastReceiver 还可以截断正在传递的广播,这样后面的BroadcastReceiver 就无法收到广播消息了。
接收系统广播
注册BroadcastReceiver 的方式一般有两种:在代码中注册和在AndroidManifest.xml 中注册。其中前者也被称为动态注册,后者也被称为静态注册。
动态注册
新建一个类,让它继承自 BroadcastReceiver ,并重写父类的onReceive()方法就行了。这样当有广播到来时, onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。
class MainActivity : AppCompatActivity() { lateinit var timeChangeReceiver: TimeChangeReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val intentFilter = IntentFilter() // 当系统时间发生变化时,系统发出的正是一条值为android.intent.action.TIME_TICK的广播 intentFilter.addAction("android.intent.action.TIME_TICK") timeChangeReceiver = TimeChangeReceiver() // 后调用registerReceiver()方法进行注册 registerReceiver(timeChangeReceiver, intentFilter) } override fun onDestroy() { super.onDestroy() // 动态注册的BroadcastReceiver一定要取消注册才行 unregisterReceiver(timeChangeReceiver) } // 定义了一个内部类TimeChangeReceiver,这个类是继承自BroadcastReceiver的,并重写了父类的onReceive()方法。 inner class TimeChangeReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show() Log.i("MainActivity", "Time has changed" + Toast.LENGTH_SHORT.toString()) } } }
Android 系统还会在亮屏熄屏、电量变化、网络变化等场景下发出广播。如果你想查看完整的系统广播列表,可以到如下的路径中去查看:
<Android SDK>/platforms/<任意android api版本>/data/broadcast_actions.txt
静态注册
其实从理论上来说,动态注册能监听到的系统广播,静态注册也应该能监听到,在过去的 Android 系统中确实是这样的。但是由于大量恶意的应用程序利用这个机制在程序未启动的情况 下监听系统广播,从而使任何应用都可以频繁地从后台被唤醒,严重影响了用户手机的电量和性能,因此Android 系统几乎每个版本都在削减静态注册BroadcastReceiver 的功能。
在Android 8.0 系统之后,所有隐式广播都不允许使用静态注册的方式来接收了。隐式广播指的 是那些没有具体指定发送给哪个应用程序的广播,大多数系统广播属于隐式广播,但是少数特 殊的系统广播目前仍然允许使用静态注册的方式来接收。这些特殊的系统广播列表详见 https://developer.android.google.cn/guide/components/broadcastexceptions.html 。
class BootCompleteReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show() Log.i("BootCompleteReceiver", "Boot Complete") } }
AndroidManifest.xml 文件进行修改
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
发送自定义广播
广播主要分为两种类型:标准广播和有序广播。
发送标准广播
在发送广播之前,我们还是需要先定义一个BroadcastR eceiver 来准备接收此广播
class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show() Log.i("MyBroadcastReceiver", "received in MyBroadcastReceiver") } }
然后在AndroidManifest.xml 中对这个BroadcastReceiver 进行修改:
<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST" /> </intent-filter> </receiver>
接下来修改activity_main.xml 中的代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Broadcast" /> </LinearLayout>
然后修改MainActivity 中的代码
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Log.i("MainActivity", "onCreate") button.setOnClickListener { val intent = Intent("com.example.broadcasttest.MY_BROADCAST") intent.setPackage(packageName) sendBroadcast(intent) } } }
发送有序广播
和标准广播不同,有序广播是一种同步执行的广播,并且是可以被截断的。
新建AnotherBroadcastReceiver
class AnotherBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in AnotherBroadcastReceiver", Toast.LENGTH_SHORT).show() Log.i("AnotherBroadcastReceive", "received in AnotherBroadcastReceiver") } }
然后在AndroidManifest.xml 中对这个BroadcastReceiver 的配置进行修改
<receiver android:name=".AnotherBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST" /> </intent-filter> </receiver>
发送有序广播只需要改动一行代码,即将sendBroadcast()方法改成 sendOrderedBroadcast()方法。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Log.i("MainActivity", "onCreate") button.setOnClickListener { val intent = Intent("com.example.broadcasttest.MY_BROADCAST") intent.setPackage(packageName) sendOrderedBroadcast(intent, null) } } }
可以看到,AnotherBroadcastReceiver 同样接收的是 com.example.broadcasttest.MY_BROADCAST这条广播。现在重新运行程序,并点击“Send Broadcast” 按钮,就会分别弹出两次提示信息
android:priority优先级
如何设定BroadcastReceiver的先后顺序呢?当然是在注册的时候进行设定了,修改 AndroidManifest.xml 中的代码,如下所示:
<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="100"> <action android:name="com.example.broadcasttest.MY_BROADCAST" /> </intent-filter> </receiver>
通过android:priority属性给BroadcastReceiver 设置了优先级,优先级比较高的BroadcastReceiver 就可以先收到广播。这里将MyBroadcastReceiver 的优先级设成了100 ,以保证它一定会在AnotherBroadcastReceiver 之前收到广播。
abortBroadcast()广播截断
既然已经获得了接收广播的优先权,那么MyBroadcastReceiver 就可以选择是否允许广播继续传递了。修改MyBroadcastReceiver 中的代码,如下所示:
class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show() Log.i("MyBroadcastReceiver", "received in MyBroadcastReceiver") abortBroadcast() } }
如果在onReceive()方法中调用了abortBroadcast()方法,就表示将这条广播截断,后面 的BroadcastReceiver 将无法再接收到这条广播。
标签:Toast,MyBroadcastReceiver,广播,intent,注册,Android,BroadcastReceiver From: https://www.cnblogs.com/ooo0/p/17057623.html