hsp activar android bluetooth a2dp avrcp

android - activar - bluetooth avrcp version



enviar información de la pista a través de A2DP/AVRCP (5)

Este código funcionó para mí:

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

Llame a bluetoothNotifyChange con la intención apropiada (definida arriba) dependiendo de su estado de reproducción: pausa / reproducción / cambio de metadatos.

Estoy tratando de enviar información de pista a través de A2DP / AVRCP. En este momento, la música se transmite perfectamente, pero en el "receptor" (es decir, en el audio del automóvil), la "pantalla de información de la pista" está en blanco (lo cual no es el caso de los reproductores populares). Alguna idea ?


Esto me tomó una eternidad para averiguar. Simplemente transmitir la intención no funcionó. Conseguí que AVRCP funcionara enviando la intención Y implementando RemoteControlClient

Aquí está el código que utilicé:

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


No es necesario controlar SDK_INT si está utilizando la versión de componentes de Compat. A continuación se prueba el código con muchos dispositivos Bluetooth para automóvil y funciona a la perfección. Algunos dispositivos no entienden algunas CLAVES, por lo que es mejor usar una CLAVE posible. Reference . No te olvides de .build () después de putBitmap no antes

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

}


Para enviar los metadatos de la pista a la unidad central, debe enviar un intento.

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

Cuando la canción haya terminado de reproducirse, envíe otro intento con cadenas vacías para el segundo parámetro del método putExtra.


Si solo desea enviar información de metadatos desde su teléfono a un dispositivo bluetooth de audio compatible con AVRCP conectado y NO desea controlar su aplicación desde el dispositivo bluetooth, puede encontrar útil el siguiente código. Y NO hay necesidad de implementar y registrar un MediaButtonEventReceiver con AudioManager.

También incluí el código para la versión 21 de API (LOLLIPOP, 5.0). Desde API 21, el uso de RemoteControlClient está en desuso y se MediaSession uso de MediaSession .

Fase inicial:

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

Método para enviar información de metadatos de canciones a dispositivos de audio Bluetooth compatibles con AVRCP:

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

Llame si los metadatos cambian, pero verifique si tenemos una conexión A2DP a un dispositivo de audio bluetooth. No es necesario enviar información de metadatos si no estamos conectados:

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

Limpiar en destruir:

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

This es como se ve en el estéreo de mi auto.