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

Android15 无法接收到应用自身发出的广播分析解决

Android15 无法接收到应用自身发出的广播分析解决

文章目录

  • Android15 无法接收到应用自身发出的广播分析解决
    • 一、前言
    • 二、无法接收到应用内自身发送的普通广播分析和解决
      • 1、一段简单的应用广播监听和发送代码
      • 2、Android 15 无法接收到应用内普通广播的分析
        • Android 广播核心流程链
      • 3、无法接收到应用内自身发送的普通广播解决
    • 三、其他
      • 1、Android15 无法接收到应用内自身发出的广播分析解决小结
      • 2、自身发送的普通广播的其他验证
      • 3、Android 中的 本地广播LocalBroadcastManager
      • 4、Android14 普通应用registerReceiver注册广播报错One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be

一、前言

最近Android15新建的项目发现一个问题:应用内的广播发送后,无法接收到了。

    defaultConfig {applicationId "com.liwenzhi.broadcasttest"minSdk 31targetSdk 35versionCode 1versionName "1.0"}

把上面 的 targetSdk 替换成33 就可以正常替换了。
难道Android13 版本之后,系统对自身发出的普通广播做了限制接收?
本文简单分析解决看看。

二、无法接收到应用内自身发送的普通广播分析和解决

1、一段简单的应用广播监听和发送代码

package com.liwenzhi.broadcasttest;import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);LogUtil.debug("");registerBroadcast(this);//动态监听广播}@Overrideprotected void onDestroy() {super.onDestroy();unRegisterBroadcast(this);}//发送自定义广播public void sendBroadcast(View view) {LogUtil.debug("");Intent intent = new Intent("TestBroadcast");sendBroadcast(intent);}//注册广播监听public void registerBroadcast(Context context) {LogUtil.debug("");IntentFilter filter = new IntentFilter();filter.addAction("TestBroadcast"); //自定义广播filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //网络监听广播registerReceiver(mReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);}public void unRegisterBroadcast(Context context) {context.unregisterReceiver(mReceiver);}//广播接收者+打印private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();LogUtil.debug("onReceive: action = " + action);switch (action) {case ACTION_NET_CHANGE_ACTION:LogUtil.debug("网络变化");break;case "TestBroadcast":LogUtil.debug("自定义广播接收");break;}}};}

之前Android13 经常这样使用是OK的,但是到Android15 就不行了;

上面广播监听是正常的,开关wifi能接收到网络变化的广播;

所以为啥Android15 ,无法接收到应用内发送的普通广播了?

为啥会这样暂时未分析出具体原因和具体哪行代码导致。

但是大概过程是了解一些的:

2、Android 15 无法接收到应用内普通广播的分析

Android 广播核心流程链
应用发送广播 → ContextImpl → Binder 调用 → 
AMS(匹配接收者、调度)  //重点:ActivityManagerService 
→ Binder 调用 → 目标进程ActivityThread → 调用BroadcastReceiver.onReceive()

ActivityManagerService 里面有收集所有广播的集合:

AMS 维护 mRegisteredReceivers 映射表,存储已注册的动态接收器:
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

中间有非常复杂的过程判断逻辑,会对广播列表进行排序,分发前做各种判断处理;

用AI 搜到的说是 isSameComponentApplicationLocked 方法会判断应用内发送的广播,但是源码未找到这个方法。

所以这里暂时只能停供一个思路,研究看看 ActivityManagerService 应用内广播分发的具体流程。

ActivityManagerService 是有点多的,大概两万多行,看着头疼。

虽然目前未分析出导致应用内无法接收到自身发出的普通广播的具体的代码,但是也是有解决方案的:

3、无法接收到应用内自身发送的普通广播解决

发送本地广播就可以解决这个问题:

LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

需要注意的是,必须要注册本地广播,普通广播接收者是无法接收本地广播的信息的:

IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.BRO_TEST"); //自定义广播
filter.addAction(Intent.ACTION_TIME_CHANGED);//time_set
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //网络监听广播
//registerReceiver(mReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);//普通关闭注册
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter); //自定义广播注册

上面可以看到本地广播注册和普通动态广播注册是类型的,只是具体注册调用的api不同。

三、其他

1、Android15 无法接收到应用内自身发出的广播分析解决小结

Android 15 无法接收到应用内自身发出的普通广播的分析主要逻辑在 ActivityManagerService

目前还未找到导致问题的具体代码,有兴趣的可以自行研究看看。

解决方法:

使用 LocalBroadcastManager 发送和监听本地广播 

这个估计也不算问题,估计是Google 官方对于Android15 的优化处理,可能是为了效率或者安全。

本地广播LocalBroadcastManager并非Android15才有,早在Android5 已经存在了。

2、自身发送的普通广播的其他验证

下面是一些其他验证情况:

(1)验证试了Android14 也是上面问题,Android13 没有这个问题,所以Android14或者更新的系统会有这个问题
(2)Android14或者更新的版本上,发送普通广播,其他应用是可以动态监听到的;
(3)Android 13 AML方案,使用SKD 35编译的应用也是可以接收到自身发出的普通广播;
理论上Android15版本的应用,不能安装到Android13 版本上,这里可能是系统就行了适配,实际还是Android13 的应用。

3、Android 中的 本地广播LocalBroadcastManager

本地广播(注册),数据安全,其他app也不能给你发广播(接收)。也比系统广播高效。

一般使用在应用内部不同fragment和Activity的交互,或者界面和service 的交互。

BroadcastReceiver设计的初衷是从全局考虑可以方便应用程序和系统、应用程序之间、应用程序内的通信,

所以对单个应用程序而言BroadcastReceiver是存在安全性问题的(恶意程序脚本不断的去发送你所接收的广播)。

为了解决这个问题LocalBroadcastManager就应运而生了。

https://blog.csdn.net/wenzhi20102321/article/details/134042436

4、Android14 普通应用registerReceiver注册广播报错One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be

Android14 普通应用注册广播registerReceiver会报错,提示需要添加一个参数RECEIVER_EXPORTED 或者 RECEIVER_NOT_EXPORTED;系统framework或者系统应用是不会报这个错误的!

这个问题比较好解决,加一个参数就行,但是网上目前没有人对这个问题今天深入分析。

本文对registerReceiver报错进行分析,具体到哪个类哪行代码报错。

https://blog.csdn.net/wenzhi20102321/article/details/138345708

http://www.dtcms.com/a/274121.html

相关文章:

  • 【牛客刷题】dd爱科学1.0
  • Java 大视界 -- Java 大数据在智能医疗远程手术机器人操作数据记录与分析中的应用(342)
  • 从静到动的创作革命:Midjourney Video V1重塑AI影像叙事
  • 滑动窗口-3.无重复字符的最长子串-力扣(LeetCode)
  • 【Linux】虚拟内存的概念和布局
  • UI自动化神器:Playwright元素定位方法!
  • 新型变种木马正在伪装成Termius入侵系统
  • Kotlin 常用语法糖完整整理
  • 【springboot】IDEA手动创建SpringBoot简单工程(无插件)
  • 【零基础学AI】第37讲:提示词工程(Prompt Engineering)
  • NLP_知识图谱_大模型——个人学习记录
  • 解决MySQL虚拟删除影响唯一索引的问题
  • 《PyWin32:Python与Windows的桥梁,解锁系统自动化新姿势》
  • 从0开始学习R语言--Day44--LR检验
  • 外媒:蚂蚁数科等科技公司在香港数字资产枢纽建设中显身手
  • python 在 Linux CentOS 上安装 playwright 的完整步骤
  • 【每日刷题】回文数
  • 【数据结构】8. 二叉树
  • 【LeetCode 热题 100】24. 两两交换链表中的节点——(解法一)迭代+哨兵
  • leetcode106深度解析:从中序与后序遍历序列构造二叉树
  • leetcode:518. 零钱兑换 II[完全背包]
  • 【网络】Linux 内核优化实战 - net.ipv4.tcp_congestion_control
  • (LeetCode 每日一题) 3169. 无需开会的工作日 ( 排序+贪心 )
  • 力扣_二叉搜索树_python版本
  • 1965–2022年中国大陆高分辨率分部门用水数据集,包含:灌溉用水、工业制造用水、生活用水和火电冷却
  • 【unitrix】 4.21 类型级二进制数基本结构体(types.rs)
  • 李沐动手学深度学习Pytorch-v2笔记【07自动求导代码实现】
  • 进程管理中的队列调度与内存交换机制
  • Jenkins 系统管理与配置
  • 排序算法与前端交互优化