Search code examples
androidandroid-mediaplayergalaxy-tab

MediaPlayer freezes instead of looping video on Android 4.4


I am having a problem with video playback on Android 4.4 on the Galaxy Tab 3. The issue did not occur with the previous Android version 4.2.

The issue

I am playing a video in a loop. This worked very well for all users, until the Tab 3 got updated to Android 4.4. Since then the video freezes after the first loop (it gets stuck on the first frame of the video to be precise).

I can reproduce that behaviour, and at the moment the video freezes my LogCat starts getting full with the following output:

16:25:25.239  14589-14601/my.app V/MediaPlayer? back from callback
16:25:25.499  14589-14686/my.app V/MediaPlayer? message received msg=7, ext1=0, ext2=0
16:25:25.499  14589-14686/my.app V/MediaPlayer? unrecognized message: (7, 0, 0)
16:25:25.499  14589-14686/my.app V/MediaPlayer? callback application
16:25:25.499  14589-14686/my.app V/MediaPlayer? back from callback
16:25:25.519  14589-14602/my.app V/MediaPlayer? message received msg=4, ext1=0, ext2=0
16:25:25.519  14589-14602/my.app V/MediaPlayer? Received seek complete
16:25:25.519  14589-14602/my.app V/MediaPlayer? All seeks complete - return to regularly scheduled program
16:25:25.519  14589-14602/my.app V/MediaPlayer? callback application
16:25:25.519  14589-14602/my.app V/MediaPlayer? back from callback
16:25:25.519  14589-14601/my.app V/MediaPlayer? message received msg=6, ext1=0, ext2=0
16:25:25.519  14589-14601/my.app V/MediaPlayer? Received MEDIA_STARTED
16:25:25.519  14589-14601/my.app V/MediaPlayer? callback application
16:25:25.519  14589-14601/my.app V/MediaPlayer? back from callback
16:25:25.789  14589-14686/my.app V/MediaPlayer? message received msg=7, ext1=0, ext2=0
16:25:25.789  14589-14686/my.app V/MediaPlayer? unrecognized message: (7, 0, 0)
16:25:25.789  14589-14686/my.app V/MediaPlayer? callback application
16:25:25.789  14589-14686/my.app V/MediaPlayer? back from callback
16:25:25.809  14589-14602/my.app V/MediaPlayer? message received msg=4, ext1=0, ext2=0
16:25:25.809  14589-14602/my.app V/MediaPlayer? Received seek complete

The code

The following (simplyfied) activity is supposed to play the video. MediaPlayer.OnErrorListener() and MediaPlayer.OnInfoListener() are never called.

public class VideoActivity extends Activity {

    private MediaPlayer mediaPlayer;
    private String videoPath = "some path obtained from the system";

    // [...]

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mediaPlayer = new MediaPlayer();
        startMovie();
    }

    private void startMovie(){

        mediaPlayer.stop();
        mediaPlayer.reset();
        mediaPlayer.setLooping(true);
        mediaPlayer.setDataSource(videoPath);
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
                mp.start();
                mp.seekTo(0);
            }
        });
        mediaPlayer.prepare();
    }

}

The video can be started several times with a different video file path during the lifetime of the activity, that's why I stop and reset the player before starting the movie.

So far the only solutions I found on the internet were to make sure the MediaPlayer is not collected by the GC (which I do by not making it a method-local object) and implement the WakeLock, which I also did without effect.

Can anyone please help me here and point me in the right direction? Thank you!


Solution

  • More a workaround than a solution, I ended up not looping the video using the setLooping method of MediaPlayer. Instead I am now restarting the video in the OnCompletion callback of MediaPlayer. After a lot of trying this was the only way I got it to work across all devices I am testing on.

    public class VideoActivity extends Activity {
    
        private MediaPlayer mediaPlayer;
        private String videoPath = "some path obtained from the system";
    
        // [...]
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mediaPlayer = new MediaPlayer();
            startMovie();
        }
    
        private void startMovie(){
    
            mediaPlayer.stop();
            mediaPlayer.reset();
            mediaPlayer.setDataSource(videoPath);
    
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
                    mp.start();
                    mp.seekTo(0);
                }
            });
    
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    startMovie();
                }
            });
    
            mediaPlayer.prepare();
        }
    
    }
    

    Still, if someone has a valid solution to that problem I will be happy to mark the corresponding answer as correct.