Android MediaSession 的简单使用

一、MediaSession 是什么?

简单明了的从中式英语去理解,Media 多媒体、 Session 会话

MediaSession 是Google 官方提供的多媒体框架

框架主要分为两部分:服务端、客户端

服务端提供播放器的参数配置啥的

客户端控制服务端具体操作;比如:播放、暂停、上一曲、下一曲等等自定义方式

想要官方一点的理解自己去看官方文档:

        https://developer.android.google.cn/guide/topics/media-apps/media-apps-overview

话不多说,直接撸代码:

        MediaSession 服务端:


import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserServiceCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class MediaService extends MediaBrowserServiceCompat {
    private static final String TAG = "TEST_MediaService";

    /**
     * 媒体会话,受控端
     * 设置session 到界面响应
     */
    private MediaSessionCompat mediaSession;
    /**
     * 返回到界面的播放状态/播放的ID3信息
     */
    private PlaybackStateCompat mPlaybackState;

    /**
     * 当前播放下标
     */
    private int currentPostion = 0;
    /**
     *
     */
    private String parentId;
    /**
     * 当前播放列表
     */
    private List mPlayBeanList = MusicListData.getPlayList();

    boolean isHaveAudioFocus = false;
    private AudioManager mAudioManager;

    /**
     * 进度条更新时间1s
     */
    private static final int UPDATE_TIME = 1000;

    private final Handler mHandler = new Handler();

    /**
     * 音乐进度条
     */
    private final Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            if (null == mMediaPlayer || null == mPlaybackState || null == mediaSession) {
                Log.d(TAG, "run: mMediaPlayer = " + mMediaPlayer + "  mPlaybackState = " + mPlaybackState + "   mediaSession = " + mediaSession);
                return;
            }
            if (!mMediaPlayer.isPlaying()) {
                Log.d(TAG, "run: not playing");
                return;
            }
            Log.d(TAG, "run: currentPostion = " + mMediaPlayer.getCurrentPosition() + "  duration = " + mMediaPlayer.getDuration());
            Bundle extras = new Bundle();
            extras.putLong("currentPostion", mMediaPlayer.getCurrentPosition());
            extras.putLong("duration", mMediaPlayer.getDuration());
            sendPlaybackState(PlaybackStateCompat.STATE_PLAYING, extras);
            mHandler.postDelayed(mRunnable, UPDATE_TIME);
        }
    };

    /**
     * 播放器
     */
    private MediaPlayer mMediaPlayer;
    /**
     * 准备就绪?
     */
    private boolean isPrepare = false;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

        mPlaybackState = new PlaybackStateCompat.Builder()
                .setState(PlaybackStateCompat.STATE_NONE, currentPostion, 1.0f)
                .setActions(getAvailableActions(PlaybackStateCompat.STATE_NONE))
                .build();

        //初始化,第一个参数为context,第二个参数为String类型tag,这里就设置为类名了
        mediaSession = new MediaSessionCompat(this, "MediaService");
        //设置token
        setSessionToken(mediaSession.getSessionToken());
        //设置callback,这里的callback就是客户端对服务指令到达处
        mediaSession.setCallback(mCallback);
        mediaSession.setActive(true);

        //初始化播放器
        mMediaPlayer = new MediaPlayer();
        //准备监听
        mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                Log.d(TAG, "onPrepared: ");
                isPrepare = true;
                // 准备就绪
                sendPlaybackState(PlaybackStateCompat.STATE_BUFFERING);
                handlePlay();
            }
        });
        //播放完成监听
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Log.d(TAG, "onCompletion: ");
                sendPlaybackState(PlaybackStateCompat.STATE_NONE);
                // 播放完成 重置 播放器
//                mMediaPlayer.reset();
                // 下一曲
                mCallback.onSkipToNext();
            }
        });
        //播放错误监听
        mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                Log.d(TAG, "onError:  what = " + what + "   extra = " + extra);
                isPrepare = false;
                sendPlaybackState(PlaybackStateCompat.STATE_ERROR);
                // 播放错误 重置 播放器
                mMediaPlayer.reset();
                return false;
            }
        });

        // 设置音频流类型
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        //设置声音
        AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        if (null != mAudioManager) {
            int mVolumn = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setVolume(mVolumn, mVolumn);
        }
    }

    //mediaSession设置的callback,也是客户端控制指令所到达处
    private final MediaSessionCompat.Callback mCallback = new MediaSessionCompat.Callback() {
        //重写的方法都是选择性重写的,不完全列列举,具体可以查询文章末尾表格
        @Override
        public void onPlay() {
            super.onPlay();
            Log.d(TAG, "onPlay: isPrepare = " + isPrepare);
            //客户端mMediaController.getTransportControls().play()就会调用到这里,以下类推
            //处理播放逻辑
            //处理完成后通知客户端更新,这里就会回调给客户端的MediaController.Callback
            if (null != mMediaPlayer && !isPrepare) {
                handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(getPlayBean()).mediaId));
            } else {
                handlePlay();
            }
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, "onPause: ");
            handlePause(true);
        }

        @Override
        public void onSeekTo(long pos) {
            super.onSeekTo(pos);
            //设置到指定进度时触发
        }

        @Override
        public void onSkipToPrevious() {
            int pos = (currentPostion + mPlayBeanList.size() - 1) % mPlayBeanList.size();
            Log.e(TAG, "onSkipToPrevious  pos = " + pos);
            handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(setPlayPosition(pos)).mediaId));
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();

            //下一首
            //通知媒体信息改变
//            mediaSession.setMetadata(mediaMetadata);
            int pos = (currentPostion + 1) % mPlayBeanList.size();
            Log.d(TAG, "onSkipToNext: pos = " + pos);
            handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(setPlayPosition(pos)).mediaId));
        }

        /**
         * 响应MediaControllerCompat.getTransportControls().playFromUri
         *
         * @param uri uri
         * @param extras extras
         */
        @Override
        public void onPlayFromUri(Uri uri, Bundle extras) {
            Log.e(TAG, "onPlayFromUri");
            int position = extras.getInt("playPosition");
            setPlayPosition(position);
            handleOpenUri(uri);
        }

        @Override
        public void onCustomAction(String action, Bundle extras) {
            super.onCustomAction(action, extras);
            //自定义指令发送到的地方
            //对应客户端 mMediaController.getTransportControls().sendCustomAction(...)
        }

    };

    /**
     * 控制客户端 链接
     *
     * @param clientPackageName clientPackageName
     * @param clientUid         clientUid
     * @param rootHints         rootHints
     * @return BrowserRoot
     */
    @Nullable
    @Override
    public BrowserRoot onGetRoot(@android.support.annotation.NonNull @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
        //MediaBrowserService必须重写的方法,第一个参数为客户端的packageName,第二个参数为Uid
        //第三个参数是从客户端传递过来的Bundle。
        //通过以上参数来进行判断,若同意连接,则返回BrowserRoot对象,否则返回null;
        //构造BrowserRoot的第一个参数为rootId(自定义),第二个参数为Bundle;
        Log.d(TAG, "onGetRoot: clientPackageName = " + clientPackageName + "   clientUid = " + clientUid);
        return new BrowserRoot(clientPackageName, null);
    }

    /**
     * 播放列表
     *
     * @param parentId parentId
     * @param result   result
     */
    @Override
    public void onLoadChildren(@android.support.annotation.NonNull @NonNull String parentId, @NonNull Result> result) {
        //MediaBrowserService必须重写的方法,用于处理订阅信息,文章后面会提及
        // 设置播放列表
        Log.e(TAG, "onLoadChildren-------- parentId = " + parentId);
        this.parentId = parentId;
        // 将信息从当前线程中移除,允许后续调用sendResult方法
        result.detach();

        // 我们模拟获取数据的过程,真实情况应该是异步从网络或本地读取数据
        ArrayList mediaItems = MusicListData.transformPlayList(mPlayBeanList);

        // 向Browser发送 播放列表数据
        result.sendResult(mediaItems);
        // 刷新 播放数据数据
//        notifyChildrenChanged(parentId);
        // 模拟定时加载数据
        if (mediaItems.size() == 2) {
            getSyncData();
        }
    }


    /**
     * 模拟刷新数据
     */
    private void getSyncData() {
        Log.d(TAG, "getSyncData: ");

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run: load data for update ");
                mPlayBeanList = MusicListData.getPlayListUpdate();
                currentPostion = 0;
                notifyChildrenChanged(parentId);
            }
        }, 30000);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isPrepare = false;
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        if (mediaSession != null) {
            mediaSession.release();
            mediaSession = null;
        }
    }

    /**
     * 申请焦点
     *
     * @return 焦点
     */
    private int requestAudioFocus() {
        int result = mAudioManager.requestAudioFocus(mOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
        isHaveAudioFocus = AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result;
        return result;
    }


    /**
     * 释放焦点
     */
    private void abandAudioFocus() {
        int result = mAudioManager.abandonAudioFocus(mOnAudioFocusChangeListener);
        isHaveAudioFocus = AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result;
    }


    /**
     * open
     *
     * @param uri uri
     */
    private void handleOpenUri(Uri uri) {
        Log.d(TAG, "handleOpenUri: uri = " + uri);
        if (uri == null) {
            Log.d(TAG, "handlePlayUri: URL == NULL ");
            return;
        }
        if (requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            Log.d(TAG, "handlePlayUri: requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED");
            return;
        }
        isPrepare = false;
        mMediaPlayer.reset();
        mMediaPlayer.setLooping(false);
        try {
            mMediaPlayer.setDataSource(this, uri);
        } catch (IOException e) {
            Log.e(TAG, "handlePlayUri: ", e);
            e.printStackTrace();
        }
        mMediaPlayer.prepareAsync();
    }

    /**
     * 播放
     */
    private void handlePlay() {
        Log.d(TAG, "handlePlay: play   isPrepare = " + isPrepare);

        if (null == mMediaPlayer || !isPrepare) {
            Log.d(TAG, "handlePlay: null == mMediaPlayer || isPrepare " + isPrepare);
            return;
        }
        if (!mMediaPlayer.isPlaying()) {
            mMediaPlayer.start();
        }

        mHandler.removeCallbacks(mRunnable);
        mHandler.postDelayed(mRunnable, UPDATE_TIME);

        sendPlaybackState(PlaybackStateCompat.STATE_CONNECTING);
        //我们可以保存当前播放音乐的信息,以便客户端刷新UI
        mediaSession.setMetadata(MusicListData.transformPlayBean(Objects.requireNonNull(getPlayBean())));
    }

    /**
     * 暂停
     *
     * @param isAbandFocus 焦点
     */
    private void handlePause(boolean isAbandFocus) {
        Log.d(TAG, "handlePause: isAbandFocus = " + isAbandFocus);
        if (mMediaPlayer == null || !isPrepare) {
            return;
        }
        if (mMediaPlayer.isPlaying()) {
            mMediaPlayer.pause();
        }
        mHandler.removeCallbacks(mRunnable);
        sendPlaybackState(PlaybackStateCompat.STATE_PAUSED);
    }


    /**
     * 当前播放 歌曲
     *
     * @return playbean
     */
    private MusicData getPlayBean() {
        if (currentPostion >= 0 && currentPostion < mPlayBeanList.size()) {
            return mPlayBeanList.get(currentPostion);
        }
        return null;
    }

    /**
     * 设置列表 播放下标
     *
     * @param pos pos
     * @return playbean
     */
    private MusicData setPlayPosition(int pos) {
        if (pos >= 0 && pos < mPlayBeanList.size()) {
            currentPostion = pos;
            return mPlayBeanList.get(currentPostion);
        }
        return null;
    }


    /**
     * Set the current capabilities available on this session. This should
     * use a bitmask of the available capabilities.
     *
     * @param state 歌曲状态
     * @return 可用的操作Actions
     */
    public long getAvailableActions(int state) {
        long actions = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
                | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_SEEK_TO;
        if (state == PlaybackStateCompat.STATE_PLAYING) {
            actions |= PlaybackStateCompat.ACTION_PAUSE;
        } else {
            actions |= PlaybackStateCompat.ACTION_PLAY;
        }
        return actions;
    }

    /**
     * 音源切换监听
     */
    AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            Log.d(TAG, "onAudioFocusChange  focusChange = " + focusChange + ", before isHaveAudioFocus = " +
                    isHaveAudioFocus);
            switch (focusChange) {
                case AudioManager.AUDIOFOCUS_LOSS:
                    // 音源丢失
                    isHaveAudioFocus = false;
                    mCallback.onPause();
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    // 音源短暂丢失
                    isHaveAudioFocus = false;
                    Log.d(TAG, " AUDIOFOCUS_LOSS_TRANSIENT  ");
                    handlePause(false);
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    //  降低音量
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    // 获得音源
                    isHaveAudioFocus = true;
                    mCallback.onPlay();
                    break;
                case AudioManager.AUDIOFOCUS_REQUEST_FAILED:
                    // 音源申请失败
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * 发送歌曲状态
     *
     * @param state 状态
     */
    private void sendPlaybackState(int state) {
        sendPlaybackState(state, null);
    }

    /**
     * 发送歌曲状态
     *
     * @param state  状态
     * @param extras 参数
     */
    private void sendPlaybackState(int state, Bundle extras) {
        mPlaybackState = new PlaybackStateCompat.Builder()
                .setState(state, currentPostion, 1.0f)
                .setActions(getAvailableActions(state))
                .setExtras(extras)
                .build();
        mediaSession.setPlaybackState(mPlaybackState);
    }

}

     别忘了在AndroidManifest.xml 新增   和启动服务

        
            
                
            
        

    启动服务

// 避免ui unbind后,后台播放音乐停止
startService(new Intent(this, MediaService.class));

          MediaSession  服务端 主要做的是:

                MediaPlayer 初始化

                        AudioManager 申请音源

                实现MediaBrowserServiceCompat   

                        onGetRoot 客户端链接

                        onLoadChildren  服务端把数据传给对应的客户端

                PlaybackStateCompat.Builder() 是用于发送歌曲状态到客户端的实体                

                MediaMetadataCompat 传输的歌曲实体

                MediaSessionCompat 主要用于把歌曲信息、歌曲状态等,发送到客户端进行操作

        MediaSession 客户端 :


import android.content.ComponentName;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;


import java.util.List;

public class DemoActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "TEST_DemoActivity";

    private MediaBrowserCompat mMediaBrowser;
    PlayInfo mPlayInfo = new PlayInfo();

    private TextView mTvInfo;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        mTvInfo = findViewById(R.id.tv_music_name);
        findViewById(R.id.btn_play_or_puse).setOnClickListener(this);
        findViewById(R.id.btn_pre).setOnClickListener(this);
        findViewById(R.id.btn_next).setOnClickListener(this);

    }


    @Override
    protected void onResume() {
        super.onResume();
        connectRemoteService();
    }


    private void connectRemoteService() {
        // 1.连接的服务
        
        ComponentName componentName = new ComponentName("com.xxx.xxxx", "com.xxx.xxxx.session.MossMusicService");

        // 2.创建MediaBrowser
        mMediaBrowser = new MediaBrowserCompat(this, componentName, mConnectionCallbacks, null);
        // 3.建立连接
        mMediaBrowser.connect();
    }

    private void refreshPlayInfo() {
        mTvInfo.setText(mPlayInfo.debugInfo());
    }

    private final MediaBrowserCompat.ConnectionCallback mConnectionCallbacks = new MediaBrowserCompat.ConnectionCallback() {

        @Override
        public void onConnected() {
            Log.d(TAG, "MediaBrowser.onConnected");
            if (mMediaBrowser.isConnected()) {
                String mediaId = mMediaBrowser.getRoot();
                mMediaBrowser.unsubscribe(mediaId);
                //之前说到订阅的方法还需要一个参数,即设置订阅回调SubscriptionCallback
                //当Service获取数据后会将数据发送回来,此时会触发SubscriptionCallback.onChildrenLoaded回调
                mMediaBrowser.subscribe(mediaId, browserSubscriptionCallback);
                try {
                    MediaControllerCompat mediaController = new MediaControllerCompat(DemoActivity.this,
                            mMediaBrowser.getSessionToken());

                    MediaControllerCompat.setMediaController(DemoActivity.this, mediaController);

//                    mediaController = new MediaControllerCompat(DemoActivity.this, mMediaBrowser.getSessionToken());
                    mediaController.registerCallback(mMediaControllerCallback);
                    if (mediaController.getMetadata() != null) {
                        updatePlayMetadata(mediaController.getMetadata());
                        updatePlayState(mediaController.getPlaybackState());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onConnectionSuspended() {
            // 连接中断回调
            Log.d(TAG, "onConnectionSuspended");
        }

        @Override
        public void onConnectionFailed() {
            Log.d(TAG, "onConnectionFailed");
        }
    };


    private void updatePlayMetadata(MediaMetadataCompat metadata) {
        if (metadata == null) {
            return;
        }
        mPlayInfo.setMetadata(metadata);
        refreshPlayInfo();
    }


    /**
     * 被动接收播放信息、状态改变
     */
    MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
        @Override
        public void onSessionDestroyed() {
            // Session销毁
            Log.d(TAG, "onSessionDestroyed");

        }

        @Override
        public void onQueueChanged(List queue) {
            // 当前播放列表更新回调
        }

        @Override
        public void onMetadataChanged(MediaMetadataCompat metadata) {
            // 数据变化
            Log.e(TAG, "onMetadataChanged ");
            updatePlayMetadata(metadata);
        }

        @Override
        public void onPlaybackStateChanged(PlaybackStateCompat state) {
            // 播放状态变化
            Log.d(TAG, "onPlaybackStateChanged   PlaybackState:" + state.getState());
            updatePlayState(state);
        }

        @Override
        public void onQueueTitleChanged(CharSequence title) {
            super.onQueueTitleChanged(title);
            //播放列表信息回调,QueueItem在文章后面会提及
        }

        @Override
        public void onSessionEvent(String event, Bundle extras) {
            super.onSessionEvent(event, extras);
            //自定义的事件回调,满足你各种自定义需求
        }

        @Override
        public void onExtrasChanged(Bundle extras) {
            super.onExtrasChanged(extras);
            //额外信息回调,可以承载播放模式等信息
        }
    };


    /**
     * 向媒体浏览器服务(MediaBrowserService)发起数据订阅请求的回调接口b
     */
    private final MediaBrowserCompat.SubscriptionCallback browserSubscriptionCallback = new MediaBrowserCompat.SubscriptionCallback() {

        @Override
        public void onChildrenLoaded(@NonNull String parentId, @NonNull List children, @NonNull Bundle options) {
            super.onChildrenLoaded(parentId, children, options);
            //订阅消息时添加了Bundle参数,会回调到此方法
            //即mMediaBrowser.subscribe("PARENT_ID_1", mCallback,bundle)的回调
            Log.d(TAG, "onChildrenLoaded: parentId = " + parentId + "  children = " + children + " options = " + options);
        }

        @Override
        public void onChildrenLoaded(@NonNull String parentId, @NonNull List children) {
            Log.d(TAG, "onChildrenLoaded: parentId = " + parentId + "  children = " + children);
            mPlayInfo.setChildren(children);
            refreshPlayInfo();
        }

        @Override
        public void onError(@NonNull String parentId) {
            super.onError(parentId);
            Log.d(TAG, "onError: parentId = " + parentId);
        }

        @Override
        public void onError(@NonNull String parentId, @NonNull Bundle options) {
            super.onError(parentId, options);
            Log.d(TAG, "onError: parentId = " + parentId + "  options = " + options);
        }
    };


    @Override
    public void onClick(View v) {
        MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(DemoActivity.this);

        switch (v.getId()) {
            case R.id.btn_play_or_puse:
                PlaybackStateCompat playbackState = mediaController.getPlaybackState();
                if (null != playbackState && playbackState.getState() == PlaybackState.STATE_PLAYING) {
                    Log.d(TAG, "onClick: 暂停");
                    mediaController.getTransportControls().pause();
                } else {
                    Log.d(TAG, "onClick: 播放");
//                    Log.d(TAG, "onClick: play or puse " + .getState());
                    mediaController.getTransportControls().play();
                }
                break;
            case R.id.btn_pre:
                mediaController.getTransportControls().skipToPrevious();
                break;
            case R.id.btn_next:
                mediaController.getTransportControls().skipToNext();
                break;
        }
    }


    private void updatePlayState(PlaybackStateCompat state) {
        if (state == null) {
            return;
        }
        mPlayInfo.setState(state);
        refreshPlayInfo();
    }


    static class PlayInfo {
        private MediaMetadataCompat metadata;
        private PlaybackStateCompat state;
        private List children;


        public void setMetadata(MediaMetadataCompat metadata) {
            this.metadata = metadata;
        }

        public void setState(PlaybackStateCompat state) {
            this.state = state;
        }

        public void setChildren(List children) {
            this.children = children;
        }

        public String debugInfo() {
            StringBuilder builder = new StringBuilder();
            if (state != null) {
                builder.append("当前播放状态:\t").append(state.getState() == PlaybackState.STATE_PLAYING ? "播放中" : "未播放");
                Bundle extras = state.getExtras();
                if (null != extras) {
                    long currentPostion = extras.getLong("currentPostion", 0);
                    long duration = extras.getLong("duration", 0);
                    builder.append("\n当前播放进度:\t").append("currentPostion = ").append(currentPostion).append(" / duration = ").append(duration);
                }
                builder.append("\n\n");
            }
            if (metadata != null) {
                builder.append("当前播放信息:\t").append(transform(metadata));
                builder.append("\n\n");
            }
            if (children != null && !children.isEmpty()) {
                builder.append("当前播放列表:").append("\n");
                for (int i = 0; i < children.size(); i++) {
                    MediaBrowserCompat.MediaItem mediaItem = children.get(i);
                    builder.append(i + 1).append(" ").append(mediaItem.getDescription().getTitle()).append(" - ").append(mediaItem.getDescription().getSubtitle()).append("\n");
                }
            }
            return builder.toString();
        }

        public static String transform(MediaMetadataCompat data) {
            if (data == null) {
                return null;
            }
            String title = data.getString(MediaMetadataCompat.METADATA_KEY_TITLE);
            String artist = data.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
            String albumName = data.getString(MediaMetadataCompat.METADATA_KEY_ALBUM);
            long mediaNumber = data.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER);
            long mediaTotalNumber = data.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS);
            return title + " - " + artist;
        }
    }
}

            MediaBrowserCompat   客户端

        主要用于控制Service的播放:

        启动连接:

        // 1.待连接的服务
        ComponentName componentName = new ComponentName("com.xxx.xxxx", "com.xxx.xxxx.session.MossMusicService");
        // 2.创建MediaBrowser
        mMediaBrowser = new MediaBrowserCompat(this, componentName, mConnectionCallbacks, null);
        // 3.建立连接
        mMediaBrowser.connect();

         服务连接后,需要订阅数据的监听、MediaBrowserCompat.ConnectionCallback

                               被动接收播放信息、状态改变等信息回调:MediaControllerCompat.Callback   

数据组装:


import android.content.Context;
import android.net.Uri;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;


import java.util.ArrayList;
import java.util.List;

public class MusicListData {

    /**
     * rwa 转换成Uri
     *
     * @param context context
     * @param id      资源 id
     * @return Uri
     */
    public static Uri rawToUri(Context context, int id) {
        String uriStr = "android.resource://" + context.getPackageName() + "/" + id;
        return Uri.parse(uriStr);
    }

    public static List getPlayList() {
        List list = new ArrayList<>();

        MusicData playBean = new MusicData();
        playBean.mediaId = R.raw.cesinspire;
        playBean.tilte = "cesinspire.mp3";
        playBean.artist = "test";
        list.add(playBean);

        MusicData playBean2 = new MusicData();
        playBean2.mediaId = R.raw.bigbigbig;
        playBean2.tilte = "bigbigbig";
        playBean2.artist = "罗罗罗罗罗罗";
        list.add(playBean2);

        return list;
    }


    public static List getPlayListUpdate() {
        List list = new ArrayList<>();

        MusicData playBean = new MusicData();
        playBean.mediaId = R.raw.cesinspire;
        playBean.tilte = "cesinspire.mp3";
        playBean.artist = "test";
        list.add(playBean);

        MusicData playBean2 = new MusicData();
        playBean2.mediaId = R.raw.bigbigbig;
        playBean2.tilte = "bigbigbig";
        playBean2.artist = "罗罗罗罗罗罗";
        list.add(playBean2);

        MusicData playBean3 = new MusicData();
        playBean3.mediaId = R.raw.fengtimo_shuosanjiusan;
        playBean3.tilte = "说散就散";
        playBean3.artist = "fengtimo";
        list.add(playBean3);

        return list;
    }


    /**
     * 数据转换
     *
     * @param playBeanList playBeanList
     * @return MediaSession 数据实体
     */
    public static ArrayList transformPlayList(List playBeanList) {
        //我们模拟获取数据的过程,真实情况应该是异步从网络或本地读取数据
        ArrayList mediaItems = new ArrayList<>();
        for (int i = 0; i < playBeanList.size(); i++) {
            MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
                    .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, "" + playBeanList.get(i).mediaId)
                    .putString(MediaMetadataCompat.METADATA_KEY_TITLE, playBeanList.get(i).tilte)
                    .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, playBeanList.get(i).artist)
                    .build();
            mediaItems.add(createMediaItem(metadata));
        }
        return mediaItems;
    }


    public static MediaMetadataCompat transformPlayBean(MusicData bean) {
        return new MediaMetadataCompat.Builder()
                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, "" + bean.mediaId)
                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, bean.tilte)
                .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, bean.artist)
                .build();
    }

    private static MediaBrowserCompat.MediaItem createMediaItem(MediaMetadataCompat metadata) {
        return new MediaBrowserCompat.MediaItem(metadata.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
    }

}

数据实体

public class MusicData {
    int mediaId;
    String tilte;
    String artist;
}

以上 就是 MediaSession 的简单使用方式。

                

你可能感兴趣的:(android)