Proguard打破资产或原始的音频文件

时间:2014-01-29 19:21:35

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

我有一项活动,使用MediaPlayer发出哔哔声,工作正常,即使在生产版本中也能正常工作。随着最新发布,它现在突然崩溃

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中,当我在未经过编程的应用程序中使用时它们都可以工作但是它们都在发布时失败了已编程/已对其进行签名和签名的版本。

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

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

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

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

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

3 个答案:

答案 0 :(得分:12)

该错误表明压缩条目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插件配置引起的。我将removeExistingSignatures设置为true,这不是默认值,导致归档中的所有文件都被压缩。在这个阶段,我认为这是jarsigner插件的一个奇怪的错误。在任何情况下......默认配置是将此参数设置为false,这样任何人都不应该有任何问题...除非您将其设置为true,就像我一样;-)

答案 1 :(得分:3)

我有一个类似的情况,我的应用程序在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)

最后,我必须在自定义要保留的资源

下添加keep.xml文件,如建议的here

有类似的东西(@ /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 :(得分:1)

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

  

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

我认为你需要告诉它还要保留R类。这是我在一个应用程序中使用的,它也从raw。

加载.ogg文件
-keep class *.R

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