2013-03-21 20 views
23

Desidero creare un'applicazione Android in grado di ricevere un flusso audio. Ho pensato di utilizzare il profilo A2DP, ma sembra che Android non supporti il ​​sink A2DP. Sembra che ci siano molte persone alla ricerca di una soluzione per questo problema. Ma per quanto riguarda la ricezione di un flusso di bit ordinario e quindi convertire i dati in audio nell'applicazione? Stavo pensando di ricevere un flusso di dati PCM o Mp3 tramite RFCOMM (profilo SPP Bluetooth), quindi di riprodurlo utilizzando AudioTrack.Ricezione audio tramite Bluetooth in Android

Innanzitutto, come si riceve un flusso di bit sul mio telefono Android tramite RFCOMM? Ed è possibile ricevere un flusso di bit via RFCOMM come un flusso PCM o Mp3?

In secondo luogo, se non è possibile ricevere un flusso di bit via RFCOMM come un flusso PCM o Mp3, come posso convertire il flusso di bit ricevuto in audio?

In terzo luogo, come posso convertire i dati ricevuti in audio E riprodurre l'audio simultaneamente, in "tempo reale"? Posso usare onDataReceived?

Per essere chiari, non sono interessato all'utilizzo del profilo A2DP! Voglio trasmettere i dati tramite RFCOMM (profilo SPP Bluetooth). Il flusso di dati ricevuto sarà in PCM o Mp3. Ho pensato di scrivere la mia app, ma se qualcuno conoscesse un'app per risolverlo sarei lieto di sentirne parlare! Sto usando Android 2.3 Gingerbread.

/Johnny

+0

Hey Johnny, alcun progresso fino ad ora? ;) – Nippey

+0

Ehi! Qualche progresso? – dpaksoni

risposta

37

No. Cercando di scrivere un'applicazione Android che gestisce questo non sarà la soluzione. Almeno se si desidera utilizzare il ruolo A2DP Sink.

Il fatto è che Android, come lei ha menzionato, non implementa le chiamate API a BlueZ (lo stack bluetooth Android utilizza fino a Jelly Bean 4.1) per quanto riguarda le funzionalità A2DP sink. Devi implementarli da soli. Cercherò di guidarti, poiché anch'io ero interessato a farlo da solo nel passato prossimo.

Il dispositivo Android abilitato per Bluetooth è pubblicizzato come dispositivo A2DP source per impostazione predefinita. Devi prima modificarlo, in modo che i dispositivi vicini possano riconoscere il tuo dispositivo come un sink. Per fare questo, è necessario modificare il file di audio.conf(usally situato in /etc/bluetooth/) e assicurarsi che esista la chiave Enable e il valore Source è collegata a questa chiave, in modo da ottenere qualcosa di simile:

Enable=Source 

Reboot, dispositivi nelle vicinanze dovrebbero ora riconoscere il dispositivo come A2DP sink.

Ora sarà necessario interagire con BlueZ per reagire in modo appropriato quando un dispositivo sorgente A2DP inizierà a trasmettere l'audio al telefono.

Android e BlueZ stanno parlando tra loro tramite D-BUS. Infatti, Android si connette al canale DBUS_SYSTEM e ascolta ogni annuncio BlueZ, ad esempio eventi, descrittori di file ...

Mi ricordo di aver legato con successo me stesso utilizzando un'applicazione nativa a questo canale d-bus e ottenuto l'accesso a i vari eventi che BlueZ stava postando. Questo è relativamente facile da utilizzare come riferimento, l'API BlueZ disponibile here.Se andate in questo modo, dovrete creare un'applicazione nativa (C/C++) e compilarla per la vostra piattaforma. Devi essere in grado di farlo utilizzando Android NDK.

Se hai difficoltà a utilizzare D-BUS, puoi provare questa libreria Java che ho appena trovato che gestisce la comunicazione con D-BUS per te: http://jbluez.sourceforge.net/. Non l'ho mai usato ma vale la pena provare secondo me.

Quello che dovete veramente fare è scoprire quando un dispositivo sorgente A2DP è accoppiato al telefono e quando inizia a trasmettere musica. Puoi recuperare questi eventi tramite D-BUS. Una volta che qualcuno proverà a trasmettere musica, devi dire a BlueZ che la tua applicazione nativa lo gestirà. C'è un documento piuttosto buono che spiega il flusso di eventi che dovresti gestire per farlo. Questo documento è accessibile here. La parte che ti interessa arriva a pagina 7. L'applicazione sink nell'esempio fornito è PulseAudio ma potrebbe essere anche la tua applicazione.

BlueZ ti inoltrerà un socket UNIX quando chiamerai il metodo org.bluez.MediaTransport.Acquire. Leggendo su questo socket fornirai i dati attualmente in streaming dal dispositivo remoto. Ma ricordo che un ragazzo che lavorava allo stack BlueZ mi aveva detto che i dati letti su questo socket non erano audio puro PCM, ma contenuti audio codificati. I dati sono generalmente codificati in un formato chiamato SBC(codifica di bassa complessità di banda).

Decodifica SBC non è molto difficile, è possibile trovare un decoder right here.

Il passaggio finale sarebbe l'inoltro dell'audio PCM ai diffusori.

Per evitare di rimanere bloccati e per testare l'applicazione in modo più semplice, è possibile utilizzare il binario d-bus che dovrebbe essere disponibile sul proprio sistema Android. Si trova in /system/bin.

test rapidi si può fare prima di fare qualsiasi cosa di cui sopra potrebbe essere:

Get nell'elenco Dispositivi:

dbus-send --system --dest = org.bluez --print per Reply/ org.bluez.Manager.GetProperties

Questa restituisce un array di adattatori con loro percorsi. Una volta individuati questi percorsi, è possibile recuperare l'elenco di tutti i dispositivi Bluetooth associati al/ai proprio/i adattatore/i.

dispositivi Ricevi un accoppiati:

dbus-send --system --print-risposta --dest = org.bluez /org/bluez/{pid}/hci0 org.bluez.Adapter .GetProperties

Fornisce l'elenco dei dispositivi associati nel campo Array dispositivi.

Una volta ottenuto l'elenco dei dispositivi associati al proprio adattatore Bluetooth, è possibile sapere se è collegato all'interfaccia AudioSource.

I dispositivi collegati all'interfaccia AudioSource:

dbus-send --system --print-risposta --dest = org.bluez /org/bluez/{pid}/hci0/dev_XX_XX_XX_XX_XX_XX org.bluez.AudioSource.GetProperties org.bluez.Manager.GetProperties

Spero che questo aiuti.

+0

Fantastico! Proverò presto. Ma penso che dovrebbe essere possibile ignorare l'A2DP e usare semplicemente RFCOMM. Mi rendo conto che probabilmente finirò con l'audio mono, ma un flusso audio è in realtà un flusso di bit, non è vero? Quindi, perché non riceverlo utilizzando RFCOMM e quindi convertire il bitstream in un flusso audio PCM nella mia app? – Johnny

+1

Poiché A2DP è uno standard e viene utilizzato in modo predefinito in tutti i telefoni (vale a dire che non richiede alcuna applicazione per funzionare, dal lato client). Se decidi di utilizzare RFCOMM, avrai, credo, anche un'app client che trasmetterà l'audio dal dispositivo remoto. Se si decide di farlo, è anche possibile utilizzare la rete wifi per lo streaming audio attraverso un normale socket.Molte applicazioni nel Play Store offrono questa funzionalità. –

+0

Detto questo, se applichi le modifiche che ho citato sopra, il tuo dispositivo sink sarà unico in quanto le modifiche non saranno disponibili su tutti i telefoni Android (a meno che non incapsuli nella tua app un altro stack BlueZ usando JNI, e comunque, questo sarebbe molto difficile). Ma d'altra parte, ogni singolo dispositivo sarebbe in grado di trasmettere l'audio al lavandino. –

0

audio.conf sembra mancare in Android 4.2.2?

+1

Da Jellybean in poi, lo stack bluez viene sostituito da google nello stack bluetooth broadcomm – ashish

+0

Nella 4.1.2 avevo già menzionato il file audio.conf. Dopo aver installato AOKP 4.2.2, manca audio.config. – WoodsLink

+0

4.2.2 conterrà stack bluetooth da Broadcom, audio.conf è una parte di bluez stack [qui] (https://source.android.com/devices/bluetooth.html) – ashish

0

Per ricevere il flusso audio pcm tramite rfcomm, è possibile utilizzare il flusso del codice come suggerimento spiegato (Reading Audio file in C and forwarding over bluetooth to play in Android Audio track), con una modifica. cambiamento freq utilizzato durante l'inizializzazione da 44100 al 22050

AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM); 

Nota: Questo lo streaming consiste ancora un po 'di rumore, ma la vostra

"la ricezione di un flusso di dati PCM tramite il RFCOMM (SPP profilo Bluetooth), e poi giocare usando AudioTrack. "

funzionerà.

1

Un altro problema è l'utilizzo di HandsFreeProfile.

in Android, BluetoothHeadset ci sta lavorando. Attendi fino a quando lo stato non è cambiato in BluetoothHeadset.STATE_AUDIO_CONNECTED.

quindi è possibile registrare l'audio da cuffie 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(); 
+0

Hai il codice completo per la connessione e l'installazione Vivavoce in Android? Grazie – user8264

+0

@ user8264 "mezzo pieno" - https://developer.sony.com/develop/wearables/smarteyeglass-sdk/guides/use-bluetooth-for-audio-io/ – Nativ

1

[Irrilevante, ma funziona] Questo mod serve solo mp3 in streaming via Wi-Fi hotspot (lo uso nella mia macchina che ha solo ingresso AUX):

  1. Installare l'applicazione AirSong,
  2. Attivare l'hotspot Wi-Fi,
  3. Collegare l'altro dispositivo a quell'hotspot,
  4. Accesso 192.168.43.1:8088 dal browser del dispositivo e yo sei su

(chiedendo perché "192.168.43.1" solo? Perché questo è il gateway predefinito di qualsiasi dispositivo connesso a Android Hotspot)