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

Android V 广播注册和配置注意事项问题

现象

在Android V平台上,应用注册非Protected广播时,如果没有加导出flag会抛出异常导致进程crash。

E/AndroidRuntime: FATAL EXCEPTION: main

        java.lang.SecurityException: com.demo.myapplication: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts

                at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)

官方的protected-broadcast参考

AndroidManifest.xml - OpenGrok cross reference for /frameworks/base/core/res/AndroidManifest.xml (aospxref.com)

平台规则

在Android 13 或更高版本为目标平台的应用内,在调用registerReceiver()时必须指定导出行为(exported true or false),如果未指定导出行为,可能会导致应用崩溃。

android:exported="true"

参考:广播概览  |  Background work  |  Android Developers

代码实现

接收广播

应用可以通过两种方式接收广播:通过清单声明的接收器 和上下文注册的接收器

1、【静态】声明广播接收器法

1、指定 <receiver> 元素。

<!-- If this receiver listens for broadcasts sent from the system or fromother apps, even other apps that you own, set android:exported to "true". -->
<receiver android:name=".MyBroadcastReceiver" android:exported="false"><intent-filter><action android:name="APP_SPECIFIC_BROADCAST" /></intent-filter>
</receiver>

intent 过滤器指定您的接收器所订阅的广播操作。 

2、创建 BroadcastReceiver 子类并实现 onReceive(Context, Intent)。通过 以下示例中的广播接收器会记录日志并显示内容 以下内容:

public class MyBroadcastReceiver extends BroadcastReceiver {private static final String TAG = "MyBroadcastReceiver";@Overridepublic void onReceive(Context context, Intent intent) {StringBuilder sb = new StringBuilder();sb.append("Action: " + intent.getAction() + "\n");sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");String log = sb.toString();Log.d(TAG, log);ActivityNameBinding binding =ActivityNameBinding.inflate(layoutInflater);val view = binding.root;setContentView(view);Snackbar.make(view, log, Snackbar.LENGTH_LONG).show();}}

系统软件包管理器会在应用安装时注册接收器。 然后,接收器将成为应用的单独入口点,这意味着 确保系统可以启动应用并传递广播(如果应用未 。

系统会创建一个新的 BroadcastReceiver 组件 对象来处理它接收的每个广播。仅此对象有效 在调用 onReceive(Context, Intent) 期间有效。将代码添加到 返回时,系统会将该组件 活动状态。

2、【动态】上下文注册的接收器(常用)

上下文注册的接收器可以接收广播,前提是它们的注册 上下文有效。例如,如果您在一个 Activity 上下文,只要 activity 不被销毁,您就会收到广播。如果您 注册到应用上下文,那么,只要应用 正在运行。

先创建 BroadcastReceiver和IntentFilter,再通过调用registerReceiver()方法来注册接收器。
 

RECEIVER_EXPORTED 导出flag定义

源码:

Context.java - OpenGrok cross reference for /frameworks/base/core/java/android/content/Context.java (aospxref.com)

    /*** <p>For apps targeting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},* either {@link #RECEIVER_EXPORTED} or {@link #RECEIVER_NOT_EXPORTED} must be* specified if the receiver is not being registered for <a* href="{@docRoot}guide/components/broadcasts#system-broadcasts">system broadcasts</a>* or a {@link SecurityException} will be thrown. See {@link* #registerReceiver(BroadcastReceiver, IntentFilter, int)} to register a receiver with* flags.*//*** Flag for {@link #registerReceiver}: The receiver can receive broadcasts from other Apps.* Has the same behavior as marking a statically registered receiver with "exported=true"*/public static final int RECEIVER_EXPORTED = 0x2;/*** @deprecated Use {@link #RECEIVER_NOT_EXPORTED} or {@link #RECEIVER_EXPORTED} instead.* @hide*/@Deprecated@TestApipublic static final int RECEIVER_EXPORTED_UNAUDITED = RECEIVER_EXPORTED;/*** Flag for {@link #registerReceiver}: The receiver cannot receive broadcasts from other Apps.* Has the same behavior as marking a statically registered receiver with "exported=false"*/public static final int RECEIVER_NOT_EXPORTED = 0x4;

整改方案※

运行时注册的广播接收器必须指定导出行为。

1、查看服务或应用内是否注册动态广播,且该广播属于非Procted系统广播

protected-broadcast

2、按照监听情况,在调用registerReceiver时添加标志位参数RECEIVER_EXPORTED 或RECEIVER_NOT_EXPORTED

//RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTEDBroadcastReceiver br = new MyBroadcastReceiver();//系统广播
//写法1
//IntentFilter filter = new IntentFilter();
//filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);//写法2
//IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
//registerReceiver(mSimStateReceiver, intentFilter);//写法3:自定义
IntentFilter filter = new IntentFilter("com.demo.myintentfilter");
boolean isListenBroadcaseFromOtherAps = false;int receiverFlags;
if (isListenBroadcaseFromOtherAps) {receiverFlags = RECEIVER_EXPORTED;
} else {receiverFlags = RECEIVER_NOT_EXPORTED;
}ContextCompat.registerReceiver(context, br, filter, receiverFlags)

源码kotlin参考:

 源码Java参考:

ScreenshotHelper.java - OpenGrok cross reference for /frameworks/base/core/java/com/android/internal/util/ScreenshotHelper.java (aospxref.com)

    public ScreenshotHelper(Context context) {mContext = context;IntentFilter filter = new IntentFilter(ACTION_USER_SWITCHED);mContext.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED);}

如上参考:Android 14 之 动态注册Broadcast必须声明exported属性以 Android 14 为目标并动态 - 掘金 (juejin.cn)


http://www.mrgr.cn/news/23658.html

相关文章:

  • ZCC6507高压、高频推挽变压器驱动器替代SN6507
  • 旋转目标检测对照实验-mmrotate基础教程
  • 全球视频云创新挑战赛算法赛道第一名比赛攻略
  • 智慧农业小型气象站
  • Java类和对象(详解)
  • Android - NDK: 在jni层生成java层对象,并调用java层的方法
  • 视频号黄金时间
  • JMeter做接口测试,如何提取登录Cookie
  • Unity Apple Vision Pro 开发(七):UI 交互 + 虚拟键盘
  • 数据结构应用实例(六)——最短路径
  • 2023下半年软考网络规划
  • Vue实现自定义进度条占比功能 Vue自定义进度条功能
  • excel无法保存文件
  • chapter08 面向对象编程高级 知识点总结Note
  • 源代码加密软件有哪些?10款常用的源代码加密软件分享!
  • 批发订货系统源码怎么弄 门店订货系统小程序价格
  • NX二次开发—实体名称工具
  • 数组的常用算法
  • 【Petri网导论学习笔记】Petri网导论入门学习(一)
  • Linux常见操作指令