【问题标题】:Proguard breaking audio file in assets or rawProguard 破坏资产或原始音频文件
【发布时间】:2014-02-21 19:35:25
【问题描述】:

我有一个使用 MediaPlayer 播放哔哔声的活动,它可以正常工作,并且即使在 proguarded 生产版本中也可以正常工作。在最新版本中,它现在突然崩溃了

Caused by: android.content.res.Resources$NotFoundException: File res/raw/beep.ogg from drawable resource ID #0x7f060000
at android.content.res.Resources.openRawResourceFd(Resources.java:994)
at android.media.MediaPlayer.create(MediaPlayer.java:855)
at com.digikey.mobile.activity.CaptureActivity.onCreate(SourceFile:135)
at android.app.Activity.performCreate(Activity.java:5206)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
... 11 more
Caused by: java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
at android.content.res.AssetManager.openNonAssetFdNative(Native Method)
at android.content.res.AssetManager.openNonAssetFd(AssetManager.java:428)
at android.content.res.Resources.openRawResourceFd(Resources.java:991)
... 16 more

我尝试了多种不同的加载和播放声音的方法,包括将其存储在资产中而不是原始 res/raw 中,当我在未经过保护的应用程序中使用它们时它们都可以工作,但它们都在发布时失败proguarded/zipaligned 和签名的版本。

我的 proguard 文件相当大,它确实包含经常建议的修复

-keepclassmembers class **.R$* {public static <fields>;}
-keep class **.R$*

以前有人有任何想法或遇到过类似的事情吗?

更新:我也尝试过使用 mp3 文件,但也有同样的问题。

更新 2:有趣的是,这条消息似乎需要很长时间(接近 1 秒)才能崩溃。好像它正在搜索或处理某些文件或其他东西..但是文件真的很小所以很奇怪。

【问题讨论】:

  • 这个文件有多大?另外,您是否在某些自定义构建脚本中摆弄过任何 aapt 开关?
  • 它非常小,我没有摆弄过 aapt 开关。但正如你想象的那样,我正在使用 Android Maven 插件。是否有任何可能有用的 aapt 开关?
  • 更多的是感觉这个文件在不应该压缩的时候被压缩了。 aapt 以前总是知道.ogg 文件并且没有压缩它们。我不知道 ProGuard/zipalign 为什么/如何影响它。如果您使用 DexGuard 而不是 ProGuard,则例外情况,因为我不知道他们的资源加密可能会对事情产生什么影响。
  • 顺便说一句,mp3 文件也出现了同样的问题。并且只使用 ProGuard。

标签: android android-mediaplayer proguard assets android-maven-plugin


【解决方案1】:

我有一个类似的案例,我的应用在 ProGuard 之后退化(即使在调试中?虽然我已经明确将其关闭)。

08-30 22:10:32.360 561-18619/? E/FileSource: Failed to open file 'android.resource://com.mycompany.myapp/2131230720'. (No such file or directory)

最终我不得不在自定义要保留的资源

下按照here的建议添加keep.xml文件

类似 (@ /res/raw/keep.xml):

    <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@raw/*">
</resources>

您当然可以更明确地设置它,但我的 RAW 文件夹中只有 mp3。

我的unzip -lv app-release.apk 将我的 mp3 文件显示为:

0 Stored 0 0% 00-00-1980 00:00 00000000 res/raw/audio.mp3

这是奇数(0 字节?!)。

【讨论】:

    【解决方案2】:

    该错误表明 zip 条目 beep.ogg 被压缩,而它不应该被压缩。

    可以选择压缩 zip 文件中的各个条目。这种压缩通常对读取 zip 文件的应用程序是透明的。但是,Android 直接访问某些类型的文件(如 .ogg 和 .mp3),无需解压,只有在未压缩的情况下才有效。

    你可以看到哪些条目被压缩了

    unzip -lv MyApplication.apk
    

    在“方法”列中,“Defl”表示已压缩,“Stored”表示未压缩。

    ProGuard 不会执行 apk 文件的最终打包——aapt、apkbuilder、jarsigner、zipalign 和可能的后处理步骤会执行。在适当的阶段,他们应该不压缩 .ogg 和 .mp3 文件。您可能需要在 Maven 构建过程中检查它们的集成。

    DexGuard 偶尔会执行最终打包。它有一个选项 -dontcompress 来控制哪些文件或文件类型未压缩。默认配置未压缩 .ogg 和 .mp3 文件。

    (我是 ProGuard 和 DexGuard 的开发者)

    Manfred Moser 更新:

    这确实是问题所在。事实证明,这与 proguard 集成或 Android Maven 插件无关。问题是由我使用的 Maven Jarsigner Plugin 配置引起的。我已将 removeExistingSignatures 设置为 true,这不是默认值,并导致存档中的所有文件都被压缩。我认为这是现阶段 jarsigner 插件的一个奇怪错误。在任何情况下...默认配置是将此参数设置为 false 所以没有人应该有任何问题...除非您像我一样将其设置为 true ;-)

    【讨论】:

    • 感谢您回答埃里克。我将不得不进一步调查。 PS 我当然知道你是 ProGuard 的作者 ;-)
    • 哇...难以置信。我做了检查,现在似乎所有内容都被压缩了。这可能是我管理的 Android Maven 插件中的一些回归,所以我现在要去寻找错误 ;-) 非常感谢 Eric。
    • 为了其他人的利益,我正在使用 3.8.2 的 Android Maven 插件。一旦我找出问题,我会在这里和邮件列表发布。
    • Proguard 混淆了资产文件夹下的我的 db 文件。你能给我任何方法来避免资产的文件混淆吗?或其他阻止我的资产文件夹保护的东西。
    • 通过从 proguard 中排除模型类来修复。
    【解决方案3】:

    我觉得奇怪的是它告诉你这是一个可绘制资源:

    来自可绘制资源 ID 的文件 res/raw/beep.ogg

    我认为你需要告诉它也保留 R 类。这是我在一个应用程序中使用的,它还从原始加载 .ogg 文件。

    -keep class *.R
    
    -keepclasseswithmembers class **.R$* {
        public static <fields>;
    }
    

    【讨论】:

    • 这已经像您在问题中看到的那样进行了配置,是的..错误消息很奇怪。
    • 不,这个配置和你的不一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多