programacion - Recibe audio vía Bluetooth en Android
manual de android en pdf (5)
¿Audio.conf parece faltar en Android 4.2.2?
Quiero crear una aplicación de Android que sea capaz de recibir una transmisión de audio. Pensé en usar el perfil A2DP, pero parece que Android no es compatible con el receptor A2DP. Parece que hay mucha gente que está buscando una solución para este problema. Pero, ¿qué hay de recibir un flujo de bits normal y luego convertir los datos en audio en la aplicación? Estaba pensando en recibir un flujo de datos PCM o Mp3 a través del RFCOMM (perfil Bluetooth SPP) y luego reproducirlo utilizando AudioTrack.
Primero, ¿cómo recibo un flujo de bits en mi teléfono Android a través del RFCOMM? ¿Y es posible recibir un flujo de bits a través de RFCOMM como un flujo PCM o Mp3?
Segundo, si no es posible recibir un flujo de bits a través de RFCOMM como un flujo PCM o Mp3, ¿cómo convierto el flujo de bits recibido en audio?
Tercero, ¿cómo convierto los datos recibidos en audio Y reproduzco el audio simultáneamente, en "tiempo real"? ¿Puedo usar onDataReceived?
Para ser claro, no estoy interesado en usar el perfil A2DP! Quiero transmitir los datos a través del RFCOMM (perfil Bluetooth SPP). El flujo de datos recibido estará en PCM o Mp3. Pensé en escribir mi propia aplicación, pero si alguien sabe de una aplicación para resolver esto, ¡me encantaría saberlo! Estoy usando Android 2.3 Gingerbread.
/ Johnny
Otra solución es usar HandsFreeProfile.
En Android, BluetoothHeadset está trabajando en eso. Espere hasta que el estado cambie a BluetoothHeadset.STATE_AUDIO_CONNECTED.
entonces puede grabar audio desde auriculares 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();
Para recibir el flujo de audio pcm a través de rfcomm, puede usar el flujo de código como una pista explicada ( Lectura de un archivo de audio en C y reenvío a través de Bluetooth para reproducir en la pista de audio de Android ), con un cambio. cambiar la frecuencia utilizada al inicializar de 44100 a 22050
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM);
Nota: esta transmisión todavía consiste en un poco de ruido, pero su
"recibiendo un flujo de datos PCM a través del RFCOMM (perfil Bluetooth SPP), y luego reproducirlo usando AudioTrack".
trabajará.
No. Intentar escribir una aplicación de Android que maneje esto no será la solución. Al menos si quieres usar el rol de A2DP Sink
.
El hecho es que Android, como usted lo mencionó, no implementa las llamadas de API a BlueZ
(la pila de bluetooth que usa Android hasta Jelly Bean 4.1) con respecto a las capacidades del A2DP sink
. Tienes que implementarlas tú mismo. Trataré de guiarlo, ya que también estaba interesado en hacerlo por mí mismo en el pasado cercano.
Su dispositivo Android habilitado para Bluetooth se anuncia de forma predeterminada como un dispositivo de A2DP source
. Primero debes cambiar esto, por lo que los dispositivos cercanos pueden reconocer tu dispositivo como un sumidero. Para hacer esto, debe modificar el archivo audio.conf (usualmente ubicado en / etc / bluetooth / ) y asegurarse de que exista la clave Enable
y que el valor Source
esté adjunto a esta clave, por lo que obtendrá algo como:
Enable=Source
Reinicie, los dispositivos cercanos ahora deben reconocer su dispositivo como un A2DP sink
.
Ahora tendrá que interactuar con BlueZ para reaccionar adecuadamente cuando un dispositivo de origen A2DP comenzará a transmitir audio a su teléfono.
Android y BlueZ están hablando entre ellos a través de D-BUS
. De hecho, Android se conecta al canal DBUS_SYSTEM y escucha cada anuncio de BlueZ, como eventos, descriptores de archivos ...
Recuerdo haberme enlazado con éxito utilizando una aplicación nativa a este canal de d-bus y tuve acceso a los diversos eventos que BlueZ estaba publicando. Esto es relativamente fácil de lograr usando como referencia, la API de BlueZ disponible here . Si sigue este camino, tendrá que crear una aplicación nativa (C / C ++) y compilarla para su plataforma. Debes poder hacer esto usando el Android NDK
.
Si le resulta difícil usar D-BUS
, puede probar esta biblioteca de Java que encontré y que maneja la comunicación con D-BUS por usted: http://jbluez.sourceforge.net/ . Nunca lo he usado pero vale la pena intentarlo en mi opinión.
Lo que realmente tiene que hacer es averiguar cuándo un dispositivo de origen A2DP está emparejado con su teléfono y cuándo comienza a transmitir música. Puede recuperar estos eventos a través de D-BUS. Una vez que alguien intente transmitir música, debe decirle a BlueZ que su aplicación nativa lo manejará. Hay un documento bastante bueno que explica el flujo de eventos que debe manejar para hacer esto. Este documento es accesible here . La parte que le interesa aparece en la página 7. La aplicación de sumidero en el ejemplo dado es PulseAudio
pero también podría ser su aplicación.
BlueZ le reenviará un socket UNIX cuando llame al método org.bluez.MediaTransport.Acquire
. La lectura en este zócalo le proporcionará los datos que el dispositivo remoto transmite actualmente. Pero recuerdo que un tipo que trabajaba en la pila de BlueZ me dijo que los datos leídos en este zócalo no son audio puro PCM, sino contenido de audio codificado. Los datos generalmente se codifican en un formato llamado SBC
(codificación de subbandas de baja complejidad) .
Decodificar SBC no es muy difícil, puedes encontrar un decodificador aquí mismo .
El último paso sería enviar el audio PCM a sus altavoces.
Para evitar que se atasque y para probar su aplicación de una manera más fácil, puede usar el binario de d-bus
que debería estar disponible en su sistema Android. Se encuentra en / system / bin .
Las pruebas rápidas que puede hacer antes de hacer algo de lo anterior podrían ser:
Obtener lista de dispositivos:
dbus-send --system --dest = org.bluez --print-reply / org.bluez.Manager.GetProperties
Esto devuelve una matriz de adaptadores con sus rutas. Una vez que tenga estas rutas, puede recuperar la lista de todos los dispositivos Bluetooth emparejados con sus adaptadores.
Consigue dispositivos emparejados:
dbus-send --system --print-reply --dest = org.bluez / org / bluez / {pid} / hci0 org.bluez.Adapter.GetProperties
Esto le da la lista de dispositivos emparejados dentro del campo de la matriz de dispositivos.
Una vez que tenga la lista de dispositivos emparejados con su adaptador Bluetooth, puede saber si está conectado a la interfaz de AudioSource.
Conecta los dispositivos a la interfaz de AudioSource:
dbus-send --sistema --print-reply --dest = org.bluez / org / bluez / {pid} / hci0 / dev_XX_XX_XX_XX_XX_XX org.bluez.AudioSource.GetProperties org.bluez.Manager.GetProperties
Espero que esto ayude.
[Irrelevante, pero funciona] Este truco solo sirve para la transmisión de mp3 a través de un punto de acceso WIFI (lo uso en mi auto que solo tiene entrada AUX):
- Instala la aplicación AirSong ,
- Encienda el punto de acceso wifi,
- Conecte el otro dispositivo a ese punto de acceso,
- Acceda a 192.168.43.1:8088 desde el navegador del dispositivo y ya está.
(¿Se pregunta por qué "192.168.43.1" solamente? Porque esa es la puerta de enlace predeterminada de cualquier dispositivo conectado a un hotspot de Android)