十一、Android-四大组件之Broadcast

97 阅读1分钟

11. 广播

11.1 广播机制

  • 标准广播-normal broadcasts

是一种完全异步执行的广播,在广播发出后,所有的BroadcastReceiver几乎在同一时刻收到这条广播消息,没有先后顺序。效率高,无法被截断。

  • 有序广播-ordered broadcasts

是一种同步执行广播,在广播发出后,同一时刻只会有一个BroadcastReceiver能够接受到这条广播,当这个BroadcastReceiver中逻辑执行完后,广播才会继续传递。所以是有先后顺序的,优先级高先收到广播消息,并且前面的BroadcastReceiver能够截断正在传递的广播。

BroadcastReceiver中是不允许开启线程的。当onReceive()方法运行较长时间没有结束时,程序会出现错误。

11.2 注册广播的两种方式

  • 静态注册:AndroidManifest.xml中的receiver注册intent-filteraction
        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
            </intent-filter>
        </receiver>

常驻广播,应用程序关闭后,如果有注册的广播来,程序也会被系统调用自动运行。

  • 动态注册:代码中调用registerReceiver(),记得适时销毁
        val intentFilterMyBroadcast = IntentFilter()
        intentFilterMyBroadcast.addAction("$packageName.MY_BROADCAST")
        myBroadcastReceiver = MyBroadcastReceiver()
        registerReceiver(myBroadcastReceiver, intentFilter)

不是常驻广播,广播跟随程序的声明周期。

11.3 接收系统广播

class MainActivity : AppCompatActivity() {
​
    private lateinit var binding: ActivityMainBinding
    lateinit var timeChangeReceiver: TimeChangeReceiver
​
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
​
        val intentFilter = IntentFilter()
        intentFilter.addAction("android.intent.action.TIME_TICK")
        timeChangeReceiver = TimeChangeReceiver()
        registerReceiver(timeChangeReceiver, intentFilter)
    }
​
    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(timeChangeReceiver)
    }
}
​
class TimeChangeReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
    }
}

当系统时间发生变化时,每隔一分钟,系统会发送一条android.intent.action.TIME_TICK的广播。

收到广播,触发onReceive中的代码。

11.4 发送自定义广播

新建自定义广播

新建广播时:

  • Exported:是否允许这个BroadcastReceiver接收本程序以外的广播
  • Enabled:是否启用这个BroadcastReceiver
class MyBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast
        val p = intent.`package`
        val data = intent.getStringExtra("key1")
        Log.d("MyBroadcastReceiver", "p: $p; data: $data")
        Toast.makeText(context, "received in MyBroadcastReceiver", android.widget.Toast.LENGTH_SHORT).show()
    }
}

AndroidManifest.xml中的receiver注册intent-filteraction

action android:name 类似于Swift的Notification.Name

        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
            </intent-filter>
        </receiver>

Activity中发送广播

        binding.button1.setOnClickListener {
            val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
            intent.setPackage(packageName)
            intent.putExtra("key1", "value1")
            sendBroadcast(intent)
        }

11.5 发送有序广播

新建一个AnotherBroadcastReceiver广播

class AnotherBroadcastReceiver : BroadcastReceiver() {
​
    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
        Toast.makeText(context, "received in AnotherBroadcastReceiver", android.widget.Toast.LENGTH_SHORT).show()
    }
}

Activity中发送sendOrderedBroadcast

        binding.button1.setOnClickListener {
            val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
            intent.setPackage(packageName)
            intent.putExtra("key1", "value1")
            sendOrderedBroadcast(intent, null)
        }

设置优先级android:priority,谁高谁先接收到

        <receiver
            android:name=".AnotherBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="0">
                <action android:name="com.example.broadcasttest.MY_BROADCAST" />
            </intent-filter>
        </receiver>
        <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>

可以中止广播传递 abortBroadcast()

class MyBroadcastReceiver : BroadcastReceiver() {
​
    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast
        val p = intent.`package`
        val data = intent.getStringExtra("key1")
        Log.d("MyBroadcastReceiver", "p: $p; data: $data")
        Toast.makeText(context, "received in MyBroadcastReceiver", android.widget.Toast.LENGTH_SHORT).show()
        abortBroadcast()
    }
}