A2DP/AVRCP 経由でトラック情報を送信しようとしています。現在、音楽は完全にストリーミングされていますが、「受信機」(つまり、カーオーディオ) では、「トラック情報画面」は空白です (これは、一般的なプレーヤーを使用する場合とは異なります)。何か案が ?
5 に答える
このコードは私のために働いた:
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 互換のオーディオ bluetooth デバイスにメタデータ情報を送信するだけで、bluetooth デバイスからアプリを制御したくない場合は、以下のコードが役立つ場合があります。MediaButtonEventReceiver を実装してAudioManagerに登録する必要はありません。
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 対応の Bluetooth オーディオ デバイスに送信する方法:
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);
}
}
メタデータが変更された場合に呼び出しますが、オーディオ Bluetooth デバイスへの A2DP 接続があるかどうかを確認します。接続されていない場合、メタデータ情報を送信する必要はありません:
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();
}
トラック メタデータをヘッドユニットに送信するには、インテントを送信する必要があります。
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 メソッドの 2 番目のパラメーターに空の文字列を指定して別のインテントを送信します。