0

I'm building an application that among other things plays some audio files. Here is my code for doing so:

public void reproducirAudioSelect() {

        String audioPath = directorio1 + File.separator + getItemSeleccionado();
        try {
           // mediaplayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
            mediaplayer = new MediaPlayer();

            mediaplayer.setDataSource(audioPath);
            mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaplayer.setLooping(false);
            mediaplayer.prepare();
            mediaplayer.start();
            mediaplayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaplayer) {
                    Log.i("A", "onComplete hit");
                    mediaplayer.stop();
                    mediaplayer.release();
                }
            });

        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
        }

    }

There is no problem when I just try to play whichever song I choose. However, the song is played again and again. I just want them to be played once, and when the song is finished, stop. (Hence the use of the setOnCompletionListener(..)).

I've tried many different solutions to this problem. The most popular (https://stackoverflow.com/a/19555480/13127574) consists of placing the listener after the .start(). But it doesn't work for me. I can't see anything wrong in my code, after debugging. Simply, onCompletition is not triggered.

Logcat if that's of any help:

2020-12-28 13:14:57.677 3662-3662/com.example.a_2_b_a19manuelgp W/MediaPlayer: Use of stream types is deprecated for operations other than volume control 2020-12-28 13:14:57.677 3662-3662/com.example.a_2_b_a19manuelgp W/MediaPlayer: See the documentation of setAudioStreamType() for what to use instead with android.media.AudioAttributes to qualify your playback use case 2020-12-28 13:15:03.057 3662-3662/com.example.a_2_b_a19manuelgp W/2_b_a19manuelg: Accessing hidden method Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate; (light greylist, linking) 2020-12-28 13:15:03.553 3662-3707/com.example.a_2_b_a19manuelgp D/EGL_emulation: eglMakeCurrent: 0xefcc3580: ver 2 0 (tinfo 0xefc31ca0) 2020-12-28 13:15:03.562 3662-3662/com.example.a_2_b_a19manuelgp V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false 2020-12-28 13:15:03.563 3662-3662/com.example.a_2_b_a19manuelgp V/MediaPlayer: cleanDrmObj: mDrmObj=null mDrmSessionId=null

Zoe
  • 27,060
  • 21
  • 118
  • 148
Manuel
  • 127
  • 2
  • 11

1 Answers1

1

I think you want to use prepareAsync() along with setOnPreparedListener(), and set your listeners before calling prepareAsync, something like this:

String audioPath = directorio1 + File.separator + getItemSeleccionado();
try 
{
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(audioPath);
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
    {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer)
        {
            mediaPlayer.start();
        }
    };
            
    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
    {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) 
        {
            Log.i("A", "onComplete hit");
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    });

    mediaPlayer.setLooping (false);     
    mediaPlayer.prepareAsync();
    
} 
catch (Exception e) 
{
    Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
CSmith
  • 13,318
  • 3
  • 39
  • 42
  • Thanks for your help, but still not working. It is properly invoking the first listener, but not the second. I don't know why but apparently it never recieves the info that the audio was "completed". I have no idea what can be wrong. – Manuel Dec 29 '20 at 17:43
  • I have edited my answer, this code worked for me, including onCompletion being called, though its not clear how your mediaPlayer object is scoped from your example code. Is this code inside an Activity? – CSmith Dec 30 '20 at 12:15
  • Thanks for your time. Yes, it is inside an activity and it is a private field that I initialize in onCreate() (maybe your guesswork was that it was being garbage collected?) Yesterday I noticed something quite strange. First, If wiped data from the AVD, the code would work, but just once. After reinstalling the app, without the previous wiping, then the same problem would happen. Then, after working a little bit more on it, I noticed that if I was playing sounds recorded by me, those new recordings added would work! But the "old ones" wouldn't (1/2) – Manuel Dec 30 '20 at 16:16
  • (2/2) So.. I was copying a couple of audio files ("old ones") from Assets to the SD card before recording anyhting new. I think that after reinstalling, I was re-copying from Assets and messing things up. I just prevented this behaviour by checking if the content was already copied. Now, magically, the old/initial audio files are working just fine!. So my guess is that in the sucessive reinstallations, something strange was happening to the initial audio files that, when played, woulnd't allow them to reach its "completition". That would explain that the OnPrepare was being invoked but.. – Manuel Dec 30 '20 at 16:23
  • ... no OnCompletion. Again thanks for your time and tell me if this makes sense to you – Manuel Dec 30 '20 at 16:24
  • I used the exact code shown above, in an activity, but hard-coded an audio URL of https://www.kozco.com/tech/LRMonoPhased4.mp3 (a short test clip). I had this code in onStart(). It worked and the onCompletion function was called. Sorry I can't be of further help. – CSmith Dec 30 '20 at 18:52