问题
I am loading mp3 files to play in an Android game based on AndEngine. When I package my game as an APK, mp3 audio in the assets folder throws the error "can not be opened as a file descriptor; it is probably compressed."
However, when I run the game using the run > button in Eclipse (MOTODEV Studio 3.0.2), the app is packaged, deployed to a device and the game has sound. Works perfectly on a device.
If I package the app using "Export Android Application", which creates a signed APK ready to deploy in the Android Market and then install that APK on a device, the game functions perfectly except the sound doesn't play and throws the following error:
> 02-02 20:42:31.433: E/AndEngine(1925): AndEngine 02-02 20:42:31.433:
> E/AndEngine(1925): java.io.FileNotFoundException: This file can not be
> opened as a file descriptor; it is probably compressed 02-02
> 20:42:31.433: E/AndEngine(1925): at
> android.content.res.AssetManager.openAssetFd(Native Method) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> android.content.res.AssetManager.openFd(AssetManager.java:330) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> org.anddev.andengine.audio.music.MusicFactory.createMusicFromAsset(MusicFactory.java:75)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> com.snoffleware.android.roshambomb.PlayLevelActivity.onLoadResources(PlayLevelActivity.java:255)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> org.anddev.andengine.ui.activity.BaseGameActivity.doResume(BaseGameActivity.java:168)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> org.anddev.andengine.ui.activity.BaseGameActivity.onWindowFocusChanged(BaseGameActivity.java:85)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> com.android.internal.policy.impl.PhoneWindow$DecorView.onWindowFocusChanged(PhoneWindow.java:2012)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> android.view.View.dispatchWindowFocusChanged(View.java:3924) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> android.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:659)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> android.view.ViewRoot.handleMessage(ViewRoot.java:1968) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> android.os.Handler.dispatchMessage(Handler.java:99) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> android.os.Looper.loop(Looper.java:130) 02-02 20:42:31.433:
> E/AndEngine(1925): at
> android.app.ActivityThread.main(ActivityThread.java:3683) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> java.lang.reflect.Method.invokeNative(Native Method) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> java.lang.reflect.Method.invoke(Method.java:507) 02-02 20:42:31.433:
> E/AndEngine(1925): at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:850)
> 02-02 20:42:31.433: E/AndEngine(1925): at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 02-02
> 20:42:31.433: E/AndEngine(1925): at
> dalvik.system.NativeStart.main(Native Method)
I have tried deploying the APK to a Kindle Fire, Motorolo Droid and Motorolo Droid 2 Global. The game works on all of these devices but without sound.
The audio is stored as mp3 files in a folder under Assets called Sound. An example filename is "music-a-nebulas-promise.mp3". I have tried renaming one of the files, "simple.mp3", worried that dashes are not allowed in the naming but it didn't make any difference.
The code that loads the audio is as follows and please note, when I run the application using MOTODEV Studio the sound is played back perfectly. It is only when I try to export the app as an APK and install it that I get the aforementioned error regarding compression:
SoundFactory.setAssetBasePath("sound/");
MusicFactory.setAssetBasePath("sound/");
try {
if (!level.getMusic().equals("")) {
backgroundMusic = MusicFactory.createMusicFromAsset(this.mEngine.getMusicManager(), this, level.getMusic());
backgroundMusic.setLooping(true);
} else {
// music is turned on but there is no music file -- protect
// against crash
isMusic = false;
}
} catch (final IOException e) {
Debug.e(e);
// music is turned on but the music file was not found -- protect
// against crash
isMusic = false;
}
try {
collisionSound = SoundFactory.createSoundFromAsset(this.mEngine.getSoundManager(), this, "sfx-collision.mp3");
portalSound = SoundFactory.createSoundFromAsset(this.mEngine.getSoundManager(), this, "sfx-portal-activated.mp3");
winningSound = SoundFactory.createSoundFromAsset(this.mEngine.getSoundManager(), this, "sfx-winning.mp3");
losingSound = SoundFactory.createSoundFromAsset(this.mEngine.getSoundManager(), this, "sfx-losing.mp3");
} catch (final IOException e) {
Debug.e(e);
isSound = false;
}
The AndEngine method that initializes the audio:
public static Music createMusicFromAsset(final MusicManager pMusicManager, final Context pContext, final String pAssetPath) throws IOException {
final MediaPlayer mediaPlayer = new MediaPlayer();
final AssetFileDescriptor assetFileDescritor = pContext.getAssets().openFd(MusicFactory.sAssetBasePath + pAssetPath);
mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());
mediaPlayer.prepare();
final Music music = new Music(pMusicManager, mediaPlayer);
pMusicManager.add(music);
return music;
}
I have tried converting the mp3 files to both ogg and wav. Both ogg and wav throw the same error as mp3 files.
Since the game sound works when I run or debug it using Eclipse that seems to leave the final export step as the culprit. I have seen posts that suggest controlling the build process to prevent compression of files in the Assets folder but I'm not sure how to accomplish that from MOTODEV Studio.
I have also seen posts that suggest storing the mp3 audio in the res/raw folder but since audio in the Assets folder plays when run from Eclipse, it seems that it should also work when packaged as an APK.
Version details
I am current targeting Android SDK level 13 (Android 3.2) using Android SDK Tools v.15 and Android SDK Platform-tools v.9 -- so thinking it might have something to do with the SDK tools, I updated the SDK to v.16 and the platform tools to v.10 but that did not fix the problem.
回答1:
The reason your app works when run from within Eclipse (or MOTODEV Studio) on debug is it is not going through the full path that occurs on export. I don't have the SDK build process chart in front of me, but there is one out there. I'm sure a bit of probing the Ant scripts will expose what is going on.
I say this because there's nothing MOTODEV Studio does different from Eclipse wrt the build process. While there is a separate "Export with MOTODEV Studio" menu item, all that's happening there is a couple of fields are being pre-populated with information as a convenience and access to your certificate store. Otherwise, the export process is the same as Eclipse+ADT (which is what it is).
回答2:
The problem seems to be related to the mediaPlayer.prepare() method in the MusicFactory.java of AndEngine. I've just comment out line 91 (as in the following code snipet) and the MP3 resource was loaded without any exceptions. I think the same can be done with the asset loading method.
public static Music createMusicFromResource(final MusicManager pMusicManager, final Context pContext, final int pMusicResID) throws IOException {
final MediaPlayer mediaPlayer = MediaPlayer.create(pContext, pMusicResID);
**//mediaPlayer.prepare();**
final Music music = new Music(pMusicManager, mediaPlayer);
pMusicManager.add(music);
return music;
}
回答3:
You could put the audio-files in the "RAW" folder and play them via:
mPlayer2= MediaPlayer.create(this, R.raw.MUSICTAG);
mPlayer2.start();
This way, there should be no problems with compression.
来源:https://stackoverflow.com/questions/9124378/mp3-audio-in-the-android-assets-folder-fails-to-play-from-a-signed-and-zip-align