媒体播放器切断声音太快了

我有两个设备可以testing我的游戏:美国Celluar手机(SCH-R880)和Kindle Fire,Kindle Fire比手机function强大得多。

我有几个短(小于或大约1秒)的音效。 为了节省内存,我加载,播放和释放这些音效。 在他们打电话(主要)如预期。 然而,在Kindle Fire上,它们被缩短了。 真的很短的声音很快被切断了,我什么都没听到。 然而,在安装程序中加载并保持的那些可以很好地工作。

任何人都知道这里发生了什么? 我是不是很快地发布我的媒体? 下面是这个的一个例子。 在电话里,我听到“二级!” 但在Kindle上,我听到像“Lev tw”这样的东西。

mpNum = null; try { switch (level) { case 2: mpNum = MediaPlayer.create(contxt, R.raw.l2); break; case 3: mpNum = MediaPlayer.create(contxt, R.raw.l3); break; case 4: mpNum = MediaPlayer.create(contxt, R.raw.l4); break; case 5: mpNum = MediaPlayer.create(contxt, R.raw.l5); break; case 6: mpNum = MediaPlayer.create(contxt, R.raw.l6); break; case 7: mpNum = MediaPlayer.create(contxt, R.raw.l7); break; case 8: mpNum = MediaPlayer.create(contxt, R.raw.l8); break; default: return; } MediaPlayer vLevel = MediaPlayer.create(contxt, R.raw.level); vLevel.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { mp.start(); } }); vLevel.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mpl) { mpNum.start(); mpl.release(); } }); mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mp.release(); } }); } catch (Exception e) {} 

为了试图解决这个问题,我尝试了SoundPool,但是它不起作用; 我什么也没听到。 以下是我尝试使用SoundPool播放音乐的方法:

 SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100); soundPool.load(contxt, R.raw.song2, 1); AudioManager mgr = (AudioManager)contxt.getSystemService(Context.AUDIO_SERVICE); float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC); float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); float volume = streamVolumeMax; soundPool.play(1, volume, volume, 1, 5, 2); 

UPDATE

我注意到当一个声音应该播放(但不)有这个错误出现:

 AudioPolicyManager: stopOutput() oldDevice 2 AudioPolicyManager: [getDeviceForStrategy] strategy : 0,forceUse(0) 

Solutions Collecting From Web of "媒体播放器切断声音太快了"

我有同样的问题,这确实是一个垃圾回收问题! 如果您将媒体播放器的实例分配给某个方法中的某个局部variables,那么在离开该方法后该实例不再存在,因此GC可以随时将其随机删除。

为了避免这种情况,您至less需要在其他地方保留一个指向实例的指针。 我创build了一个静态集来保存所有的指针,如下所示:

 private static Set<MediaPlayer> activePlayers = new HashSet<MediaPlayer>(); 

然后创build媒体播放器如下:

 MediaPlayer player = MediaPlayer.create(context, context.getResources().getIdentifier(id, "raw", pkg)); activePlayers.add(player); player.setOnCompletionListener(releaseOnFinishListener); player.start(); 

其中releaseOnFinishListener是一个监听器,可以像您一样在完成时释放媒体播放器,但也会从activePlayers集中删除指针:

 MediaPlayer.OnCompletionListener releaseOnFinishListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mp.release(); activePlayers.remove(mp); } }; 

我希望这可以帮助你。

我已经读过SoundPool类比MediaPlayer更适合这样的简短声音,但这可能不是问题。 ( 这里是一个SoundPool例子的链接)。

你也可以发布你的点击处理程序的代码?

此外,我build议,而不是释放和重新获得MediaPlayer实例,使用一个MediaPlayer实例,只要按照典型的重置(),setDataSource(),准备(),开始()顺序,只要你需要重用。 每次构build一个新的实例会更有效率。 即:

 MediaPlayer mp = new MediaPlayer(); AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.sound1); mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(); mp.prepare(); mp.start(); //to reuse mp.reset(); afd = getResources().openRawResourceFd(R.raw.sound2); mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(); mp.prepare(); mp.start(); 

以及我在一个项目中有同样的问题,是因为在KindleFire的声音切割完成之前,以解决这个问题(释放),我在版本中添加了一个延迟:

  mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { // Add a handler delay new Timer().schedule(new TimerTask() { @Override public void run() { mp.release(); } }, DELAY_TIME); } }); 

这不是最好的解决scheme,但我认为这可能会帮助你。

这很奇怪,不是一个很好的解决方法,但是我迄今为止唯一find的解决scheme。 如果我删除mp.setOnPreparedListenermp.setOnCompletionListener ,只是有mp.start() ,它的工作原理。

我有这个问题,并解决它使我的MediaPlayer对象私人,所以垃圾收集器不清理实例。 希望它可以帮助别人!