当前位置: 首页 > news >正文

Android Broadcast广播封装

在 Android 高版本(尤其是 Android 8.0 及以上)中,Broadcast 的使用受到了一些限制,例如 隐式广播 的限制和 后台执行限制。为了适配高版本并简化 Broadcast 的使用,可以封装一个工具类,支持动态注册、静态注册、权限控制等功能。

以下是 Broadcast 工具类的封装,支持高版本适配,并提供简洁的 API。

  1. Broadcast 工具类封装
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import androidx.annotation.RequiresApi;
import java.util.HashMap;
import java.util.Map;

public class BroadcastUtils {

    private static final Map<Context, Map<BroadcastReceiver, IntentFilter>> receiverMap = new HashMap<>();

    /**
     * 动态注册广播
     *
     * @param context  上下文
     * @param receiver 广播接收器
     * @param filter   意图过滤器
     */
    public static void registerReceiver(Context context, BroadcastReceiver receiver, IntentFilter filter) {
        if (context == null || receiver == null || filter == null) {
            return;
        }

        // 高版本适配:使用 ContextCompat 注册
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            context.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED);
        } else {
            context.registerReceiver(receiver, filter);
        }

        // 保存注册信息,用于取消注册
        Map<BroadcastReceiver, IntentFilter> contextReceivers = receiverMap.get(context);
        if (contextReceivers == null) {
            contextReceivers = new HashMap<>();
            receiverMap.put(context, contextReceivers);
        }
        contextReceivers.put(receiver, filter);
    }

    /**
     * 取消注册广播
     *
     * @param context  上下文
     * @param receiver 广播接收器
     */
    public static void unregisterReceiver(Context context, BroadcastReceiver receiver) {
        if (context == null || receiver == null) {
            return;
        }

        try {
            context.unregisterReceiver(receiver);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        // 移除注册信息
        Map<BroadcastReceiver, IntentFilter> contextReceivers = receiverMap.get(context);
        if (contextReceivers != null) {
            contextReceivers.remove(receiver);
            if (contextReceivers.isEmpty()) {
                receiverMap.remove(context);
            }
        }
    }

    /**
     * 发送广播
     *
     * @param context 上下文
     * @param intent  意图
     */
    public static void sendBroadcast(Context context, Intent intent) {
        if (context == null || intent == null) {
            return;
        }
        context.sendBroadcast(intent);
    }

    /**
     * 发送带权限的广播
     *
     * @param context      上下文
     * @param intent       意图
     * @param permission   权限
     */
    public static void sendBroadcast(Context context, Intent intent, String permission) {
        if (context == null || intent == null || permission == null) {
            return;
        }
        context.sendBroadcast(intent, permission);
    }

    /**
     * 发送有序广播
     *
     * @param context      上下文
     * @param intent       意图
     * @param permission   权限
     */
    public static void sendOrderedBroadcast(Context context, Intent intent, String permission) {
        if (context == null || intent == null || permission == null) {
            return;
        }
        context.sendOrderedBroadcast(intent, permission);
    }

    /**
     * 取消注册所有广播
     *
     * @param context 上下文
     */
    public static void unregisterAllReceivers(Context context) {
        if (context == null) {
            return;
        }

        Map<BroadcastReceiver, IntentFilter> contextReceivers = receiverMap.get(context);
        if (contextReceivers != null) {
            for (BroadcastReceiver receiver : contextReceivers.keySet()) {
                try {
                    context.unregisterReceiver(receiver);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
            }
            contextReceivers.clear();
            receiverMap.remove(context);
        }
    }
}
  1. 使用示例
    2.1 动态注册广播
// 自定义广播接收器
BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            System.out.println("Device boot completed");
        }
    }
};

// 注册广播
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
BroadcastUtils.registerReceiver(context, receiver, filter);

// 取消注册广播
BroadcastUtils.unregisterReceiver(context, receiver);

2.2 发送广播

// 发送普通广播
Intent intent = new Intent("com.example.CUSTOM_ACTION");
intent.putExtra("key", "value");
BroadcastUtils.sendBroadcast(context, intent);

// 发送带权限的广播
String permission = "com.example.PERMISSION";
BroadcastUtils.sendBroadcast(context, intent, permission);

2.3 发送有序广播

// 发送有序广播
String permission = "com.example.PERMISSION";
BroadcastUtils.sendOrderedBroadcast(context, intent, permission);

2.4 取消注册所有广播

// 取消注册所有广播
BroadcastUtils.unregisterAllReceivers(context);
  1. 高版本适配说明
    3.1 隐式广播限制
    从 Android 8.0(API 26)开始,系统对 隐式广播 进行了限制。如果目标广播是隐式的,需要使用 显式广播 或 JobScheduler 替代。

3.2 后台执行限制
从 Android 9(API 28)开始,系统对后台应用的广播接收器进行了限制。如果应用在后台运行,某些广播可能无法接收。

3.3 动态注册
在高版本中,建议使用 动态注册 的方式注册广播接收器,并在适当的生命周期中取消注册,以避免内存泄漏。

  1. 静态注册广播
    如果需要在应用未启动时接收广播(如开机启动),可以使用 静态注册。以下是一个示例:

4.1 在 AndroidManifest.xml 中声明广播接收器

<receiver android:name=".MyBootReceiver"
    android:exported="true"
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

4.2 实现广播接收器

public class MyBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            System.out.println("Device boot completed");
        }
    }
}
5. 总结

通过封装 Broadcast 工具类,可以:

简化广播的注册和发送。

适配高版本的隐式广播限制。

支持权限控制和有序广播。

避免内存泄漏和重复注册。

建议将工具类封装到一个独立的模块中,方便在项目中复用。根据实际需求,可以进一步扩展功能,如支持跨进程广播、自定义权限等。

相关文章:

  • 博客系统自动化测试_测试报告
  • OceanBase-obcp-v3考试资料梳理
  • LLMs之Agent:Manus(一款通用人工智能代理)的简介、安装和使用方法、案例应用之详细攻略
  • Redis—01—分布式系统
  • 使用 Docker 部署 RabbitMQ 并实现数据持久化
  • Kubernetes 的正式安装
  • 【数分】Numpy入门及进阶(四)
  • 数据集路径出错.yaml‘ images not found , missing path
  • 【Java线程基础操作详解】
  • SpringBoot3—场景整合:AOT
  • [LeetCode]day34 347.前k个高频元素
  • 使用开源OPUS-MT模型进行文本翻译(python)
  • android中activity1和activity2中接收定时消息
  • (C/S)架构、(B/S)架构
  • 粉尘环境下的智能生产革命 ——助力矿山行业实现高效自动化作业
  • 第九篇《行军篇》
  • 设计模式-单例模式
  • 【Javascript】计算器(Calculator)网页设计案例
  • NVIDIA Jetson Nano的国产替代,基于算能BM1684X+FPGA+AI算力盒子,支持deepseek边缘部署
  • 【Python项目】基于深度学习的电影评论情感分析系统
  • 广西隆林突发山洪,致3人遇难1人失联
  • 多个“首次”!上市公司重大资产重组新规落地
  • 全国省市县国土空间总体规划已基本批复完成,进入全面实施阶段
  • 租车订单时隔7年从花呗免密扣费?“GoFun出行”引质疑
  • 舱位已排到月底,跨境电商忙补货!美线订单大增面临爆舱,6月运价或翻倍
  • 上海市税务局:收到对刘某某存在涉税问题的举报,正依法依规办理