Tofeeq Ahmad
Tofeeq Ahmad

Reputation: 11975

Media Control on Lock Screen like Google Play Music in android?

I had gone through Lock-screen Widget documentation, i implemented it but this is not what automatically place on main Lock Window. I searching for solution which provide Media Control over Main Lock-screen window (in Jelly Bean and above) like Google Play Music Application.

Have Look on Google Play Music Lock which obviously is not Lock Screen widget.

enter image description here

Upvotes: 10

Views: 17433

Answers (3)

Rahul Kamble
Rahul Kamble

Reputation: 340

If your media controls are working good in notification and media control is already displayed on lock screen but not functional then you can follow this code to start working of the media controls(Play, pause, next, previous) on lock screen :-

private MediaSessionCompat mMediaSessionCompat;  
private AudioManager audioManager;

Call below method in onCreate of your service class:

private void RegisterRemoteClient() {
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    assert audioManager != null;
    audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN);

    ComponentName mRemoteControlResponder = new ComponentName(getPackageName(),
            NotificationBroadcast.class.getName());


    Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
    mediaButtonIntent.setComponent(mRemoteControlResponder);

    mMediaSessionCompat = new MediaSessionCompat(getApplication(), "JairSession", mRemoteControlResponder, null);
    mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    PlaybackStateCompat playbackStateCompat = new PlaybackStateCompat.Builder()
            .setActions(
                    PlaybackStateCompat.ACTION_SEEK_TO |
                            PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                            PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
                            PlaybackStateCompat.ACTION_PLAY |
                            PlaybackStateCompat.ACTION_PAUSE |
                            PlaybackStateCompat.ACTION_STOP
            )
            .build();
    mMediaSessionCompat.setPlaybackState(playbackStateCompat);
    mMediaSessionCompat.setCallback(mMediaSessionCallback);
    mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
}

Now create this callback in service class:

private MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback() {

    @Override
    public void onPlay() {
        super.onPlay();
        mMediaSessionCompat.setActive(true);
        Log.d("dvmMediaSessionCompat ","onPlay");
        if (PlayerConstants.SONG_PAUSED){
            Controls.playControl(getApplicationContext());
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("dvmMediaSessionCompat ","onPause");
        if (!PlayerConstants.SONG_PAUSED){
            Controls.pauseControl(getApplicationContext());
        }
        else
            Controls.playControl(getApplicationContext());


    }
    @Override
    public void onSkipToQueueItem(long queueId) {

    }

    @Override
    public void onSeekTo(long position) {

    }

    @Override
    public void onStop() {
        Log.d("dvmMediaSessionCompat ","onStop");
    }

    @Override
    public void onSkipToNext() {
        Log.d("dvmMediaSessionCompat ","onSkipToNext");
        Controls.nextControl(getApplicationContext());
    }

    @Override
    public void onSkipToPrevious() {
        Log.d("dvmMediaSessionCompat ","onSkipToPrevious");
        Controls.previousControl(getApplicationContext());
    }

};

That's what I have done and controls are started working, I was just forgot to add setCallback on my MediaSessionCompat instance, that's why my controls was not working. But now it's working perfectly.

Note: Controls.nextControl(context) this is the method in which I have added my own functionality to switch the song, you can replace that with your logic.

Upvotes: 0

Shreyash Mahajan
Shreyash Mahajan

Reputation: 23596

Have you checked RemoteControlClient? it is used for the Android Music Remote control even if the App is in Lock mode.(same like image you have attached)

Please check RemoteControlClient

Just call below method while you receiver command action for Play,Pause,Next and previous of the Song track.

  private void lockScreenControls() {

    // Use the media button APIs (if available) to register ourselves for media button
    // events

    MediaButtonHelper.registerMediaButtonEventReceiverCompat(mAudioManager, mMediaButtonReceiverComponent);
    // Use the remote control APIs (if available) to set the playback state
    if (mRemoteControlClientCompat == null) {
        Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        intent.setComponent(mMediaButtonReceiverComponent);
        mRemoteControlClientCompat = new RemoteControlClientCompat(PendingIntent.getBroadcast(this /*context*/,0 /*requestCode, ignored*/, intent /*intent*/, 0 /*flags*/));
        RemoteControlHelper.registerRemoteControlClient(mAudioManager,mRemoteControlClientCompat);
    }
    mRemoteControlClientCompat.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
    mRemoteControlClientCompat.setTransportControlFlags(
            RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
            RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
            RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
            RemoteControlClient.FLAG_KEY_MEDIA_STOP);

  //update remote controls
    mRemoteControlClientCompat.editMetadata(true)
            .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, "NombreArtista")
            .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, "Titulo Album")
            .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, nombreCancion)
            //.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION,playingItem.getDuration())
                    // TODO: fetch real item artwork
            .putBitmap(RemoteControlClientCompat.MetadataEditorCompat.METADATA_KEY_ARTWORK, getAlbumArt())
            .apply();
    }
}

MediaButtonHelper Class

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.content.ComponentName;
import android.media.AudioManager;
import android.util.Log;

/**
 * Class that assists with handling new media button APIs available in API level 8.
 */
public class MediaButtonHelper {
    // Backwards compatibility code (methods available as of API Level 8)
    private static final String TAG = "MediaButtonHelper";

    static {
        initializeStaticCompatMethods();
    }

    static Method sMethodRegisterMediaButtonEventReceiver;
    static Method sMethodUnregisterMediaButtonEventReceiver;

    static void initializeStaticCompatMethods() {
        try {
            sMethodRegisterMediaButtonEventReceiver = AudioManager.class.getMethod(
                    "registerMediaButtonEventReceiver",
                    new Class[] { ComponentName.class });
            sMethodUnregisterMediaButtonEventReceiver = AudioManager.class.getMethod(
                    "unregisterMediaButtonEventReceiver",
                    new Class[] { ComponentName.class });
        } catch (NoSuchMethodException e) {
            // Silently fail when running on an OS before API level 8.
        }
    }

    public static void registerMediaButtonEventReceiverCompat(AudioManager audioManager,
            ComponentName receiver) {
        if (sMethodRegisterMediaButtonEventReceiver == null)
            return;

        try {
            sMethodRegisterMediaButtonEventReceiver.invoke(audioManager, receiver);
        } catch (InvocationTargetException e) {
            // Unpack original exception when possible
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            } else {
                // Unexpected checked exception; wrap and re-throw
                throw new RuntimeException(e);
            }
        } catch (IllegalAccessException e) {
            Log.e(TAG, "IllegalAccessException invoking registerMediaButtonEventReceiver.");
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unused")
    public static void unregisterMediaButtonEventReceiverCompat(AudioManager audioManager,
            ComponentName receiver) {
        if (sMethodUnregisterMediaButtonEventReceiver == null)
            return;

        try {
            sMethodUnregisterMediaButtonEventReceiver.invoke(audioManager, receiver);
        } catch (InvocationTargetException e) {
            // Unpack original exception when possible
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            } else {
                // Unexpected checked exception; wrap and re-throw
                throw new RuntimeException(e);
            }
        } catch (IllegalAccessException e) {
            Log.e(TAG, "IllegalAccessException invoking unregisterMediaButtonEventReceiver.");
            e.printStackTrace();
        }
    }
}

Please also check this developer app given for how to integrate RemoteControlClient: Random Music Player However UI for the RemoteControlClient defer as per the device you can not updates its UI to your own but you have control to show and display the component and control of the Music app.

Update

Above mentioned class is deprecated now. So please check with Media Session for that and update accordingly.

Upvotes: 15

eremzeit
eremzeit

Reputation: 4516

RemoteControlClient was what you were looking for, but now it's deprecated and has been replaced with MediaSession.

The docs are here: https://developer.android.com/reference/android/media/session/MediaSession.html

Upvotes: 2

Related Questions