Search code examples
androidandroid-mediaplayer

Why MediaPlayer does not play the audio correctly?


I am working in a gallery of images that include an audio of how the things that the user is viewing on the screen are pronounced, which is executed with a button also included in the screen.

The following code works, but sometimes the audio is cut before it finishes reproducing, the problem with this is that I am not receiving any error log.

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();

These are the scenarios that I have debugged:

-setOnPreparedListener() call naturally, always (the audio starts playing always).

-setOnCompletionListener() call only if the audio was finished playing (if the audio was not cut).

-setOnErrorListener() It never call, regardless of whether the audio is cut.

-catch This block is never executed either, regardless of whether the audio is cut.

I tested in devices like Samsung tab S3, Samsgung tab E, Samsung tab A, Alcatel A3, Xiaomi MiA2, Swissmobility. In the most powerful devices happens less frequently. but I want this failure never to occur.

Tnks.


Solution

  • You may want to ensure btnPlaySound.setClickable(true) is being called on the UI thread. It could be causing an error. Also the media player may be getting garbage collected before finishing keep a (strong) reference to the MediaPlayer to prevent garbage collection.

    Try this to test if it being garbage collected:

    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();