Android Zero Base to Proficient Broadcast Mechanism

  • 2021-12-21 04:54:39
  • OfStack

Directory Broadcast Mechanism Introduction Receiving System Broadcast 1. Dynamic Registration Monitoring Time Change 2. Static Registration Realization Start-up Start-up Send Custom Broadcast 1. Send Standard Broadcast 2. Send Ordered Broadcast

Brief introduction of broadcasting mechanism

There are two main types of broadcasting in Android:

Standard broadcast: A broadcast performed asynchronously. After the broadcast is sent, all BroadcasterReceiver will receive the broadcast message at almost the same time, without any time sequence Ordered broadcast: A synchronous broadcast in which only one BroadcasterReceiver can receive the broadcast message at the same time after the broadcast is sent, and the broadcast will continue only after the logic in the BroadcasterReceiver is executed

Receive system broadcast

Android has many built-in system-level broadcasts, which we can listen to in the application to get the status information of various systems

1. Dynamic registration monitoring time changes

Create a new class, inherit from BroadcasterReceiver, and override the parent's onReceive () method so that the onReceive () method is executed when a broadcast comes


class MainActivity : AppCompatActivity() {

    lateinit var timeChangeReceiver: TimeChangeReceiver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intentFilter = IntentFilter()
        intentFilter.addAction("android.intent.action.TIME_TICK")
        timeChangeReceiver = TimeChangeReceiver()
        registerReceiver(timeChangeReceiver, intentFilter)
    }

    inner class TimeChangeReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context?, intent: Intent?) {
            Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
        }
    }
}
Defines an inner class TimeChangeReceiver, inherits from BroadcasterReceiver and overrides the method of the parent class, so that whenever the system time changes, Toast will be used to prompt a text message Create an instance of IntentFilter in the onCreate () method and add action with the value of android. intent. action. TIME_TICK, which is also the value of the broadcast that the system will emit when the system time changes The TimeChangeReceiver instance is created, then the registerReceiver () method is called to register, and the IntentFilter instance and TimeChangeReceiver instance are passed in to complete the monitoring function

2. Static registration to realize startup

Dynamic registration of BroadcasterReceiver is relatively flexible, but it must be started after the program can receive broadcast, if you want to let the program in the case of not started to receive broadcast, you need to use static registration

Create class BootCompleteReceiver, Exported attribute indicates whether to allow this BroadcasterReceiver to receive broadcasts other than this program, Enabled attribute indicates whether to enable this BroadcasterReceiver, check these two attributes, and click Finish to complete the creation


class BootCompleteReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show()
    }
}

Static BroadcasterReceiver must be registered in the AndroidManifest. xml file before it can be used. Since the Android system will send out a broadcast with the value of android.intent.action.BOOT_COMPLETED after startup, we are < receiver > Tag to add 1 < intent-filter > Tag and declare the corresponding action in it. In addition, permission declaration must be made in AndroidManifest. xml.


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragmenttest">
    
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FragmentTest">
        
        ...
        
        <receiver
            android:name="com.example.broadcasttest.BootCompleteReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

Send a custom broadcast

1. Send standard broadcasts

Create a new MyBroadcasterReceiver and add the following code to the onReceive () method:


class MyBroadcasterReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "received in MyBroadcasterReceiver", Toast.LENGTH_SHORT).show()
    }
}

Then modify this BroadcasterReceiver in AndroidManifest. xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragmenttest">

	...
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FragmentTest">
        
        ...
        
        <receiver
            android:name="com.example.broadcasttest.MyBroadcasterReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.broadcasttest.MyBroadcasterReceiver" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

Next, modify activity_main. xml to define a button as the trigger point for sending broadcasts


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Broadcast" />

</LinearLayout>

Modify the code in MainActivity


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.setOnClickListener {
            val intent = Intent("com.example.broadcasttest.MyBroadcasterReceiver")
            intent.setPackage(packageName)
            sendBroadcast(intent)
        }
    }
}

Here for setPackage () method to do a description, statically registered BroadcasterReceiver is not able to receive implicit broadcast, and by default we send out the custom broadcast is implicit broadcast, so here to call setPackage () method, specify which application this broadcast is sent to, so that it becomes an explicit broadcast

2. Send ordered broadcasts

Ordered broadcast is a synchronous broadcast and can be truncated. We will create a new AnotherBroadcasterReceiver


class AnotherBroadcasterReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "received in AnotherBroadcasterReceiver", Toast.LENGTH_SHORT).show()
    }
}

Then modify it in AndroidManifest. xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragmenttest">

   ...

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FragmentTest">
        
		...

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

    </application>

</manifest>

So far, the program is sending out standard broadcasts. To send orderly broadcasts, you have to go back to the BroadcasterTest project and modify the code in MainActivity


class MainActivity : AppCompatActivity() {
    
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.setOnClickListener {
            val intent = Intent("com.example.broadcasttest.MyBroadcasterReceiver")
            intent.setPackage(packageName)
            sendOrderedBroadcast(intent, null)
        }
        ...
    }
}

The sendOrderedBroadcast () method takes two parameters: the first parameter is still Intent; The second parameter is a string related to permission, where you can pass in null

Next, set the sequence of BroadcasterReceiver and modify the code in AndroidManifest. xml


class BootCompleteReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show()
    }
}
0

Give priority to BroadcasterReceiver through android: priority attribute, and BroadcasterReceiver with higher priority can receive broadcast first. Now that ES 148EN gets the priority to receive the broadcast, ES 149EN can choose whether to allow the broadcast to continue


class BootCompleteReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show()
    }
}
1

Calling the abortBroadcaster () method in the onReceive () method means that the broadcast is truncated and subsequent BroadcasterReceiver can no longer receive the broadcast


Related articles: