public class

MediaControllerAdapter

extends PlayerAdapter

 java.lang.Object

androidx.leanback.media.PlayerAdapter

↳androidx.leanback.media.MediaControllerAdapter

Gradle dependencies

compile group: 'androidx.leanback', name: 'leanback', version: '1.2.0-alpha04'

  • groupId: androidx.leanback
  • artifactId: leanback
  • version: 1.2.0-alpha04

Artifact androidx.leanback:leanback:1.2.0-alpha04 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.leanback:leanback com.android.support:leanback-v17

Androidx class mapping:

androidx.leanback.media.MediaControllerAdapter android.support.v17.leanback.media.MediaControllerAdapter

Overview

A helper class for implementing a adapter layer for android.support.v4.media.session.MediaControllerCompat.

Summary

Constructors
publicMediaControllerAdapter(android.support.v4.media.session.MediaControllerCompat controller)

Constructor for the adapter using android.support.v4.media.session.MediaControllerCompat.

Methods
public voidfastForward()

Optional method.

public longgetBufferedPosition()

Returns the current buffered position of the media item in milliseconds.

public longgetCurrentPosition()

Returns the current position of the media item in milliseconds.

public longgetDuration()

Returns the duration of the media item in milliseconds.

public DrawablegetMediaArt(Context context)

Get current media's drawable art.

public android.support.v4.media.session.MediaControllerCompatgetMediaController()

Return the object of android.support.v4.media.session.MediaControllerCompat from this class.

public java.lang.CharSequencegetMediaSubtitle()

Get current media's subtitle.

public java.lang.CharSequencegetMediaTitle()

Get current media's title.

public longgetSupportedActions()

Return xor combination of values defined in PlaybackBaseControlGlue.

public booleanisPlaying()

Returns true if media is currently playing.

public voidnext()

Optional method.

public voidonAttachedToHost(PlaybackGlueHost host)

This method is called attached to associated PlaybackGlueHost.

public voidonDetachedFromHost()

This method is called when current associated PlaybackGlueHost is attached to a different PlaybackGlue or PlaybackGlueHost is destroyed.

public abstract voidpause()

Pauses the media player.

public abstract voidplay()

Starts the media player.

public voidprevious()

Optional method.

public voidrewind()

Optional method.

public voidseekTo(long positionInMs)

Seek to new position.

public voidsetProgressUpdatingEnabled(boolean enable)

Implement this method to enable or disable progress updating.

public voidsetRepeatAction(int repeatActionIndex)

Optional method.

public voidsetShuffleAction(int shuffleActionIndex)

Optional method.

from PlayerAdaptergetCallback, isPrepared, setCallback
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public MediaControllerAdapter(android.support.v4.media.session.MediaControllerCompat controller)

Constructor for the adapter using android.support.v4.media.session.MediaControllerCompat.

Parameters:

controller: Object of MediaControllerCompat..

Methods

public android.support.v4.media.session.MediaControllerCompat getMediaController()

Return the object of android.support.v4.media.session.MediaControllerCompat from this class.

Returns:

Media Controller Compat object owned by this class.

public abstract void play()

Starts the media player.

public abstract void pause()

Pauses the media player.

public void seekTo(long positionInMs)

Seek to new position.

Parameters:

positionInMs: New position in milliseconds.

public void next()

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_SKIP_TO_NEXT to skip to next item.

public void previous()

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_SKIP_TO_PREVIOUS to skip to previous item.

public void fastForward()

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_FAST_FORWARD to fast forward current media item.

public void rewind()

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_REWIND to rewind in current media item.

public void setRepeatAction(int repeatActionIndex)

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_REPEAT to set the repeat action.

Parameters:

repeatActionIndex: The shuffle action. Must be one of the followings: PlaybackControlsRow.RepeatAction.INDEX_ONE PlaybackControlsRow.RepeatAction.INDEX_ALL, PlaybackControlsRow.RepeatAction.INDEX_NONE,

public void setShuffleAction(int shuffleActionIndex)

Optional method. Override this method if PlayerAdapter.getSupportedActions() include PlaybackBaseControlGlue.ACTION_SHUFFLE to set the shuffle action.

Parameters:

shuffleActionIndex: The repeat action. Must be one of the followings: PlaybackControlsRow.ShuffleAction.INDEX_OFF PlaybackControlsRow.ShuffleAction.INDEX_ON

public boolean isPlaying()

Returns true if media is currently playing.

public long getCurrentPosition()

Returns the current position of the media item in milliseconds.

public long getBufferedPosition()

Returns the current buffered position of the media item in milliseconds.

public java.lang.CharSequence getMediaTitle()

Get current media's title.

Returns:

Title of current media.

public java.lang.CharSequence getMediaSubtitle()

Get current media's subtitle.

Returns:

Subtitle of current media.

public Drawable getMediaArt(Context context)

Get current media's drawable art.

Returns:

Drawable art of current media.

public long getDuration()

Returns the duration of the media item in milliseconds.

public void onAttachedToHost(PlaybackGlueHost host)

This method is called attached to associated PlaybackGlueHost.

Parameters:

host:

public void onDetachedFromHost()

This method is called when current associated PlaybackGlueHost is attached to a different PlaybackGlue or PlaybackGlueHost is destroyed. Subclass may override. A typical implementation will release resources (e.g. MediaPlayer or connection to playback service) in this method.

public void setProgressUpdatingEnabled(boolean enable)

Implement this method to enable or disable progress updating.

Parameters:

enable: True to enable progress updating, false otherwise.

public long getSupportedActions()

Return xor combination of values defined in PlaybackBaseControlGlue. Default is PLAY_PAUSE (unless subclass enforce to be 0)

Source

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.leanback.media;

import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_FAST_FORWARD;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_PLAY_PAUSE;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REPEAT;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REWIND;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SHUFFLE;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_NEXT;
import static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_PREVIOUS;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.leanback.widget.PlaybackControlsRow;

/**
 * A helper class for implementing a adapter layer for {@link MediaControllerCompat}.
 */
public class MediaControllerAdapter extends PlayerAdapter {

    private static final String TAG = "MediaControllerAdapter";
    private static final boolean DEBUG = false;

    private MediaControllerCompat mController;
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    Handler mHandler = new Handler();

    // Runnable object to update current media's playing position.
    private final Runnable mPositionUpdaterRunnable = new Runnable() {
        @Override
        public void run() {
            getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
            mHandler.postDelayed(this, getUpdatePeriod());
        }
    };

    // Update period to post runnable.
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    int getUpdatePeriod() {
        return 16;
    }

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    boolean mIsBuffering = false;

    MediaControllerCompat.Callback mMediaControllerCallback =
            new MediaControllerCompat.Callback() {
                @Override
                public void onPlaybackStateChanged(PlaybackStateCompat state) {
                    if (mIsBuffering && state.getState() != PlaybackStateCompat.STATE_BUFFERING) {
                        getCallback().onBufferingStateChanged(MediaControllerAdapter.this, false);
                        getCallback().onBufferedPositionChanged(MediaControllerAdapter.this);
                        mIsBuffering = false;
                    }
                    if (state.getState() == PlaybackStateCompat.STATE_NONE) {
                        // The STATE_NONE playback state will only occurs when initialize the player
                        // at first time.
                        if (DEBUG) {
                            Log.d(TAG, "Playback state is none");
                        }
                    } else if (state.getState() == PlaybackStateCompat.STATE_STOPPED) {
                        // STATE_STOPPED is associated with onPlayCompleted() callback.
                        // STATE_STOPPED playback state will only occurs when the last item in
                        // play list is finished. And repeat mode is not enabled.
                        getCallback().onPlayCompleted(MediaControllerAdapter.this);
                    } else if (state.getState() == PlaybackStateCompat.STATE_PAUSED) {
                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
                    } else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
                    } else if (state.getState() == PlaybackStateCompat.STATE_BUFFERING) {
                        mIsBuffering = true;
                        getCallback().onBufferingStateChanged(MediaControllerAdapter.this, true);
                        getCallback().onBufferedPositionChanged(MediaControllerAdapter.this);
                    } else if (state.getState() == PlaybackStateCompat.STATE_ERROR) {
                        CharSequence errorMessage = state.getErrorMessage();
                        if (errorMessage == null) {
                            getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(),
                                    "");
                        } else {
                            getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(),
                                    state.getErrorMessage().toString());
                        }
                    } else if (state.getState() == PlaybackStateCompat.STATE_FAST_FORWARDING) {
                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
                    } else if (state.getState() == PlaybackStateCompat.STATE_REWINDING) {
                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
                    }
                }

                @Override
                public void onMetadataChanged(MediaMetadataCompat metadata) {
                    getCallback().onMetadataChanged(MediaControllerAdapter.this);
                }
            };

    /**
     * Constructor for the adapter using {@link MediaControllerCompat}.
     *
     * @param controller Object of MediaControllerCompat..
     */
    public MediaControllerAdapter(MediaControllerCompat controller) {
        if (controller == null) {
            throw new NullPointerException("Object of MediaControllerCompat is null");
        }
        mController = controller;
    }

    /**
     * Return the object of {@link MediaControllerCompat} from this class.
     *
     * @return Media Controller Compat object owned by this class.
     */
    public MediaControllerCompat getMediaController() {
        return mController;
    }

    @Override
    public void play() {
        mController.getTransportControls().play();
    }

    @Override
    public void pause() {
        mController.getTransportControls().pause();
    }

    @Override
    public void seekTo(long positionInMs) {
        mController.getTransportControls().seekTo(positionInMs);
    }

    @Override
    public void next() {
        mController.getTransportControls().skipToNext();
    }

    @Override
    public void previous() {
        mController.getTransportControls().skipToPrevious();
    }

    @Override
    public void fastForward() {
        mController.getTransportControls().fastForward();
    }

    @Override
    public void rewind() {
        mController.getTransportControls().rewind();
    }

    @Override
    public void setRepeatAction(int repeatActionIndex) {
        int repeatMode = mapRepeatActionToRepeatMode(repeatActionIndex);
        mController.getTransportControls().setRepeatMode(repeatMode);
    }

    @Override
    public void setShuffleAction(int shuffleActionIndex) {
        int shuffleMode = mapShuffleActionToShuffleMode(shuffleActionIndex);
        mController.getTransportControls().setShuffleMode(shuffleMode);
    }

    @Override
    public boolean isPlaying() {
        if (mController.getPlaybackState() == null) {
            return false;
        }
        return mController.getPlaybackState().getState()
                == PlaybackStateCompat.STATE_PLAYING
                || mController.getPlaybackState().getState()
                == PlaybackStateCompat.STATE_FAST_FORWARDING
                || mController.getPlaybackState().getState() == PlaybackStateCompat.STATE_REWINDING;
    }

    @Override
    public long getCurrentPosition() {
        if (mController.getPlaybackState() == null) {
            return 0;
        }
        return mController.getPlaybackState().getPosition();
    }

    @Override
    public long getBufferedPosition() {
        if (mController.getPlaybackState() == null) {
            return 0;
        }
        return mController.getPlaybackState().getBufferedPosition();
    }

    /**
     * Get current media's title.
     *
     * @return Title of current media.
     */
    public CharSequence getMediaTitle() {
        if (mController.getMetadata() == null) {
            return "";
        }
        return mController.getMetadata().getDescription().getTitle();
    }

    /**
     * Get current media's subtitle.
     *
     * @return Subtitle of current media.
     */
    public CharSequence getMediaSubtitle() {
        if (mController.getMetadata() == null) {
            return "";
        }
        return mController.getMetadata().getDescription().getSubtitle();
    }

    /**
     * Get current media's drawable art.
     *
     * @return Drawable art of current media.
     */
    public Drawable getMediaArt(Context context) {
        if (mController.getMetadata() == null) {
            return null;
        }
        Bitmap bitmap = mController.getMetadata().getDescription().getIconBitmap();
        return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap);
    }

    @Override
    public long getDuration() {
        if (mController.getMetadata() == null) {
            return 0;
        }
        return (int) mController.getMetadata().getLong(
                MediaMetadataCompat.METADATA_KEY_DURATION);
    }

    @Override
    public void onAttachedToHost(@NonNull PlaybackGlueHost host) {
        mController.registerCallback(mMediaControllerCallback);
    }

    @Override
    public void onDetachedFromHost() {
        mController.unregisterCallback(mMediaControllerCallback);
    }

    @Override
    public void setProgressUpdatingEnabled(boolean enable) {
        mHandler.removeCallbacks(mPositionUpdaterRunnable);
        if (!enable) {
            return;
        }
        mHandler.postDelayed(mPositionUpdaterRunnable, getUpdatePeriod());
    }

    @Override
    public long getSupportedActions() {
        long supportedActions = 0;
        if (mController.getPlaybackState() == null) {
            return supportedActions;
        }
        long actionsFromController = mController.getPlaybackState().getActions();
        // Translation.
        if ((actionsFromController & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) {
            supportedActions |= ACTION_PLAY_PAUSE;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
            supportedActions |= ACTION_SKIP_TO_NEXT;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
            supportedActions |= ACTION_SKIP_TO_PREVIOUS;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) {
            supportedActions |= ACTION_FAST_FORWARD;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_REWIND) != 0) {
            supportedActions |= ACTION_REWIND;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_SET_REPEAT_MODE) != 0) {
            supportedActions |= ACTION_REPEAT;
        }
        if ((actionsFromController & PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE) != 0) {
            supportedActions |= ACTION_SHUFFLE;
        }
        return supportedActions;
    }

    /**
     * This function will translate the index of RepeatAction in PlaybackControlsRow to
     * the repeat mode which is defined by PlaybackStateCompat.
     *
     * @param repeatActionIndex Index of RepeatAction in PlaybackControlsRow.
     * @return Repeat Mode in playback state.
     */
    private int mapRepeatActionToRepeatMode(int repeatActionIndex) {
        switch (repeatActionIndex) {
            case PlaybackControlsRow.RepeatAction.INDEX_NONE:
                return PlaybackStateCompat.REPEAT_MODE_NONE;
            case PlaybackControlsRow.RepeatAction.INDEX_ALL:
                return PlaybackStateCompat.REPEAT_MODE_ALL;
            case PlaybackControlsRow.RepeatAction.INDEX_ONE:
                return PlaybackStateCompat.REPEAT_MODE_ONE;
        }
        return -1;
    }

    /**
     * This function will translate the index of RepeatAction in PlaybackControlsRow to
     * the repeat mode which is defined by PlaybackStateCompat.
     *
     * @param shuffleActionIndex Index of RepeatAction in PlaybackControlsRow.
     * @return Repeat Mode in playback state.
     */
    private int mapShuffleActionToShuffleMode(int shuffleActionIndex) {
        switch (shuffleActionIndex) {
            case PlaybackControlsRow.ShuffleAction.INDEX_OFF:
                return PlaybackStateCompat.SHUFFLE_MODE_NONE;
            case PlaybackControlsRow.ShuffleAction.INDEX_ON:
                return PlaybackStateCompat.SHUFFLE_MODE_ALL;
        }
        return -1;
    }
}