You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Chromium 136至Bundle APK时PlaybackListenerService崩溃(dexPath==null)

Chromium 136 Bundle APK 崩溃问题排查与修复

问题描述

将项目升级至Chromium 136后,本地发布APK运行正常,但通过Play商店或bundletool安装的Bundle构建版本启动时崩溃,报错如下:

FATAL EXCEPTION: main 
java.lang.RuntimeException: Unable to create service org.chromium.chrome.browser.media.ui.ChromeMediaNotificationControllerServices$PlaybackListenerService: java.lang.NullPointerException: dexPath == null
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:5391)
    ...
Caused by: java.lang.NullPointerException: dexPath == null
    at dalvik.system.DexPathList.<init>(DexPathList.java:144)
    at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:160)
    at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:45)
    at org.chromium.base.BundleUtils.d(BundleUtils.java:62)
    at org.chromium.base.BundleUtils.g(BundleUtils.java:29)
    at org.chromium.base.BundleUtils.h(BundleUtils.java:26)
    at org.chromium.chrome.browser.base.SplitCompatUtils.loadClassAndAdjustContext(SplitCompatUtils.java:1)
    at org.chromium.chrome.browser.base.SplitCompatService.attachBaseContext(SplitCompatService.java:3)
    at android.app.Service.attach(Service.java:983)

已尝试的方案:

  • 在ProGuard/R8规则中保留相关服务实现类:
    -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.ChromeMediaNotificationControllerDelegate$PlaybackListenerServiceImpl { *; }
    -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.ChromeMediaNotificationControllerDelegate$PresentationListenerServiceImpl { *; }
    -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.ChromeMediaNotificationControllerDelegate$CastListenerServiceImpl { *; }
    
  • 强制BundleUtils.isBundle()返回false规避崩溃,但属于临时 workaround,可能破坏拆分逻辑:
    @CalledByNative
    public static boolean isBundle() {
        return false; // temporary workaround
    }
    

问题解答

1. 为何仅Bundle APK会出现dexPath == null错误,本地发布APK却正常?

普通发布APK是单包结构,所有Dex文件都打包在主APK中,类加载器可以直接获取明确的Dex路径,不需要处理动态模块的拆分逻辑。而Bundle APK采用**应用拆分(App Bundle)**机制,会将代码、资源拆分为多个动态模块,Chromium的SplitCompat框架会在运行时尝试加载对应模块的Dex文件。

Chromium 136的SplitCompat逻辑触发空指针的核心原因:

  • 动态模块的声明或打包配置错误,导致模块未被正确包含或安装;
  • BundleUtils中获取模块Dex路径的逻辑未处理模块未安装或路径不存在的场景;
  • Bundle安装时,动态模块的加载时机与服务启动时机不匹配,服务启动时模块尚未完成安装。

2. Chromium 136动态特性下SplitCompat崩溃的正确修复方案

方案1:修复BundleUtils中的Dex路径获取逻辑

修改org.chromium.base.BundleUtils中创建模块类加载器的代码,添加dexPath非空校验,避免空指针:

// 对应BundleUtils.d()方法的逻辑调整
public static ClassLoader createModuleClassLoader(String moduleName, Context context) {
    String dexPath = getModuleDexPath(moduleName, context);
    // 当dexPath为空时,回退到应用主类加载器
    if (dexPath == null) {
        return context.getClassLoader();
    }
    // 原有的类加载器创建逻辑
    return new PathClassLoader(dexPath, context.getClassLoader());
}

方案2:完善ProGuard/R8规则

除了保留服务实现类,还需要保留SplitCompat相关的核心类和方法,避免混淆导致逻辑异常:

// 保留BundleUtils核心方法
-keep class org.chromium.base.BundleUtils {
    *;
}
// 保留SplitCompat工具类与服务类
-keep class org.chromium.chrome.browser.base.SplitCompatUtils { *; }
-keep class org.chromium.chrome.browser.base.SplitCompatService { *; }
// 保留崩溃相关的服务类
-keep class org.chromium.chrome.browser.media.ui.ChromeMediaNotificationControllerServices$PlaybackListenerService { *; }

方案3:检查动态模块配置

确认项目中动态模块的声明正确:

  • 在settings.gradle中确保动态模块已被包含:
    include ':app', ':media_ui' // 假设media_ui是相关动态模块
    
  • 在主模块的build.gradle中声明动态特性依赖:
    android {
        dynamicFeatures = [':media_ui']
    }
    

方案4:调整SplitCompatService的模块加载逻辑

在SplitCompatService的attachBaseContext方法中,添加模块存在性校验,确保模块已安装后再加载类:

@Override
protected void attachBaseContext(Context base) {
    String moduleName = getModuleName(); // 根据服务所属模块获取名称
    if (BundleUtils.isModuleInstalled(moduleName, base)) {
        super.attachBaseContext(SplitCompatUtils.loadClassAndAdjustContext(base, getClass()));
    } else {
        super.attachBaseContext(base);
    }
}

内容的提问来源于stack exchange,提问作者Sanjay Bhalani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 09:34:52