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.