2013-03-20 15 views
22

私はA2DP/AVRCP経由でトラック情報を送信しようとしています。現在、音楽は完全にストリーミングされていますが、「レシーバ」(カーオーディオ)では「トラック情報の画面」は空白です(一般的なプレーヤーを使用しているケースではありません)。 A2DP/AVRCP経由でトラック情報を送信

答えて

18

このコードは、私の仕事:

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あなたの再生状況に応じて適切な意思(上記に定義)で:一時停止/再生/メタデータを変更しました。

+0

このコードは私のブルートゥースヘッドセットで動作しますが、トラック名のみを表示します...もっとテストします。どうも。 – DavyJonesUA

+0

このコードはソニーのヘッドセットでは機能しませんでしたが、Googleミュージックアプリでもそのヘッドセットの曲情報を表示できます。 – Wayne

+0

利用可能なメタデータのサンプルリンクを教えてもらえますか? – Wayne

1

トラックのメタデータをヘッドユニットに送信するには、インテントを送信する必要があります。

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番目のパラメータに別のインテントを空の文字列で送信します。

+1

前に()を構築します。それはハックのようなアプローチのようです。この意図を処理するためにGoogleミュージックアプリに依存しているようです。 googleの音楽アプリはそれをどのようにしますか? –

+0

確かに。 googleの音楽がavrcpを使用できる唯一のものである可能性はありますか?すべてのアプリはRemoteControlClientの権限でこの機能を備えている必要がありますか? –

6

これは私を永遠に理解するのに苦労しました。意図を放送するだけでは機能しませんでした。あなただけの接続AVRCP対応のオーディオBluetoothデバイスにお使いの携帯電話からのメタデータ情報を送信する場合は

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(); 
} 
+0

'ComponentName rec = new ComponentName(getPackageName()、MyReceiver.class.getName()); ' – Distwo

+0

それはあなたが反射を使ってBroadcastReceiverを見上げる方法です... –

+0

私はコードを試しました。これは確かにhttps://android.googlesource.com/platform/packages/apps/Music/+/androidで見つかるものと一致しています-5.1.1_r13/src/com/android/music/MediaPlaybackService.javaですが、これは機能しません。 AudioManager.AUDIOFOCUSを処理する必要があるためでしょうか? –

10

:私はAVRCPはRemoteControlClient

を実装する意図を送信することで動作するようになったここで私が使用するコードですあなたのアプリをBluetoothデバイスから制御したい場合は、以下のコードを参考にしてください。 は、AudioManagerにMediaButtonEventReceiverを実装して登録する必要があります。

APIバージョン21(LOLLIPOP、5.0)のコードも含まれています。 API21からRemoteControlClientの使用は推奨されず、MediaSessionの使用が推奨されています。

初期化フェーズ:Bluetooth対応のオーディオデバイスをAVRCPする曲のメタデータ情報を送信するための

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

     } 
    } 

方法:

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

Thisあなたは必要としない私のカーステレオ

+0

シャッフルリピートモードはどうですか?これも処理しましたか?ありがとう – issamux

+0

@issamuxこれを見てくださいhttp://stackoverflow.com/questions/31194180/how-do-i-make-shuffle-playlist-button-and-repeat-button-in-android-studio –

0

のように、それがどのように見えるかです互換バージョンのコンポーネントを使用している場合はSDK_INTを制御します。 以下のコードは多くの車のBluetoothデバイスでテストされ、魅力的に機能します。 いくつかのデバイスはいくつかのKEYを理解していないので、可能なKEYを使用することをお勧めします。 Reference。に忘れないでください。私はこれを行うための別の方法を発見していないもののputBitmap後のない

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

}

関連する問題