通过A2DP / AVRCP发送曲目信息

我试图通过A2DP / AVRCP发送曲目信息。 现在,音乐完美stream畅,但在“接收器”(即:汽车音响)上,“曲目信息屏幕”是空白的(这不是使用stream行的播放器的情况)。 任何想法 ?

Solutions Collecting From Web of "通过A2DP / AVRCP发送曲目信息"

这段代码适用于我:

private static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; private static final String AVRCP_META_CHANGED = "com.android.music.metachanged"; private void bluetoothNotifyChange(String what) { Intent i = new Intent(what); i.putExtra("id", Long.valueOf(getAudioId())); i.putExtra("artist", getArtistName()); i.putExtra("album",getAlbumName()); i.putExtra("track", getTrackName()); i.putExtra("playing", isPlaying()); i.putExtra("ListSize", getQueue()); i.putExtra("duration", duration()); i.putExtra("position", position()); sendBroadcast(i); } 

根据您的播放状态,用适当的意图(定义如上)调用bluetoothNotifyChange:暂停/播放/元数据已更改。

如果你只是想从你的手机发送元数据信息到一个连接的AVRCP兼容的audio蓝牙设备,而不想从蓝牙设备控制你的应用程序,你可能会发现下面的代码有用。 并且不需要用AudioManager实现和注册MediaButtonEventReceiver。

我还包括API版本21(LOLLIPOP,5.0)的代码。 从API 21不再推荐使用RemoteControlClient,并鼓励使用MediaSession 。

初始阶段:

  if (mAudioManager == null) { mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (mRemoteControlClient == null) { Log.d("init()", "API " + Build.VERSION.SDK_INT + " lower then " + Build.VERSION_CODES.LOLLIPOP); Log.d("init()", "Using RemoteControlClient API."); mRemoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(this, 0, new Intent(Intent.ACTION_MEDIA_BUTTON), 0)); mAudioManager.registerRemoteControlClient(mRemoteControlClient); } } else { if (mMediaSession == null) { Log.d("init()", "API " + Build.VERSION.SDK_INT + " greater or equals " + Build.VERSION_CODES.LOLLIPOP); Log.d("init()", "Using MediaSession API."); mMediaSession = new MediaSession(this, "PlayerServiceMediaSession"); mMediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); mMediaSession.setActive(true); } } 

将歌曲元数据信息发送给兼容AVRCP的蓝牙audio设备的方法:

 private void onTrackChanged(String title, String artist, String album, long duration, long position, long trackNumber) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { RemoteControlClient.MetadataEditor ed = mRemoteControlClient.editMetadata(true); ed.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title); ed.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist); ed.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album); ed.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration); ed.putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, trackNumber); ed.apply(); mRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING, position, 1.0f); } else { MediaMetadata metadata = new MediaMetadata.Builder() .putString(MediaMetadata.METADATA_KEY_TITLE, title) .putString(MediaMetadata.METADATA_KEY_ARTIST, artist) .putString(MediaMetadata.METADATA_KEY_ALBUM, album) .putLong(MediaMetadata.METADATA_KEY_DURATION, duration) .putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, trackNumber) .build(); mMediaSession.setMetadata(metadata); PlaybackState state = new PlaybackState.Builder() .setActions(PlaybackState.ACTION_PLAY) .setState(PlaybackState.STATE_PLAYING, position, 1.0f, SystemClock.elapsedRealtime()) .build(); mMediaSession.setPlaybackState(state); } } 

如果元数据更改,则调用,但检查是否有A2DP连接到audio蓝牙设备。 如果我们没有连接,则无需发送元数据信息:

 if (mAudioManager.isBluetoothA2dpOn()) { Log.d("AudioManager", "isBluetoothA2dpOn() = true"); onTrackChanged(getTitle(), getArtist(), getAlbum(), getDuration(), getCurrentPosition(), getId()); } 

清理摧毁:

 @Override public void onDestroy() { super.onDestroy(); [..] if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { mAudioManager.unregisterRemoteControlClient(mRemoteControlClient); } else { mMediaSession.release(); } } 

这是我的汽车音响上的样子

这使我永远不知所措。 只是广播意图没有奏效。 我通过发送意图实现RemoteControlClient来获得AVRCP的工作

这是我使用的代码:

 public void onCreate(){ super.onCreate(); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); ComponentName rec = new ComponentName(getPackageName(), MyReceiver.class.getName()); mAudioManager.registerMediaButtonEventReceiver(rec); Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON); i.setComponent(rec); PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0); mRemoteControlClient = new RemoteControlClient(pi); mAudioManager.registerRemoteControlClient(mRemoteControlClient); int flags = RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT | RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_STOP | RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD | RemoteControlClient.FLAG_KEY_MEDIA_REWIND; mRemoteControlClient.setTransportControlFlags(flags); } private void onTrackChanged(...) { String title = ...; String artist = ...; String album = ...; long duration = ...; Intent i = new Intent("com.android.music.metachanged"); i.putExtra("id", 1); i.putExtra("track", title); i.putExtra("artist", artist); i.putExtra("album", album); i.putExtra("playing", "true"); sendStickyBroadcast(i); RemoteControlClient.MetadataEditor ed = mRemoteControlClient.editMetadata(true); ed.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title); ed.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album); ed.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist); ed.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, track.getDuration()); ed.apply(); } public void onDestroy(){ mAudioManager.unregisterRemoteControlClient(mRemoteControlClient); super.onDestroy(); } 

要将轨道元数据发送到headunit,您需要发送一个intent。

 Intent avrcp = new Intent("com.android.music.metachanged"); avrcp.putExtra("track", "song title"); avrcp.putExtra("artist", "artist name"); avrcp.putExtra("album", "album name"); Context.sendBroadcast(avrcp); 

当歌曲完成播放发送putExtra方法的第二个参数的空string的另一个意图。

如果您使用Compat版本的组件,则不需要控制SDK_INT。 下面的代码与许多车载蓝牙设备进行testing,像魅力工作。 有些设备不理解一些密钥,所以最好使用可能的密钥。 参考 。 不要忘记putBitmap之前.build()之前

 public static void sendTrackInfo() { if(audioManager == null) { audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); } if (mMediaSession == null) { mMediaSession = new MediaSessionCompat(this, "PlayerServiceMediaSession"); mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mMediaSession.setActive(true); } if (audioManager.isBluetoothA2dpOn()) { try { String songTitle = getTitle(); String artistTitle = getArtist(); String radioImageUri = getImagesArr().get(0); String songImageUri = getImagesArr().get(1); long duration = getDuration(); final MediaMetadataCompat.Builder metadata = new MediaMetadataCompat.Builder(); metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, songTitle); metadata.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, songTitle); metadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artistTitle); metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ARTIST, artistTitle); metadata.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, radioImageUri); metadata.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, radioImageUri); metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, songImageUri); metadata.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration); imageCounter = 0; Glide.with(act) .load(Uri.parse(radioImageUri)) .asBitmap() .into(new SimpleTarget<Bitmap>(250, 250) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap); metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, bitmap); imageCounter = imageCounter + 1; if(imageCounter == 2) { mMediaSession.setMetadata(metadata.build()); } } }); Glide.with(act) .load(Uri.parse(songImageUri)) .asBitmap() .into(new SimpleTarget<Bitmap>(250, 250) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap); imageCounter = imageCounter + 1; if(imageCounter == 2) { mMediaSession.setMetadata(metadata.build()); } } }); } catch (JSONException e) { e.printStackTrace(); } } 

}