android obb 文件不是标准 zip,c# 无法直接用 ziparchive 解压,因其含 48 字节特有头部且可能 aes 加密;非加密 obb 可跳过头部后解压,加密 obb 必须通过 android assetmanager 访问,且需确保签名、命名与挂载状态正确。

Android OBB 文件不是普通 ZIP,C# 不能直接用 ZipArchive 解压
Android OBB(Opaque Binary Blob)是 Google 定义的加密/签名封装格式,哪怕后缀是 .obb,它也不是标准 ZIP。用 ZipArchive 或 SharpZipLib 直接打开会报 InvalidDataException 或解压出乱码文件——因为头部有 48 字节 OBB 特定头(含 magic、version、salt、signature 等),且资源部分可能被 AES 加密(尤其 Play 商店下发的 OBB)。
实操建议:
- 先用十六进制编辑器(如 HxD)打开 OBB 文件,检查前 4 字节是否为
0x4F424200(即 "OBB\0"),确认是合法 OBB;如果不是,可能是重命名的 ZIP,可直接用ZipArchive - 若头正确但解压失败,大概率是加密 OBB —— 这类文件**无法在 C# 中直接解密读取**,因为密钥由 Android 系统在运行时通过 APK 签名动态生成,不暴露给外部进程
- 非加密 OBB(常见于本地打包、测试环境)可跳过头直接解压:用
FileStream跳过前 48 字节,再传给ZipArchive
Unity IL2CPP 环境下读取 OBB 资源需绕过 .NET 标准库限制
如果你在 Unity(尤其是 Android 平台启用 IL2CPP 后)尝试用 C# 读 OBB,会发现 System.IO.Compression 在某些 Android SDK 版本上不可用,或 FileStream 对 /android_asset/ 外路径权限拒绝 —— 因为 OBB 实际挂载在 /sdcard/Android/obb/[package.name]/,而该路径受 Android 存储访问框架(SAF)或 Scoped Storage 限制。
实操建议:
- 不要硬编码路径,用 Unity 的
Application.streamingAssetsPath+AndroidJavaClass调用Context.getObbDir()获取真实挂载点 - 对非加密 OBB,跳过头后用
MemoryStream加载剩余字节再构造ZipArchive,避免FileStream权限问题 - 若目标是读取纹理/音频等资源,优先走 Unity 的
WWW或UnityWebRequest加载jar://协议路径(如jar:file:///sdcard/Android/obb/com.example.app/main.1.com.example.app.obb!/assets/icon.png),这是 Android 原生支持的方式
AndroidJavaObject 调用 AssetManager 是最稳的 OBB 资源读取方式
Android 系统本身通过 AssetManager 挂载并透明解密 OBB,C# 层调用它,等于复用系统能力,不碰加密逻辑、不处理头结构、不依赖 ZIP 库兼容性。
实操建议:
- 在 Unity C# 中用
AndroidJavaObject获取当前Activity的getAssets(),然后调用openFd("path/in/obb")(路径相对于 OBB 内根目录) - 注意:
openFd返回的是AssetFileDescriptor,需用getFileDescriptor()+getStartOffset()+getLength()构造InputStream,再转成 byte[] - 路径必须全小写、无中文、不含
..,否则IOException: Asset not found;OBB 内资源路径区分大小写,和 Windows 文件系统习惯不同 - 该方式只适用于 OBB 已被系统成功挂载的情况(即
PackageManager.getPackageInfo().applicationInfo.splitNames包含对应 OBB 名称)
调试时别忽略 OBB 挂载状态和签名匹配
很多“读不到文件”问题根本不在 C# 代码,而在 OBB 没挂载成功或签名不一致。Android 要求 OBB 文件名必须是 main.<code>versionCode.packageName.obb,且 APK 和 OBB 必须用同一密钥签名,否则系统拒绝挂载 —— 此时 getObbDir() 返回 null,AssetManager 也找不到任何 OBB 内资源。
实操建议:
- adb shell 进入设备,执行
ls -l /sdcard/Android/obb/确认 OBB 文件存在且权限为-rw-rw---- - 用
adb shell dumpsys package <package_name></package_name>查看obbs:字段是否列出对应 OBB,以及signatures:是否与 APK 一致 - 开发阶段用
adb install -r -t your_app.apk和adb push main.1.com.example.app.obb /sdcard/Android/obb/com.example.app/手动部署,确保顺序和命名零误差
真正卡住的地方往往不是解压算法,而是 OBB 没被系统认作“自己人”。签名、命名、挂载时机,三者错一个,后面所有 C# 代码都白忙。










