
Android 应用从 APK 切换为 AAB 发布后,内置的 AMR 格式音频文件因被自动压缩而无法加载,引发 Resources$NotFoundException;通过配置 aaptOptions.noCompress 显式排除 AMR 文件可彻底解决。
Android 应用从 APK 切换为 AAB 发布后,内置的 AMR 格式音频文件因被自动压缩而无法加载,引发 `Resources$NotFoundException`;通过配置 `aaptOptions.noCompress` 显式排除 AMR 文件可彻底解决。
在 Android 构建流程中,AAB(Android App Bundle)格式默认启用更激进的资源压缩策略,以减小下载体积。与传统 APK 不同,AAB 会通过 aapt2 对 res/ 目录下的二进制资源(如 .amr、.ogg、.webp 等)进行自动压缩——即使这些文件本身已是压缩格式。当 AMR 音频被错误地二次压缩后,Resources.openRawResource() 在运行时无法正确解码原始字节流,最终抛出类似以下异常:
android.content.res.Resources$NotFoundException: File res/raw/s003001.amr from resource ID #0x7f0a0126
该问题具有典型性:仅在 AAB 安装包(尤其是经 Google Play 动态分发后生成的优化 APK)中复现,而本地 APK 安装正常,容易误判为签名或权限问题。
✅ 根本解决方法:在模块级 build.gradle(通常为 app/build.gradle)的 android { } 块内,显式声明 AMR 文件不参与压缩:
android {
// ... 其他配置(compileSdk, defaultConfig 等)
aaptOptions {
noCompress "amr" // 关键:阻止 .amr 文件被压缩
// 如需支持其他易出错格式,可追加:
// noCompress "ogg", "wav", "webp"
}
}⚠️ 注意事项:
- noCompress 接收的是文件扩展名(不含点),如 "amr" 而非 ".amr";
- 修改后必须执行 Clean Project → Rebuild Project,确保 R.java 和资源索引重新生成;
- 若音频存于 assets/ 目录而非 res/raw/,则需改用 AssetManager.openFd() 加载,并注意 AMR 解码兼容性(建议优先使用 MediaPlayer 或 ExoPlayer);
- Google Play 后台对 AAB 的资源分发不受此配置影响,noCompress 仅作用于构建时的资源打包阶段,不会增大用户实际下载体积(Play 仍按设备特性下发最优资源)。
? 验证方式:
构建 AAB 后,可通过 bundletool 解包检查资源是否未压缩:
bundletool extract --bundle=app.aab --output=extracted/ # 检查 extracted/base/res/raw/s003001.amr 是否为原始二进制(非 ZIP 压缩流)
总结:AAB 的资源压缩优化是一把双刃剑。对于已压缩的音频格式(AMR、MP3、AAC 等),务必通过 aaptOptions.noCompress 显式豁免,这是保障媒体资源稳定加载的必要实践。