如何为音乐应用实现支持锁屏控制面板的Media Session功能?
Android 锁屏媒体控制面板实现示例(基于MediaSession)
以下是适配主流Android版本的完整实现步骤,所有代码可直接在项目中复用调整:
1. 声明必要权限
首先在AndroidManifest.xml中添加所需权限:
<!-- 媒体播放前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> <!-- Android 13+ 通知显示权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
2. 初始化MediaSession
在音乐播放对应的前台Service中完成MediaSession初始化,配置支持的操作和事件回调:
// 音乐播放Service类内定义成员变量 private MediaSession mediaSession; private long supportActions; private void initMediaSession() { ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class); mediaSession = new MediaSession(getApplicationContext(), "MusicAppSession", mediaButtonReceiver, null); // 声明支持的控制操作 supportActions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SEEK_TO; mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); // 接收用户在锁屏/通知栏触发的操作 mediaSession.setCallback(new MediaSession.Callback() { @Override public void onPlay() { // 执行播放逻辑 } @Override public void onPause() { // 执行暂停逻辑 } @Override public void onSkipToNext() { // 切换下一首逻辑 } @Override public void onSkipToPrevious() { // 切换上一首逻辑 } @Override public void onSeekTo(long pos) { // 调整播放进度逻辑 } }); mediaSession.setActive(true); }
3. 同步播放状态与歌曲信息
播放状态变化、切换歌曲时需要主动更新MediaSession的状态,锁屏信息会自动同步:
// 更新播放状态 private void updatePlayState(boolean isPlaying, long currentPosition, float playSpeed) { PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder() .setActions(supportActions) .setState(isPlaying ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED, currentPosition, playSpeed); mediaSession.setPlaybackState(stateBuilder.build()); } // 更新当前歌曲元数据 private void updateSongMeta(SongInfo currentSong) { MediaMetadataCompat.Builder metaBuilder = new MediaMetadataCompat.Builder(); metaBuilder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, currentSong.getTitle()) .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, currentSong.getArtist()) .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, currentSong.getDuration()) // 专辑封面建议控制在300*300px以内,避免被系统截断 .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, currentSong.getAlbumArt()); mediaSession.setMetadata(metaBuilder.build()); }
4. 绑定前台服务通知
Android系统要求媒体播放应用必须使用前台服务,才能在锁屏展示控制面板,需要配合MediaStyle通知实现:
private Notification buildMediaNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "MUSIC_PLAY_CHANNEL"); builder.setContentTitle(currentSong.getTitle()) .setContentText(currentSong.getArtist()) .setLargeIcon(currentSong.getAlbumArt()) .setSmallIcon(R.drawable.ic_music_play) .setContentIntent(getPlayPagePendingIntent()) // 绑定MediaSession实现锁屏状态同步 .setStyle(new androidx.media.app.NotificationCompat.MediaStyle() .setMediaSession(mediaSession.getSessionToken()) // 配置紧凑模式下显示的按钮索引 .setShowActionsInCompactView(0,1,2)); // 添加控制按钮 builder.addAction(new NotificationCompat.Action(R.drawable.ic_prev, "上一首", getActionPendingIntent(ACTION_PREV))); builder.addAction(new NotificationCompat.Action(isPlaying ? R.drawable.ic_pause : R.drawable.ic_play, "播放/暂停", getActionPendingIntent(ACTION_PLAY_PAUSE))); builder.addAction(new NotificationCompat.Action(R.drawable.ic_next, "下一首", getActionPendingIntent(ACTION_NEXT))); return builder.build(); } // 启动前台服务 startForeground(1001, buildMediaNotification());
注意事项
- 服务销毁时必须调用
mediaSession.release()释放资源,避免内存泄漏 - 小米、华为等定制ROM需要引导用户手动开启应用的「锁屏显示」权限,否则控制面板不会展示
- Android 12及以上系统对锁屏控件的样式做了统一适配,无需额外调整布局
内容的提问来源于stack exchange,提问作者Maksym Tsikal
相关产品推荐
相关产品推荐

