Recevoir l'audio via Bluetooth sur Android
je veux créer une application Android qui est capable de recevoir un flux audio. J'ai pensé à utiliser le profil A2DP, mais il semble que Android ne supporte pas A2DP sink. On dirait qu'il y a beaucoup de gens qui cherchent une solution à ce problème. Mais qu'en est-il de recevoir un flux de bits ordinaire, puis convertir les données en audio dans l'application? Je pensais recevoir un flux de données PCM ou Mp3 via le RFCOMM (profil Bluetooth SPP), puis le lire à l'aide de AudioTrack.
tout d'abord, comment puis-je recevoir un flux de bits sur mon téléphone Android via le RFCOMM? Et est-il possible de recevoir un flux de bits via RFCOMM comme un flux PCM ou Mp3?
Deuxièmement, s'il n'est pas possible de recevoir un flux de bits via RFCOMM comme un flux PCM ou Mp3, Comment puis-je convertir le flux de bits reçu en audio?
Troisièmement, Comment puis-je convertir les données reçues en audio et lire l'audio simultanément, en "temps réel"? Peut J'utilise juste onDataReceived?
pour être clair, Je ne suis pas intéressé d'utiliser le profil A2DP! Je veux diffuser les données via le RFCOMM (profil Bluetooth SPP). Le flux de données reçu sera en PCM ou Mp3. J'ai pensé à écrire ma propre application, mais si quelqu'un connaît une application pour résoudre cela, je serais heureux de l'entendre! J'utilise Android 2.3 Gingerbread.
/ Johnny
5 réponses
Pas de. essayer d'écrire une application Android qui gère ce ne sera pas la solution. Au moins si vous voulez utiliser A2DP Sink
rôle.
le fait est que Android, comme vous l'avez mentionné, ne met pas en œuvre les appels API à BlueZ
(la pile de bluetooth Android utilise till Jelly Bean 4.1) concernant les capacités A2DP sink
. Vous devez les mettre en œuvre vous-même. Je vais essayez de vous guider, car j'étais aussi intéressé à le faire moi-même dans un passé proche.
votre appareil Android compatible bluetooth se présente comme un appareil A2DP source
par défaut. Vous devez changer cela d'abord, de sorte que les appareils à proximité peuvent reconnaître votre appareil comme un évier. Pour ce faire, vous devez modifier l'audio .conf fichier (normalement situé dans /etc/bluetooth/ ) et assurez-vous que la clé Enable
existe et que la valeur Source
est attachée à cette clé, de sorte que vous obtiendrez quelque chose comme:
Enable=Source
Redémarrage, les appareils à proximité doivent maintenant reconnaître votre appareil comme un A2DP sink
.
Maintenant, vous devrez interagir avec BlueZ pour réagir de manière appropriée quand un périphérique source A2DP commencera à diffuser de l'audio vers votre téléphone.
Android et BlueZ se parlent via D-BUS
. En fait, Android se connecte au canal dbus _SYSTEM et écoute chaque publicité BlueZ, tels que les événements, les descripteurs de fichiers ...
je me souviens avoir relié avec succès mon auto en utilisant une application native à ce canal de D-bus et j'ai eu accès aux divers événements que BlueZ postait. Ceci est relativement facile à réaliser en utilisant comme référence, L'API BlueZ disponible ici . Si vous allez de cette façon, vous devrez construire une application native (C / C++) et compilez - le pour votre plateforme. Vous devez pouvoir le faire en utilisant le Android NDK
.
si vous trouvez qu'il est difficile d'utiliser D-BUS
, vous pouvez essayer cette bibliothèque Java que je viens de trouver qui gère la communication à D-BUS pour vous : http://jbluez.sourceforge.net / . Je ne l'ai jamais utilisé, mais il vaut la peine d'essayer, à mon avis.
ce que vous avez vraiment à faire est de savoir quand un périphérique source A2DP est jumelé à votre téléphone et quand il commence à diffuser de la musique. Vous pouvez récupérer ces événements par D-BUS. Une fois que quelqu'un essaiera de diffuser de la musique, vous devez dire à BlueZ que votre application native va s'en charger. Il y a un assez bon document qui explique le flux des événements que vous devriez gérer pour faire cela. Ce document est accessible ici . La partie qui vous intéresse est à la page 7. L'application de récepteur dans l'exemple donné est PulseAudio
mais ce pourrait être votre demande bien.
BlueZ vous enverra un socket UNIX lorsque vous appellerez la méthode org.bluez.MediaTransport.Acquire
. Lecture sur la socket vous donnera les données qui sont actuellement acheminés par le périphérique distant. Mais je me souviens avoir été informé par un gars travaillant sur la pile BlueZ que les données lues sur cette socket ne sont pas de L'audio PCM pur, mais du contenu audio encodé à la place. Les données sont généralement codées dans un format appelé SBC
(codage à bande étroite de faible complexité) .
Décodage SBC n'est pas très difficile, vous pouvez trouver un décodeur ici .
L'étape ultime serait de transmettre l'audio PCM à vos haut-parleurs.
pour vous empêcher d'être coincé et afin de tester votre application d'une manière plus facile, vous pouvez utiliser le binaire d-bus
qui devrait être disponible sur votre système Android. Il est situé dans / system / bin .
tests Rapides vous pouvez faire avant de faire quoi que ce soit de la ci-dessus pourrait être :
Obtenir la liste des Périphériques :
dbus-send -- system --dest = org.bluez-imprimer-répondre / org.bluez.Gestionnaire.GetProperties
cela renvoie une série d'adaptateurs avec leurs chemins. Une fois que vous avez ces chemin(s), vous pouvez récupérer la liste de tous les périphériques bluetooth jumelé avec votre carte(s).
Obtenir des appareils appariés :
dbus-send --system --print-réponse --dest=org.bluez / org / bluez / {pid} / hci0 org.bluez.Adaptateur.GetProperties
cela vous donne la liste des appareils appariés dans le champ Devices array.
une fois que vous avez la liste des appareils appariés à votre Bluetooth Adaptateur, vous pouvez savoir s'il est connecté à L'interface AudioSource.
connectez les appareils à L'interface AudioSource:
dbus-send --system --print-réponse --dest=org.bluez / org/bluez / {pid}/hci0 / dev_XX_XX_XX_XX_XX_XX org.bluez.AudioSource.GetProperties org.bluez.Gestionnaire.GetProperties
Espérons que cette aide.
un autre travail autour utilise HandsFreeProfile.
sur Android, BluetoothHeadset travaille là-dessus. Attendez que le statut change pour BluetoothHeadset.STATE_AUDIO_CONNECTED.
ensuite, vous pouvez enregistrer l'audio à partir du casque bluetooth.
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(mFilename);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.start();
[Non pertinent mais fonctionne] ce hack sert uniquement le streaming mp3 via un hotspot WIFI (Je l'utilise dans ma voiture qui n'a QU'une entrée AUX):
- Installer l'application AirSong ,
- Activer le wifi hotspot,
- connecter l'autre dispositif à ce hotspot,
- accédez à 192.168.43.1: 8088 à partir du navigateur de l'appareil et vous êtes activé.
(se demandant pourquoi" 192.168.43.1 " seulement? parce que c'est la passerelle par défaut de tout périphérique connecté à Android Hotspot)
pour recevoir le flux audio pcm via rfcomm , vous pouvez utiliser le flux de code comme un indice expliqué ( lecture de fichier Audio en C et transfert sur bluetooth pour jouer dans la piste audio Android ), avec un changement . changer freq utilisé lors de l'initialisation de 44100 à 22050
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM);
note:Ce streaming consiste toujours en un peu de bruit mais votre
" recevant un flux de données PCM via le RFCOMM (profil Bluetooth SPP), et alors joue avec AudioTrack."
fonctionnera.