打造基于MediaSessionCompat的音乐播放(一)

前言:

依稀记得很久之前写过音乐播放的Demo,当时用的方式还是:通过广播实现Activity和Service之间的通信,通过间接控制MediaPlayer来实现音乐的播放。

最近写了一个本地音乐播放器,总体架构是模仿 谷歌官方的android-UniversalMusicPlayer,这里先不多做介绍。这篇的重点是简单地介绍一下其中使用的MediaSessionCompat框架的使用。

MediaSessionCompat框架:

MediaSessionCompat位于android/support/v4/media/session包下,主要是用于替代Android L 之后推出的MessionSession。
我们通过一张别人的图来了解一下(这张图说的是MediaSession,而不是MediaSessionCompat,但大致原理是一样的):
这里写图片描述
通过Activity和Service(MediaBrowserServiceCompat)这两个组件来实现音乐播放的功能。

MediaBrowserCompat(客户端):

在Activity中,声明MediaBrowserCompat(客户端),通过MediaBrowserCompat来和MediaBrowserServiceCompat(服务端)连接,

private MediaBrowserCompat mMediaBrowser;

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

MediaBrowserCompat的连接:

同时通过MediaBrowserCompat.ConnectionCallback(上面的代码片中的mConnectionCallback)接口来实现和服务端连接的回调,在回调中,我们可以通过返回的MediaSessionCompat.Token获取到MediaControllerCompat(控制器),通过MediaControllerCompat,我们可以实现在Activity中控制音乐。

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

MediaBrowserCompat订阅:

MediaBrowserCompat连接上MediaBrowserServiceCompat之后,我们可以通过MediaBrowserCompat向MediaBrowserServiceCompat发起订阅请求,例如需要获取某一列表的数据,或者某一首歌的数据,这时就需要
做如下操作:
需要先解除订阅,再发起订阅(这好像是官方的一个Bug,必须这么做)

MediaBrowserCompat.unsubscribe(mMediaId);
MediaBrowserCompat.subscribe(mMediaId,mSubscriptionCallback);
 /*
     * 浏览器订阅的接口,数据的回调
     * */
    private final MediaBrowserCompat.SubscriptionCallback mSubscriptionCallback = new MediaBrowserCompat.SubscriptionCallback() {
        @Override
        public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaBrowserCompat.MediaItem> children) {
            super.onChildrenLoaded(parentId, children);
            //children 即为Service发送回来的媒体数据集合
            //在onChildrenLoaded可以执行刷新列表UI的操作

        }
    };

mSubscriptionCallback是浏览器订阅的接口,通过传不同的MediaId,我们可以在这里拿到不同的回调数据,再根据拿到的数据做我们想做的操作。

MediaControllerCompat(控制器):

那么MediaControllerCompat是如何控制音乐的呢?
上面不是提到了客户端连接成功后的操作吗,我们通过MediaSessionCompat.Token,初始化控制器

 private void connectToSession(MediaSessionCompat.Token token) throws RemoteException {
        mediaController = new MediaControllerCompat(this, token);
        MediaControllerCompat.setMediaController(this, mediaController);
        onMediaBrowserConnected();
        onMediaControllerConnected(mediaController.getSessionToken());
    }

通过MediaControllerCompat,我们可以拿到MediaControllerCompat.TransportControls对象,
该对象可以控制播放音乐的一些常规操作:

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

除此之外,我们还可以通过MediaControllerCompat来实现MediaControllerCompat.Callback接口,

MediaControllerCompat.registerCallback(mMediaControllerCallback);

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

该接口的作用是获取音乐播放的状态改变,从而控制我们UI界面的更新,例如进度条,播放信息

MediaBrowserServiceCompat(服务端):

而在Service中,我们可以让自己定义的service继承MediaBrowserServiceCompat,

public class MusicService extends MediaBrowserServiceCompat

MediaSessionCompat:

之前在客户端连接成功后,有这么一行代码:

connectToSession(mMediaBrowser.getSessionToken());

mMediaBrowser.getSessionToken()拿到的就是MediaSessionCompat。

那么什么是MediaSessionCompat呢

在MediaSession框架中,有受控端(一个)和控制端(可以有多个)。接下来为了保证受控端和控制端不串号(想象一个遥控器可以遥控同一型号的多台电视),就有了SessionToken的概念,相当于我们在连接蓝牙设备时的配对码,这样就保证了不串号

当应用程序想要发布媒体播放信息或处理媒体密钥时,应该创建MediaSession。MediaSessionCompat允许与媒体控制器、音量键、媒体按钮和传输控制进行交互。一般来说,一个应用程序只需要一个会话来进行所有的播放(尽管可以创建多个会话来提供更好的媒体控制)

在onCreate方法中,初始化MediaSessionCompat,

private MediaSessionCompat mSession;

 mSession = new MediaSessionCompat(this, "MusicService");
 setSessionToken(mSession.getSessionToken());
 mSession.setCallback(mPlaybackManager.getMediaSessionCallback());
 mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

onGetRoot()控制对服务的访问:

之前提到过,在客户端声明MediaBrowserCompat的时候,向服务端发起了初次连接请求。此时,服务端会在onGetRoot方法中收到请求,此时返回一个rootId就好了,如果方法返回null,则拒绝连接。

 @Nullable
    @Override
    public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
        return new BrowserRoot(MEDIA_ID_ROOT, null);
    }

onLoadChildren()与客户端通信:

接着在onLoadChildren方法中,服务端会接收来自客户端的不同请求,此时需要通过客户端发送过来的parentMediaId,服务端根据parentMediaId来返回不同的结果给客户端

@Override
    public void onLoadChildren(@NonNull String parentMediaId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {

        if (MEDIA_ID_EMPTY_ROOT.equals(parentMediaId)) {
            result.sendResult(new ArrayList<MediaBrowserCompat.MediaItem>());
        } else {
            result.sendResult(mMusicProvider.getChildren(parentMediaId));
        }
    }

这里mMusicProvider的作用是提供音乐,先不多做介绍。

至此,构建一个基于MediaSessionCompat的音乐播放器的第一步就完成啦。

### 回答1: 在Android系统中,我们通常可以使用多种方法来实现音乐播放锁屏显示功能。 首先,我们可以创建一个自定义锁屏界面来显示当前播放音乐信息。这可以通过创建一个自定义的锁屏活动(Lock Screen Activity)来实现。在这个活动中,我们可以设置一个布局文件,用来显示音乐的封面、歌曲名称、艺术家等信息。通过获取当前播放器的状态信息,我们可以更新锁屏界面上的内容,使其与当前播放音乐保持同步。 其次,我们还可以使用Notification来实现音乐播放锁屏显示。通过在音乐播放服务中创建一个Notification,并设置合适的样式和布局,我们可以将音乐信息显示在锁屏通知栏中。用户可以通过下拉通知栏来查看当前播放歌曲的信息,并且可以通过点击通知跳转到音乐播放界面。 另外,我们还可以利用第三方库来实现音乐播放锁屏显示。有一些强大的音乐播放框架,如ExoPlayer和MediaPlayer,它们提供了一些便捷的方法来实现锁屏显示功能。这些框架可以很方便地获取音乐的元数据,并使用系统提供的锁屏API来将信息显示在锁屏界面上。 总的来说,实现Android音乐播放锁屏显示功能可以通过创建自定义锁屏界面、使用Notification或者利用第三方库来实现。这些方法都可以帮助我们在锁屏状态下显示当前播放音乐信息,提升用户体验。 ### 回答2: 在Android系统中,音乐播放锁屏显示是指当我们在使用音乐播放器时,将屏幕锁定后,仍然可以在锁屏界面上进行音乐播放操作和显示相关的信息。 Android系统提供了相应的接口和功能,使得音乐播放器可以在锁屏界面上显示歌曲的信息,例如歌曲名称、歌手、专辑封面等。这样用户在锁屏状态下也能够方便地浏览和控制正在播放音乐。 要实现音乐播放锁屏显示,首先需要在应用程序中注册MediaSession对象。MediaSession是Android系统提供的一个用于媒体播放控制的类,它包含了与媒体播放状态相关的方法和属性。 在注册MediaSession之后,需要通过设置相应的参数,使得音乐播放器能够在锁屏界面上显示歌曲信息。可以通过设置MediaMetadata属性来指定音乐的标题、歌手、专辑封面等信息。此外,还可以通过设置MediaSessionCompat.TransportControls的方法来实现在锁屏界面上进行音乐播放操作,例如播放、暂停、上一首、下一首等。 当音乐播放器处于播放状态时,锁屏界面上将显示当前正在播放的歌曲信息。用户可以通过滑动或点击相应的控制按钮来控制音乐播放和暂停。在锁屏界面上,用户还可以通过上一首和下一首按钮来切换播放列表中的歌曲。 总而言之,Android系统提供了相应的接口和功能,使得音乐播放器可以在锁屏界面上显示歌曲信息并进行控制。这样,即使在锁屏状态下,用户也能够方便地浏览和操作正在播放音乐。 ### 回答3: Android音乐播放锁屏显示是指在锁屏界面上显示当前正在播放音乐信息,例如歌曲名称、歌手、专辑封面等。这样用户可以在不解锁屏幕的情况下,直接查看当前播放音乐信息。 要实现Android音乐播放锁屏显示,可以通过以下步骤: 1. 获取音乐播放器的控制权:在Android上,我们可以使用MediaSession来控制音乐播放和展示相关信息。通过创建一个MediaSession实例,并且调用setActive(true)来激活该会话。 2. 更新音乐信息:在播放音乐的过程中,我们可以使用MediaMetadata.Builder来构建音乐信息,如歌曲名称、歌手、专辑封面等。然后,通过调用setMetadata更新音乐信息。 3. 显示锁屏界面:当音乐播放器激活且音乐信息已经更新后,我们可以使用MediaStyle样式设置锁屏界面。通过创建一个Notification.Builder实例,并将音乐信息和相应的操作添加到通知栏中。 4. 更新通知栏:为了确保音乐信息的实时性,我们需要在音乐信息更新时更新通知栏。可以通过注册MediaSession.Callback监听音乐信息的变化,并在onMetadataChanged()回调中更新通知栏。 通过上述步骤,我们可以实现Android音乐播放锁屏显示功能,让用户能够方便地获取正在播放音乐信息,提高用户体验。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值