为什么 MediaPlayer 不能正确播放音频?

Why MediaPlayer does not play the audio correctly?

我在图像库中工作,其中包含用户在屏幕上查看的内容的发音方式的音频,通过屏幕中也包含的按钮执行。

以下代码有效,但有时音频在完成再现之前被剪切,问题是我没有收到任何错误日志。

View.OnClickListener eventoPlay = (v) → {
        @Override
        public void onClick(View v) {
            btnPlaySound.setClickable(false);
            try{
                Uri myUri = Uri.parse(urlroot + urlAudio); //global variables by current image
                final MediaPlayer mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setDataSource(getApplicationContext(), myUri);
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mediaPlayer.start();
                    }
                });

                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mp.release();
                        btnPlaySound.setClickable(true);
                    }
                });
                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        btnPlaySound.setClickable(true);
                        Log.e("Error in media player", String.valueOf(what));
                        Log.e("Error in media player", String.valueOf(extra));
                        return false;
                    }
                });
                mediaPlayer.prepareAsync();
            }catch (Exception e){
                e.printStackTrace();
                btnPlaySound.setClickable(true);
            }
        }
    };
btnPlaySound.setOnClickListener(eventoPlay);
btnPlaySound.performClick();

这些是我调试过的场景:

-setOnPreparedListener() 始终自然地呼叫(音频始终开始播放)。

-setOnCompletionListener() 仅在音频播放结束时调用(如果音频未被剪切)。

-setOnErrorListener()无论音频是否被剪切,它都不会调用

-catch无论是否剪切音频,此块也永远不会执行。

我在 Samsung tab S3、Samsgung tab E、Samsung tab A、Alcatel A3、小米 MiA2、Swissmobility 等设备上进行了测试。 在最强大的设备中发生的频率较低。但我希望这种故障永远不会发生。

Tnks.

您可能希望确保 btnPlaySound.setClickable(true) 在 UI 线程上被调用。它可能会导致错误。此外,媒体播放器可能会在完成之前收集垃圾,并保留对 MediaPlayer 的(强)引用以防止垃圾收集。

试试这个来测试它是否被垃圾收集:

View.OnClickListener eventoPlay = (v) → {
        @Override
        public void onClick(View v) {
            btnPlaySound.setClickable(false);
            try{
                Uri myUri = Uri.parse(urlroot + urlAudio); //global variables by current image

                // KEEP A STRONG REFERENCE
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setDataSource(getApplicationContext(), myUri);
                mediaPlayer.setLooping(false);
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mp.start();
                    }
                });

                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mp.release();
                        btnPlaySound.setClickable(true);
                    }
                });
                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        mp.release();
                        btnPlaySound.setClickable(true);
                        Log.e("Error in media player", String.valueOf(what));
                        Log.e("Error in media player", String.valueOf(extra));
                        return false;
                    }
                });
                mediaPlayer.prepareAsync();
            }catch (Exception e){
                e.printStackTrace();
                btnPlaySound.setClickable(true);
            }
        }
    };
btnPlaySound.setOnClickListener(eventoPlay);
btnPlaySound.performClick();