Android zero-based entry | broadcast mechanism Broadcast

insert image description here

Android applications can receive or send messages from the system or other apps through broadcasting. Similar to the subscribe-publish design pattern. Broadcasts can be emitted when certain events occur. The system broadcasts when some state changes, such as power on, charging. App can also send custom broadcasts. Broadcasting can be used for communication between applications and is a form of IPC.

type of broadcast

The type of broadcast can also be regarded as an attribute of the broadcast.

  • Standard Broadcasts (Normal Broadcasts) are completely asynchronous broadcasts. After the broadcast is sent out, all broadcast receivers receive the broadcast almost simultaneously. Different apps can register and receive standard broadcasts. For example system broadcast.
  • Ordered Broadcasts (Ordered Broadcasts) broadcast synchronously. Only one broadcast receiver can receive this broadcast at a time. The broadcast will not continue to be delivered until this receiver has been processed. Ordered broadcasts are global broadcasts.
  • Local broadcasts (Local Broadcasts) are only broadcasts sent and received by this App. Receivers registered for local broadcasts cannot receive standard broadcasts.
  • Permissioned broadcasts You can carry relevant permissions when sending broadcasts, and only the app or broadcast receiver that has applied for permissions can receive the corresponding permissioned broadcasts. If the corresponding permission is applied for in the manifest, the receiver can receive the corresponding broadcast without applying for another permission.

receive broadcast

To create a broadcast receiver and call onReceive()a method, a class that inherits BroadcastReceiver is required.

Registration in broadcast code is called dynamic registration. Registering in AndroidManifest.xmlis called static registration. Dynamically registered rigid wave receivers must be unregistered. onDestroy()Call method in method to unregisterReceiver()unregister.

Do not onReceive()add too many logical operations or time-consuming operations to the method. Because it is not allowed to open threads in the broadcast receiver, when onReceive()the method runs for a long time without ending, the program will report an error. So broadcast receivers are generally used to open other components, such as creating a status bar notification or starting a service.

Create a new MyExampleReceiver inherited from BroadcastReceiver .

public class MyExampleReceiver extends BroadcastReceiver {
    
    
    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        Toast.makeText(context,"Got it",Toast.LENGTH_SHORT).show();
        //abortBroadcast();
    }
}

abortBroadcast()ordered broadcast can be truncated

AndroidManifest.xmlRegister the broadcast receiver in; fill android:namein the name of the receiver. Broadcast receiver priority can be set:

<intent-filter android:priority="100">

<receiver android:name=".MyExampleReceiver">
    <intent-filter>
        <action android:name="com.rust.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

Let the receiver receive a "com.rust.broadcasttest.MY_BROADCAST"broadcast. This value is passed when sending custom broadcasts (standard broadcasts). For example:

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);

To send an ordered broadcast, you should callsendOrderedBroadcast()

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);

send broadcast

App has 3 ways to send broadcasts. Sending a broadcast requires the use of the Intent class.

sendOrderedBroadcast(Intent, String)

Send an ordered broadcast. Only 1 broadcast receiver can receive the broadcast at a time. After a receiver receives an ordered broadcast, it can either truncate the broadcast completely, or pass some information to the next receiver. The order of ordered broadcasts can be android:priorityaffected by tags. The order in which receivers of the same level receive broadcasts is random.

sendBroadcast(Intent)

Send broadcasts to all receivers in an undefined order. Also known as general broadcasting. This method is more efficient, but the receiver cannot pass the message to the next receiver. Such broadcasts cannot be truncated either.

**LocalBroadcastManager.sendBroadcast broadcast can only be delivered within the application, and broadcast receivers can only receive broadcasts from this application. This method is more efficient than global broadcast (no Interprocess communication, IPC), and there is no need to worry about other apps receiving your broadcast and other security issues.

Broadcasting and Permissions

Send a broadcast with permissions

When you call sendBroadcast(Intent, String)or sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle), you can specify a permission. The receiver can only receive this broadcast when it has applied for the corresponding permission in the manifest.

For example, send a broadcast with permissions

sendBroadcast(new Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS);

Apps that receive broadcasts must register with the corresponding permissions

<uses-permission android:name="android.permission.SEND_SMS"/>

Of course you can also use custom. Use the permission tag in the manifest

<permission android:name="custom_permission" />

Compile it after adding it. can be calledManifest.permission.custom_permission

Receive broadcasts with permissions

If permissions are declared when registering a broadcast receiver, only broadcasts with corresponding permissions will be received.

Declare permissions in the configuration file so that the program can access some key information. For example, it allows querying the system network status.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<!-- 机器开机广播 -->
<uses-permission android:name="android.permission.BOOT_COMPLETED">

If permission is not requested, the program may close unexpectedly.

Example of use

Send and receive broadcasts. It is divided into two Apps, the sender and the receiver.

Use permissioned broadcasting. System permissions and custom permissions. Permissions need to be declared in AndroidManifest.xml . If it is a custom permission, you need to add the custom permission first.

<!-- 自定义的权限  给广播用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />

Bring the permission statement when sending the broadcast. The receiving party (whether it is its own App or not) needs to AndroidManifest.xmlapply for permission in . Permissions are also required to be declared when registering a receiver.

Send unprivileged ordered broadcast

Intent intent = new Intent(MSG_PHONE);
sendOrderedBroadcast(intent, null);
Log.d(TAG, "[RustFisher-App1] 发送不带权限的有序广播, " + intent.getAction());

Sender App1 code

private static final String TAG = "rustApp";
    public static final String MSG_PHONE = "msg_phone";
    public static final String PERMISSION_RUST_1 = "com.rust.permission_rust_1";

        // onCreate注册广播接收器
        registerReceiver(mStandardReceiver1, makeIF());
        registerReceiver(mStandardReceiver2, makeIF());
        registerReceiver(mStandardReceiver3, makeIF());

        registerReceiver(mStandardReceiverWithPermission, makeIF(),
                Manifest.permission.permission_rust_1, null);  // 带上权限

        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver1, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver2, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver3, makeIF());

        // 解除接收器
        unregisterReceiver(mStandardReceiver1);
        unregisterReceiver(mStandardReceiver2);
        unregisterReceiver(mStandardReceiver3);

        unregisterReceiver(mStandardReceiverWithPermission);

        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver1);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver2);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver3);

    // 发送标准广播
    private void sendStandardBroadcast() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送标准广播");
    }

    // 发送带权限的标准广播
    private void sendStandardBroadcastWithPermission() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent, PERMISSION_RUST_1);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送带权限的标准广播");
    }

    // 发送本地广播
    private void sendAppLocalBroadcast() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送本地广播");
    }

    private IntentFilter makeIF() {
    
    
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver1 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器1 收到: " + intent.getAction());
        }
    };

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver2 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器2 收到: " + intent.getAction());
            if (intent.getAction().endsWith(MSG_PHONE)) {
    
    
                abortBroadcast(); // 截断有序广播
                Log.d(TAG, "[RustFisher-App1] 标准接收器2截断有序广播 " + intent.getAction());
            }
        }
    };

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver3 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器3 收到: " + intent.getAction());
        }
    };

    // 注册的时候给它带权限  标准接收器
    private BroadcastReceiver mStandardReceiverWithPermission = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 带权限的标准接收器收到: " + intent.getAction());
        }
    };

    /**
 * 用LocalBroadcastManager来注册成为本地接收器
 * 收不到标准广播 - 不论是本app发出的还是别的地方发出来的
 */
    private BroadcastReceiver mLocalReceiver1 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器1 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver2 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器2 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver3 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器3 收到: " + intent.getAction());
        }
    };

Receiver App2 Code

<!-- 自定义的权限  给广播用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />
public static final String MSG_PHONE = "msg_phone";

    // onCreate里注册接收器
    registerReceiver(mDefaultReceiver, makeIF());
    LocalBroadcastManager.getInstance(getApplicationContext())
            .registerReceiver(mLocalReceiver, makeIF());

    unregisterReceiver(mDefaultReceiver);
    LocalBroadcastManager.getInstance(getApplicationContext())
            .unregisterReceiver(mLocalReceiver);

    private BroadcastReceiver mDefaultReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[App2] standard receive: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[App2] local receive: " + intent.getAction());
        }
    };

    private IntentFilter makeIF() {
    
    
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

Using LocalBroadcastManagerthe local broadcast sent out, another app cannot receive it. To receive local broadcasts, you also need LocalBroadcastManagerto register the receiver.

You can think of local broadcasting as a partial broadcasting system within the app.

In the experiment, we noticed that Intent.ACTION_TIME_TICKthe broadcast can be truncated.

Monitor screen lights up

Use the broadcast to monitor the status of the screen on and off of the device. This is a broadcast from the system.

The action used is

  • Intent.ACTION_SCREEN_ON bright screen
  • Intent.ACTION_SCREEN_OFF 灭屏
    private void registerScreenListener() {
    
    
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mScreenReceiver, filter);
    }

    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            final String action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) {
    
    
                // 屏幕亮
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
    
    
                // 屏幕灭
            }
        }
    };

Broadcast related interview questions

1. Is there a limit to the data transmitted by broadcasting, how much is it, and why should it be limited?

  • Broadcasting is to carry the data that needs to be delivered through Intent
  • Intent is implemented through the Binder mechanism
  • Binder has a limit on the data size, different rooms are different, generally 1M

2. Classification of broadcasting?

  • Standard broadcast: sent to all registered receivers in the current system through context.sendBroadcast or context.sendBroadcastAsUser, that is, as long as they are registered, they will receive it. The application is used when it is necessary to notify each broadcast receiver, such as booting up.
  • Orderly broadcast: The receiver processes the broadcast according to the priority, and the receiver who previously processed the broadcast can stop the delivery of the broadcast, usually through context.sendOrderedBroadcast or context.sendOrderedBroadcastAsUser, which is used in scenarios that require specific interception, such as blacklist SMS , Phone interception.
  • Sticky broadcast: It can be sent to recipients registered in the future, which means that the system will save the previous sticky broadcast in AMS. Once a broadcast that matches the saved sticky broadcast is registered, the broadcast will be received immediately after the registration is completed. Generally, Send it through context.sendStickyBroadcast or context.sendStickyOrderedBroadcast. Literally, it can be seen that sticky broadcasts are also divided into ordinary sticky broadcasts and ordered sticky broadcasts.
  • Local broadcast: broadcasts sent can only be delivered within the application, and broadcast receivers can only accept broadcasts from this application.
  • Global broadcast: system and broadcast, the broadcast sent can be received by any other application, and can also receive the broadcast of any other application.

3. Broadcast usage scenarios and usage methods Broadcasting is a widely used mechanism for transmitting information between applications. It is mainly used to monitor the broadcast information sent by the system or application, and then use the broadcast information as a corresponding logical process. Used to transmit a small amount of data with low frequency.

When realizing boot-up services and network status changes, power changes, text messages and incoming calls, the application program can be processed accordingly by receiving the broadcast of the system.

use:

//在AndroidManifest中静态注册
<receiver
    android:name=".MyBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="100">
        <action android:name="com.example.hp.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

//动态注册,在代码中注册
@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mIntentFilter = new IntentFilter();
    //添加广播想要监听的类型,监听网络状态是否发生变化
    mIntentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    mNetworkChangeReceiver = new NetworkChangeReceiver();
    //注册广播
    registerReceiver(mNetworkChangeReceiver, mIntentFilter);
}

@Override
protected void onDestroy() {
    
    
    super.onDestroy();
    //取消注册广播接收器
    unregisterReceiver(mNetworkChangeReceiver);
}

//发送广播,同样通过Intent
Intent intent = new Intent("com.example.hp.broadcasttest.MY_BROADCAST");
//发送标准广播
sendBroadcast(intent);

//接收广播
public class MyBroadcastReceiver extends BroadcastReceiver {
    
    
    public MyBroadcastReceiver() {
    
    
    }

    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Toast.makeText(context, "received", Toast.LENGTH_SHORT).show();
        //将这条广播截断
//        abortBroadcast();
    }
}

4. Difference between BroadcastReceiver and LocalBroadcastReceiver Broadcast receiver:

1)用于应用间的传递消息
(2)由于跨应用,存在安全问题

Local broadcast receiver:

1)广播数据在本应用范围内传播。  
(2)不用担心别的应用伪造广播。  
(3)比发送全局广播更高效、安全。  
(4)无法使用静态注册  

5. How to register and use BroadcastReceiver in manifest and code (1) Register statically in AndroidManifest and use it directly. (2) In the code, register through registerReceiver. (3) After registering and sending, receive and process the broadcast in onReceive of BroadcastReceiver (a custom receiver inherited from BroadcastReceiver).

6. Time limit for anr caused by broadcast Foreground broadcast: BROADCAST_FG_TIMEOUT = 10s Background broadcast: BROADCAST_BG_TIMEOUT = 60s

last share

[Tencent technical team produced] Android zero-based entry to proficiency, Android Studio installation tutorial + a full set of Android basic tutorials

Android programming tutorial

Java language basics from entry to familiarity

insert image description here

Kotlin language basics from entry to familiarity

insert image description here

Android technology stack from entry to familiarity

insert image description here

Android Jetpack family bucket comprehensive learning

insert image description here

For novices, it may be difficult to install Android Studio. You can watch the following video and learn to install and run step by step.

Android Studio installation tutorial

insert image description here

With the learning of the Java stage, it is recommended to focus on video learning at this stage and supplement it with books to check for omissions. If you focus on books, you can type codes based on book explanations, supplemented by teaching videos to check for omissions. If you encounter problems, you can go to Baidu. Generally, many people will encounter problems when getting started, and they will give better answers.

It is necessary to master basic knowledge points, such as how to use the four major components, how to create a Service, how to layout, simple custom View, animation, network communication and other common technologies.

A full set of zero-based tutorials has been prepared for you, if you need it, you can add the QR code below to get it for free

A full set of Android basic tutorials

insert image description here

insert image description here

insert image description here

insert image description here
insert image description here
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/Android23333/article/details/132445087