Android--BroadcastReceiver

赵钊
2023-12-01

1、概念

广播分为发广播和广播接收者,类似于广播发射器和收音机。
在整个Android开发中,主要研究的就是发广播和接收广播。

2、广播的分类

从发广播的角度来说:分为系统广播和第三方广播
从接收的顺序上来说:分为有序广播和无需广播。

常见的系统广播如:系统开机完成的广播,电量改变的广播,usb是否连接的广播,wifi状态改变的广播等等

3、动态注册广播(监听电量变化)

package com.example.broadcastreceiverexample.batteryChange.BatteryChangeActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.broadcastreceiverexample.R;

/**
 * 动态注册:
 * 节省资源,不用一直监听
 * 跟随着Activity的生命周期走
 */
public class BatteryChangeActivity extends AppCompatActivity {
    private static final String TAG = "BatteryChangeActivity";
    private BatterLevelReceiver mBatterLevelReceiver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_battery_change);
        registerBroadcastReceiver();
    }

    /**
     * 第二步:注册一个BroadcastReceicer
     */
    private void registerBroadcastReceiver() {
        //创建一个意图过滤器
        IntentFilter intentFilter = new IntentFilter();
        //设置频道
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        //设置成全局变量,方便在此应用销毁的时候取消注册的广播
        mBatterLevelReceiver = new BatterLevelReceiver();
        //注册
        registerReceiver(mBatterLevelReceiver,intentFilter);
    }

    /**
     * 第一步:创建一个内部类,即创建一个广播接收者,继承BroadcastReceiver
     */
    private class BatterLevelReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG,"收到电量变化的广播---action is "+action);
            Log.d(TAG,"当前的电量为:"+ intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0));
            Log.d(TAG,"当前最大的电量为:"+ intent.getIntExtra(BatteryManager.EXTRA_SCALE,0));
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在销毁此Activity时,取消广播注册,否则会造成内存泄露
        if (mBatterLevelReceiver != null) {
            unregisterReceiver(mBatterLevelReceiver);
            Log.d(TAG, "onDestroy: 广播注销完成");
        }
    }
}

在如上的demo中,涉及到以下几个知识点:

1、android.content.intent中的ACTION_BATTERY_CHANGED(系统广播)
    /**
     * Broadcast Action:  This is a <em>sticky broadcast</em> containing the
     * charging state, level, and other information about the battery.
     * See {@link android.os.BatteryManager} for documentation on the
     * contents of the Intent.
     *
     * <p class="note">
     * You <em>cannot</em> receive this through components declared
     * in manifests, only by explicitly registering for it with
     * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
     * Context.registerReceiver()}.  See {@link #ACTION_BATTERY_LOW},
     * {@link #ACTION_BATTERY_OKAY}, {@link #ACTION_POWER_CONNECTED},
     * and {@link #ACTION_POWER_DISCONNECTED} for distinct battery-related
     * broadcasts that are sent and can be received through manifest
     * receivers.
     *
     * <p class="note">This is a protected intent that can only be sent
     * by the system.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";



2、android.os.BatteryManager中的EXTRA_LEVEL(当前电量)和EXTRA_SCALE (最大电量)
    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * integer field containing the current battery level, from 0 to
     * {@link #EXTRA_SCALE}.
     */
    public static final String EXTRA_LEVEL = "level";
    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * integer containing the maximum battery level.
     */
    public static final String EXTRA_SCALE = "scale";

4、静态注册广播(监听开机完成)

package com.example.broadcastreceiverexample.batteryChange.BatteryChangeActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

/**
 * 第一步创建一个类,并继承BroadcastReceiver
 * 静态注册比较耗资源,一直处于监听的状态。静态注册的广播优先级高于动态注册的广播
 */
public class BootCompleteReceiver extends BroadcastReceiver {
    private static final String TAG = "BootCompleteReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "action is "+action);
        Log.d(TAG, "onReceive: 开机完成...");
         try {
         //添加一个线程,在开机后更明显的显示Toast
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Toast.makeText(context,"开机完成,接收到了广播",Toast.LENGTH_LONG).show();
    }
}

    <!--添加权限,之所以添加权限,与BOOT_COMPLETED有关-->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    
        <!--静态注册-->
        <receiver android:name=".batteryChange.BatteryChangeActivity.BootCompleteReceiver">
            <!--第二步:添加action-->
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>
在源码中这样写到,需要添加RECEIVE_BOOT_COMPLETED权限才能使用
    /**
     * Broadcast Action: This is broadcast once, after the user has finished
     * booting. It can be used to perform application-specific initialization,
     * such as installing alarms. You must hold the
     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
     * order to receive this broadcast.
     * <p>
     * This broadcast is sent at boot by all devices (both with and without
     * direct boot support). Upon receipt of this broadcast, the user is
     * unlocked and both device-protected and credential-protected storage can
     * accessed safely.
     * <p>
     * If you need to run while the user is still locked (before they've entered
     * their lock pattern or PIN for the first time), you can listen for the
     * {@link #ACTION_LOCKED_BOOT_COMPLETED} broadcast.
     * <p class="note">
     * This is a protected intent that can only be sent by the system.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    @BroadcastBehavior(includeBackground = true)
    public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";

5、注意事项

在Android 8.0之后,不推荐使用静态注册的方式去注册广播。官方说明如下

As part of the Android 8.0 (API level 26) Background Execution Limits, apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. However, several broadcasts are currently exempted from these limitations. Apps can continue to register listeners for the following broadcasts, no matter what API level the apps target.

仅为学习过程中的记录,方便自己以后查阅,也希望能帮助到每一位查阅者。其它广播详情均可参考Android Developer中的详细介绍。
参考文献地址:https://developer.android.google.cn/training/permissions/requesting#principles

 类似资料: