MediaSession学习总结

1.框架预览

2.用法

2.1参考链接:

MediaSession 简单使用

2.2 服务端要实现MediaBrowserService;

主要实现的功能:

   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);

在MediaSessionCompat.Callback 中实现具体的播放与控制逻辑

  //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(...)
        }
 
    };

这里要注意监听音频焦点的变化。

  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;
            }
        }
    };
 



    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;
    }

播放的同时需要把播放状态和歌曲信息 回传给客户端

   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);
    }

歌曲数据需要转成对应格式

private MediaMetadataCompat buildFromLocal(Song song){
        String title = song.getTitle();
        String album = song.getAlbum();
        String artist = song.getArtist();
        int duration = song.getDuration();
        String source = song.getPath();
        String strId = "";
        if(title != null && artist != null){
            strId = title + artist;
        }
        String id = String.valueOf(strId.hashCode());
        String albumArt = song.getAlbumObj().getAlbumArt();
        return new MediaMetadataCompat.Builder()
                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID,id)
                .putString(SongSource.CUSTOM_METADATA_TRACK_SOURCE, source)
                .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_URI,source)
                .putString(MediaMetadataCompat.METADATA_KEY_ALBUM,album)
                .putString(MediaMetadataCompat.METADATA_KEY_ARTIST,artist)
                .putString(MediaMetadataCompat.METADATA_KEY_ART_URI,albumArt)
                .putLong(MediaMetadataCompat.METADATA_KEY_DURATION,duration)
                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
                .build();
    }

2.3客户端绑定MediaBrowserService.

创建MediaBrowser 客户端,连接倒对应服务器。

private MediaBrowserCompat mMediaBrowser;

mMediaBrowser = new MediaBrowserCompat(this,
                new ComponentName(this, MusicService.class), mConnectionCallback, null);



 private final MediaBrowserCompat.ConnectionCallback mConnectionCallback =
            new MediaBrowserCompat.ConnectionCallback() {
                @Override
                public void onConnected() {
                    //说明已经连接上了
                    try {
                        connectToSession(mMediaBrowser.getSessionToken());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            };

连接的callback,在成功连接时,获取 MediaController, 并注册MediaControllerCompat.Callback。

 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 final MediaControllerCompat.Callback mMediaControllerCallback =
            new MediaControllerCompat.Callback() {

                @Override
                public void onPlaybackStateChanged(@NonNull PlaybackStateCompat state) {
                    //这里根据播放状态的改变,本地ui做相应的改变,例如播放模式,播放、暂停,进度条等
                    updatePlaybackState(state);
                }

                @Override
                public void onMetadataChanged(MediaMetadataCompat metadata) {
                    //歌曲的信息,例如播放时长,歌曲名称等
                    updateDuration(metadata);
                }

@override
 public void onQueueChanged(List<QueueItem> queue) {
        }
            };

控制服务端的播放逻辑。通过mediaController.getTransportControls() 去调用。如:

TransportControls.skipToPrevious();
TransportControls.skipToNext();
TransportControls.pause();
TransportControls.play();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值