Android15 版本解决后台无法启动应用问题
文章目录
- 前言-需求
- 一、修改文件
- 二、实现方案
-
- 1、实现全局去除拦截-所有应用都不检查
- [2、实现某个单独App 后台启动不检查](#2、实现某个单独App 后台启动不检查)
- 三、需求实现-思路
-
- 1、搜索关键日志-找到关键的类BackgroundActivityStartController
- 2、通过类-方法找到核心代码-checkBackgroundActivityStart
- 3、通过搜索关键方法checkBackgroundActivityStart-找到使用过的类
- 4、分析各个类是如何调用方法-checkBackgroundActivityStart
-
- [ActivityStarter-checkBackgroundActivityStart 类方法调用](#ActivityStarter-checkBackgroundActivityStart 类方法调用)
- [ActivityTaskManagerService-checkBackgroundActivityStart 类方法调用](#ActivityTaskManagerService-checkBackgroundActivityStart 类方法调用)
- [AppTaskImpl-checkBackgroundActivityStart 类方法调用](#AppTaskImpl-checkBackgroundActivityStart 类方法调用)
- [解决方案小结-BackgroundActivityStartController 类进行默认值即可](#解决方案小结-BackgroundActivityStartController 类进行默认值即可)
- 四、知识点扩展
-
- [BackgroundActivityStartController 初识](#BackgroundActivityStartController 初识)
- 实现类似功能,您需要使用替代方案。以下是几种主流方法的对比
- 总结
前言-需求
- 这里进行总结这个问题的目的,为了后续静默安装并重启静默安装的应用做铺垫;
- 在Android15 非 HOME 应用,发现第三方应用、系统应用 后台启动另外一个APP ,发现无效。 这就导致静默安装的应用 无法自动启动【需求是:静默安装应用成功后,自动启动安装的应用】。
现象
比如如下,启动一个App,居然无法启动。

在静默安装后,去启动这个应用,如下简单代码:发现总是失败! 如果写一个demo ,点击启动一个应用,绝对OK的。
java
private void launchApp(String appPackageName) {
Log.d(TAG,"=======launchApp========appPackageName:"+appPackageName);
Intent mLaunchIntent = mContext.getPackageManager().getLaunchIntentForPackage(appPackageName);
if (mLaunchIntent != null) {
Log.d(TAG, "launch app---> appPackageName:"+appPackageName);
if (mLaunchIntent.resolveActivity(mContext.getPackageManager()) != null) {
Log.d(TAG, "launch app---> startActivity ");
try {
mLaunchIntent.addFlags(
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mContext.startActivity(mLaunchIntent);
} catch (ActivityNotFoundException | SecurityException e) {
Log.e(TAG, "Could not start activity", e);
}
} else {
Log.e(TAG, "No activity found to handle the intent for: " + appPackageName);
}
}else{
Log.d(TAG,"===============qidong failed========");
}
}
问题
以前在HOME程序、MTK Android12/13 上面没有问题的,这次在RK3576 平台 Android15 版本,发现无法正常启动。 这里要解决的就是Android15 后台启动应用问题。
报错如下:

一、修改文件
路径:/frameworks/base/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
二、实现方案
在 checkBackgroundActivityStart 方法中,直接返回允许:BalVerdict.ALLOW_BY_DEFAULT,代码如下;
1、实现全局去除拦截-所有应用都不检查
java
BalVerdict checkBackgroundActivityStart(
int callingUid,
int callingPid,
final String callingPackage,
int realCallingUid,
int realCallingPid,
WindowProcessController callerApp,
PendingIntentRecord originatingPendingIntent,
BackgroundStartPrivileges forcedBalByPiSender,
ActivityRecord resultRecord,
Intent intent,
ActivityOptions checkedOptions) {
// modify by fangchen start
if(true){
Slog.d(TAG, " to set default as default=====================");
return BalVerdict.ALLOW_BY_DEFAULT;
}
// modify by fangchen end
......................
return abortLaunch(state);
}

2、实现某个单独App 后台启动不检查
这里再次看日志打印[如上] 和 实际代码:先分析代码: 可以看到 需要启动的类在Intent ,又在 BalState 参数封装着的。
找到日志打印地方 和 日志展示,如下:BackgroundActivityStartController 类, abortLaunch 方法



三、需求实现-思路
1、搜索关键日志-找到关键的类BackgroundActivityStartController
如上,无法在后台App中打开第三方应用,报错日志再次提出来,如下:Background activity launch blocked! [

搜索关键日志,在源码周公搜索:grep -rn "Background activity launch blocked" ,结果如下: 找到 BackgroundActivityStartController

2、通过类-方法找到核心代码-checkBackgroundActivityStart
如上找到 BackgroundActivityStartController 日志打印地方:abortLaunch 方法,搜索abortLaunch 方法,发现都是在checkBackgroundActivityStart 方法中调用的
3、通过搜索关键方法checkBackgroundActivityStart-找到使用过的类
搜索大法:grep -rn "checkBackgroundActivityStart(",找到几个调用的类,如下:

涉及到的类路径,小结如下:
java
/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
/frameworks/base/services/core/java/com/android/server/wm/AppTaskImpl.java
/frameworks/base/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
4、分析各个类是如何调用方法-checkBackgroundActivityStart
ActivityStarter-checkBackgroundActivityStart 类方法调用
这里有个提示 ,如果: balVerdict = BalVerdict.ALLOW_BY_DEFAULT,注释:Sets ALLOW_BY_DEFAULT as default value as the activity launch will be aborted anyway. ,如果设置当前默认DEFAULT 值,那么将永远不再aborted
所以: 这里大胆猜测,让 checkBackgroundActivityStart 方法,返回 BalVerdict.ALLOW_BY_DEFAULT 即可。

再看看这个DEFAULT 是啥子,如下定义:就是一个静态对象,所以 直接调用即可。

ActivityTaskManagerService-checkBackgroundActivityStart 类方法调用
代码如下,解决方案,把相关代码屏蔽掉:

AppTaskImpl-checkBackgroundActivityStart 类方法调用
代码如下,解决方案,把相关代码屏蔽掉:就是不要执行相关逻辑检查

解决方案小结-BackgroundActivityStartController 类进行默认值即可
如上相关源码分析,最终解决方案直接在BackgroundActivityStartController 类中,创建BalVerdict 对象的方法checkBackgroundActivityStart,直接返回:BalVerdict.ALLOW_BY_DEFAULT,如下:

四、知识点扩展
BackgroundActivityStartController 初识
看类注释和方法:这个类其实就是启动Activity 前各种权限检查。 这里不仅仅是当前需求的检查,是否BalState 允许,还有是否HOME APP、uid/systemUid 等

实现类似功能,您需要使用替代方案。以下是几种主流方法的对比
| 方法 | 核心原理 | 适用场景与关键要求 | 备注 |
|---|---|---|---|
| 1. 前台服务 + 通知 | 启动一个前台服务,并显示一个带setFullScreenIntent的通知。系统在特定条件(如通知触发)下允许全屏启动。 | 用户必须授予 USE_FULL_SCREEN_INTENT 权限。适用于来电、闹钟等需要强用户感知的场景。 | 官方推荐方案,兼容性最好。 |
| 2. 引导用户开启特定权限 | 引导用户在系统设置中手动开启针对本应用的"后台弹出界面"或"显示在其他应用上层"等权限。 | 因设备厂商(小米、华为等)而异,权限名称和入口不统一,需要单独适配。 | 在非原生系统上常用,但对用户体验有干扰。 |
| 3. 在系统允许的特殊情况下启动 | 利用系统允许后台启动Activity的少数例外情况,如来电、闹钟、地理围栏、用户点击通知/PendingIntent等。 | 严格受限于系统规定的场景,无法由应用任意触发。 | 最合规的方案,但功能受限,非通用解法。 |
总结
- 这里解决了一个Android15 版本后台启动App 问题,日常如果用HOME程序启动、Framework 层启动不会有问题,但是如果是第三方App后台会有问题
- 重点是分析问题思想步骤,现在也不能说对
BackgroundActivityStartController了解多少,但核心问题是分析问题、并解决问题思路很重要。 - 这里为了解决 静默安装最后启动的一个步骤,方便静默安装更深的理解,后续再写一下笔记,方便查阅。