Android Auto桌面主机选中歌曲后不显示播放/暂停控件问题
解决Android Auto播放控件不显示问题
问题背景
为现有MP3播放器添加Android Auto支持后,专辑封面可正常显示,点击歌曲能播放,但Auto界面仅显示“获取您的选择...”,无播放/暂停等控件,而Spotify等应用可正常显示控件。
核心问题分析
Android Auto渲染播放控件需要两个关键信息,当前代码存在缺失:
- 未同步当前播放媒体的元数据:Auto需要知道当前播放歌曲的标题、艺术家等信息才能渲染详情界面和控件
- 播放状态参数错误:固定设置播放位置为0,且部分状态更新未关联实际播放进度
- 状态与元数据不同步:播放/暂停操作后未同步更新MediaSession的元数据与状态
具体修复步骤
1. 添加媒体元数据设置方法
在MediaPlaybackService中新增方法,将当前播放歌曲的信息同步到MediaSession:
private void setCurrentMediaMetadata(SongItem songItem) { if (songItem == null || mediaSession == null) return; Uri artUri = null; if (songItem.getArtLocation() != null) { File f = new File(songItem.getArtLocation()); if (f.exists()) { artUri = Uri.parse(songItem.getArtLocation()); artUri = fileProvider.mapUri(artUri); } } MediaMetadataCompat metadata = new MediaMetadataCompat.Builder() .putString(MediaMetadataCompat.METADATA_KEY_TITLE, songItem.getName()) .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, songItem.getArtist()) .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, songItem.getAlbum()) // 若SongItem包含专辑字段则添加 .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, SONG + "_" + songItem.getTrackid()) .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, songItem.getDuration()) // 若SongItem包含时长字段则添加 .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, artUri != null ? artUri.toString() : null) .build(); mediaSession.setMetadata(metadata); }
2. 修复PlaybackState的位置参数
修改setMediaPlaybackState方法,传入实际播放位置而非固定值:
// 更新方法签名,添加position参数 private void setMediaPlaybackState(int state, long position) { PlaybackStateCompat playbackState = null; switch (state) { case PLAY: playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) .setState(PlaybackStateCompat.STATE_PLAYING, position, 1.0f) .build(); break; case PAUSE: playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE) .setState(PlaybackStateCompat.STATE_PAUSED, position, 1.0f) .build(); break; case BUFFERING: playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_STOP) .setState(PlaybackStateCompat.STATE_BUFFERING, position, 1.0f) .build(); break; case CONNECTING: playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_STOP) .setState(PlaybackStateCompat.STATE_CONNECTING, 0, 1.0f) .build(); break; case STOPPED: playbackState = new PlaybackStateCompat.Builder() .setActions(PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID) .setState(PlaybackStateCompat.STATE_STOPPED, 0, 1.0f) .build(); break; } if (playbackState != null) { mediaSession.setPlaybackState(playbackState); } }
3. 同步播放回调中的状态与元数据
修改MediaSessionCompat.Callback中的关键方法:
// 修改onPlayFromMediaId方法 @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { Log.d(TAG, "onPlayFromMediaId"); String[] tokens = mediaId.split("_"); if (tokens.length > 0) { if (mediaId.toLowerCase().equals("playlist")) { if (songItemList != null && songItemList.size() > 0) { SongItem firstSong = songItemList.get(0); mediaService.play(firstSong); setCurrentMediaMetadata(firstSong); // 同步元数据 setMediaPlaybackState(PLAY, 0); } } else { String trackIdString = tokens[1]; long trackId = Long.parseLong(trackIdString); boolean found = false; for (SongItem item : songItemList) { if (item.getTrackid() == trackId) { found = true; mediaService.play(item); setCurrentMediaMetadata(item); // 同步元数据 setMediaPlaybackState(PLAY, 0); break; } } if (!found) { Log.d(TAG, "Song item not found in list for trackId " + trackId); } } } else { Log.e(TAG,"No track id in mediaId? " + mediaId); } } // 修改onPlay方法 @Override public void onPlay() { Log.d(TAG, "onPlay called (media button pressed)"); super.onPlay(); mediaService.resume(); // 获取当前播放歌曲与进度 SongItem currentSong = mediaService.getCurrentSong(); long currentPosition = mediaService.getCurrentPosition(); if (currentSong != null) { setCurrentMediaMetadata(currentSong); setMediaPlaybackState(PLAY, currentPosition); } } // 修改onPause方法 @Override public void onPause() { Log.d(TAG, "onPause called (media button pressed)"); super.onPause(); long currentPosition = mediaService.getCurrentPosition(); setMediaPlaybackState(PAUSE, currentPosition); mediaService.pause(); }
4. 为MediaService添加状态获取方法
若MediaService没有相关方法,需补充:
// 在MediaService中添加 private SongItem currentPlayingSong; private MediaPlayer mediaPlayer; // 假设使用MediaPlayer作为播放核心 public SongItem getCurrentSong() { return currentPlayingSong; } public long getCurrentPosition() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { return mediaPlayer.getCurrentPosition(); } return 0; } // 在play方法中更新当前歌曲 public void play(SongItem song) { currentPlayingSong = song; // 原有播放逻辑 }
5. 验证automotive配置
确保res/xml/automotive_app_desc.xml正确声明媒体功能:
<?xml version="1.0" encoding="utf-8"?> <automotiveApp> <uses name="media"/> </automotiveApp>
内容的提问来源于stack exchange,提问作者user3573712
相关产品推荐
相关产品推荐

