Android learning six – broadcast mechanism

Introduction to Broadcasting Mechanism

Android applications can register broadcasts they are interested in, so that they can receive the broadcast content they care about, either from the system or from the application. Android provides a complete set of apis that allow applications to receive and send broadcasts. BroadcasReceiver is needed to receive broadcasts

First of all, broadcasting is divided into standard broadcasting and orderly broadcasting

Standard broadcast: a broadcast executed completely asynchronously. After a broadcast is sent, all BroadCasReceivers receive the broadcast message almost simultaneously, all efficient, but not truncated.

Orderly broadcast: It feels like a queue. Only one BroadcasReceiver receives a broadcast message at a time, but after the logic of this BroadcasReceiver is executed, the next BroadcasReceiver receives it and passes it out in turn. BroadcasReceiver with a higher priority receives the message first and then sequentially. The ordered broadcast can be truncated. Once truncated, the message cannot be received.

Dynamic registration listens for time changes

Dynamic registration is registered in code. First we build a BroadcastTest project, define an inner class in ManActivity that extends BroadcasReceiver, and override the parent onReceive method so that it will be executed over time

package com.example.broadcastreceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast

class MainActivity : AppCompatActivity() {
    lateinit var timeChangerReceiver:TimeChangeRecevier
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Get IntentFilter instance
        val  intentFilter=IntentFilter()
        / / but time changes, the system will issue a value of "android. Intent. Action. TIME_TICK" broadcast
        // What broadcasts does the BroadcastReceiver want to listen on
        intentFilter.addAction("android.intent.action.TIME_TICK")
        timeChangerReceiver=TimeChangeRecevier()
        / / this method is to register, such ability can accept value for android. The intent. The action. The TIME_TICK broadcasting
        registerReceiver(timeChangerReceiver,intentFilter)


    }

    override fun onDestroy(a) {
        super.onDestroy()
        // Cancel registration here, otherwise it will cause memory overflow
        unregisterReceiver(timeChangerReceiver)
    }
    inner class TimeChangeRecevier:BroadcastReceiver() {override fun onReceive(context: Context? , intent:Intent?). {
            Toast.makeText(context,"This has changed",Toast.LENGTH_SHORT).show()
        }
    }
}
Copy the code

The effect of broadcasting over time is as follows

Static registration to achieve boot

Dynamic registration is flexible, but can only be accepted after the application is started, whereas static registration is used.

Dynamically register to listen to the radio in theory, then the static should also can, in the past can indeed, but because there are a large number of malicious programs using this mechanism when to start the program broadcasting system monitoring, resulted in the background of mobile phone frequent awakening, seriously affect the performance of mobile phones and battery, so every time the android version update, almost will weaken the function of static registration, Static registration is no longer allowed for all hermit broadcasts since Android8.0.

Hermit broadcast: A broadcast to which application is not specifically specified

Of course, some special broadcasts are allowed: boot broadcasts, for example

android.intent.action.BOOT_COMPLETED
Copy the code

Dynamically registering us through internal classes, now we’ll create it through the Android Studio shortcut, Right-click on the com. Example. Broadcastreceiver – > new – > other – > I changed the name of the class to BootCompleteReceiver Broadcast Receiver here

Exprodted: allows this BroadcasReceive to accept broadcasts outside the program

Enabled: Indicates whether to enable BroadcasReceive

Now modify the code of the BootCompleteReceiver class to pop up the prompt message using Toast in the onReceived method

package com.example.broadcastreceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast

class BootCompleteReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
        Toast.makeText(context,"Boot Complete",Toast.LENGTH_SHORT).show()
    }
}
Copy the code

Statically registered BroadcasReceiv must be registered in activitymanifest.xml. Since we registered it using a shortcut, we registered it directly, as shown in the following example:

 <receiver
            android:name=".BootCompleteReceiver"
            android:enabled="true"
            android:exported="true"></receiver>
Copy the code

To receive a startup broadcast, you have to modify the Activitymanifest.xml code to add because of permissions

   <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Copy the code

Finally, add the action under the <receiver TAB

 <receiver
          android:name=".BootCompleteReceiver"
          android:enabled="true"
          android:exported="true">
          <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED"/>
          </intent-filter>
Copy the code

A BroadcastReceiver is defined to receive broadcasts

package com.example.broadcastreceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast

class MyBoardcastReceiver : BroadcastReceiver() {

 override fun onReceive(context: Context, intent: Intent) {
     // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
     Toast.makeText(context,"recevied in MYboardcastReciver",Toast.LENGTH_SHORT).show()
 }
}
Copy the code

Then in ActivityManifest modify BroadcastReceiver and making BoardcastReceiver accept com here. Example. Broadcasttest. MY_BRPADCAST broadcasting

    <receiver
            android:name=".MyBoardcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.broadcasttest.MY_BRPADCAST"/>
            </intent-filter>
        </receiver>
Copy the code

To send this broadcast, modify the man.xml code to add a button layout

<? The XML version = "1.0" encoding = "utf-8"? > <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>Copy the code

Then set up the listener in ManActivity

Start by building an Intent object that passes in a send broadcast

Call intent.setpackage (packageName) to pass in the packageName of the current application

SendBroadcast (Intent) Specifies that the broadcast is sent to a specific application

class MainActivity : AppCompatActivity() { lateinit var timeChangerReceiver:TimeChangeRecevier override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val button:Button=findViewById(R.id.button) button.setOnClickListener{ val intent=Intent("comcom.example.broadcasttest.MY_BRPADCAST") intent.setPackage(packageName)  sendBroadcast(intent) } .....Copy the code

Orderly broadcast

Create a BoradcastReceiver in shortcut to accept the same broadcast

package com.example.myapplication

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast

class MyReceiver2 : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
       // The pop-up message that receives the broadcast message becomes up up
        Toast.makeText(context,"up up ", Toast.LENGTH_SHORT).show()
    }
}
Copy the code

In androidmanifest.xml, change the priority to 100. This broadcast is the first to receive messages

 <intent-filter android:priority="100">
Copy the code

You can then block the broadcast and not transmit it

class MyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
      Toast.makeText(context,"up up day day",Toast.LENGTH_SHORT).show()
         abortBroadcast()// Cut off the broadcast}}Copy the code

BroadcastReceiver best practices

Simulate forced logout after login

1. First we create a class to manage all activities

package com.example.broadcastreceiver

import android.app.Activity
// This class manages the closing and adding of all activities
object Activityall {
    private val activityaes=ArrayList<Activity>()
    fun addActivty(activity: Activity){
        activityaes.add(activity)
    }
    fun removeactivity(activity: Activity){
        activityaes.remove(activity)
    }
    fun allActivity(a){
        for (activity in activityaes){
            if(! activity.isFinishing){ activity.finish() } } activityaes.clear() } }Copy the code

We then create a BaseActivity class to be the parent of all activities, because our forced logout function means that you have to force out no matter what class you are in, so the logic for exiting and accepting registration broadcasts and unregistering is all done in this class

package com.example.broadcastreceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

open  class BaseActivity: AppCompatActivity() {
    lateinit var recevier:ForReceiver
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        Activityall.addActivty(this)}override fun onResume(a) {
        super.onResume()
        val intentFilter=IntentFilter()
          intentFilter.addAction("com.example.FOLL_PO")
          recevier=ForReceiver()
          registerReceiver(recevier,intentFilter)

    }

    override fun onPause(a) {
        super.onPause()
        unregisterReceiver(recevier)
    }
    override fun onDestroy(a) {
        super.onDestroy()
        Activityall.removeactivity(this)}inner class ForReceiver:BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

            AlertDialog.Builder(context).apply {
                setTitle("Offline")
                setMessage("You're out. Get off the line.")
                setCancelable(false)// Cannot force exit
                setPositiveButton("Ok") { _, _ ->
                    Activityall.allActivity()
                    val i = Intent(context, LoginActivity::class.java)
                    context.startActivity(i)


                }
                show()
            }
    }
}
}
Copy the code

Next build a LoginActivity as the login interface

package com.example.broadcastreceiver

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.core.content.withStyledAttributes

class LoginActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val login:Button=findViewById(R.id.login)
        login.setOnClickListener {
            val zh:EditText=findViewById(R.id.zh)
            val zh2=zh.text.toString();
            val mm:EditText=findViewById(R.id.mm)
            val mm2=mm.text.toString();
            if (zh2=="abc"&&mm2=="123") {val intent=Intent(this,MainActivity::class.java)
                startActivity(intent)
            }else{
                Toast.makeText(this."Wrong password or account number for young man.",Toast.LENGTH_SHORT).show()
            }
        }
    }
}
Copy the code
<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="18sp"
            android:text="Account." />

        <EditText
            android:id="@+id/zh"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical" />
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="18sp"
            android:text="Password" />

        <EditText
            android:id="@+id/mm"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:inputType="textPassword" />
    </LinearLayout>

    <Button
        android:id="@+id/login"
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:layout_gravity="center_horizontal"
        android:text="Login" />


</LinearLayout>
Copy the code

Verify the correctness of the account and password in LoginActivity

package com.example.broadcastreceiver

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.core.content.withStyledAttributes

class LoginActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val login:Button=findViewById(R.id.login)
        login.setOnClickListener {
            val zh:EditText=findViewById(R.id.zh)
            val zh2=zh.text.toString();
            val mm:EditText=findViewById(R.id.mm)
            val mm2=mm.text.toString();
            if (zh2=="abc"&&mm2=="123") {// The login page is displayed after forcibly logging out
                val intent=Intent(this,MainActivity::class.java)
                startActivity(intent)
            }else{
                Toast.makeText(this."Wrong password or account number for young man.",Toast.LENGTH_SHORT).show()
            }
        }
    }
}
Copy the code

Add a button to the ManActivity that triggers a forced logout

<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >
    <Button
        android:id="@+id/tc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="tuichu"/>
</LinearLayout>
Copy the code

Modify the MainActivity code

package com.example.broadcastreceiver

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val tuichu:Button=findViewById(R.id.tc)
        tuichu.setOnClickListener {
            val intent=Intent("com.example.FOLL_PO")
            // Send a broadcast
            sendBroadcast(intent)
        }
    }
}
Copy the code

Finally, be sure to change the LoginActivity login screen to the main Activity

   <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
Copy the code

Run last if the password is wrong

If yes, the page after login is redirected

Click this button to simulate forced logout

Click OK to return to the login screen