2013-03-21 32 views
23

Chcę utworzyć aplikację dla systemu Android, która może odbierać strumień audio. Myślałem o korzystaniu z profilu A2DP, ale wygląda na to, że Android nie obsługuje zlewu A2DP. Wygląda na to, że wiele osób szuka rozwiązania tego problemu. Ale co z otrzymywaniem zwykłego strumienia bitów, a następnie konwersją danych na dźwięk w aplikacji? Myślałem o odbiorze strumienia danych PCM lub Mp3 za pośrednictwem RFCOMM (profil SPP Bluetooth), a następnie odtwarzam go za pomocą funkcji AudioTrack.Odbieranie dźwięku przez Bluetooth w Androidzie

Po pierwsze, w jaki sposób mogę odbierać strumień bitów na moim telefonie z Androidem za pośrednictwem RFCOMM? I czy można odbierać strumień bitów za pośrednictwem RFCOMM jako strumień PCM lub Mp3?

Po drugie, jeśli nie można odbierać strumienia bitów przez RFCOMM jako strumień PCM lub Mp3, w jaki sposób mogę przekonwertować odebrany strumień bitów na dźwięk?

Po trzecie, w jaki sposób mogę przekonwertować odebrane dane na dźwięk I jednocześnie odtwarzać dźwięk w "czasie rzeczywistym"? Czy mogę po prostu użyć onDataReceived?

Dla jasności nie jestem zainteresowany wykorzystaniem profilu A2DP! Chcę przesyłać strumieniowo dane przez RFCOMM (profil SPP Bluetooth). Otrzymany strumień danych będzie w PCM lub Mp3. Pomyślałem o napisaniu własnej aplikacji, ale jeśli ktoś wie o aplikacji, która to rozwiąże, chętnie się o tym dowiem! Używam Androida Gingerbread.

/Johnny

+0

Hey Johnny, wszelkiego postępu tak daleko? ;) – Nippey

+0

Hej! Jakiś postęp? – dpaksoni

Odpowiedz

37

nr Próbuje napisać aplikację Android, który obsługuje ten nie będzie rozwiązaniem. Przynajmniej jeśli chcesz użyć roli A2DP Sink.

Faktem jest, że Android, jak już wspomniano, nie implementuje wywołań API do BlueZ (stos bluetooth Android używa do Jelly Bean 4.1) w odniesieniu do możliwości A2DP sink. Musisz je wdrożyć samodzielnie. Spróbuję cię poprowadzić, ponieważ byłem również zainteresowany robieniem tego w niedalekiej przeszłości.

Twoje urządzenie z Androidem z obsługą bluetooth domyślnie reklamuje się jako urządzenie A2DP source. Musisz to najpierw zmienić, aby urządzenia w pobliżu mogły rozpoznać twoje urządzenie jako zlew. Aby to zrobić, należy zmodyfikować audio.conf plik (zwykle zatrzymujemy się w /etc/bluetooth/) i upewnij się, że klucz Enable istnieje i wartość Source jest dołączony do tego klucza, więc będzie coś takiego:

Enable=Source 

Reboot, w pobliżu urządzenia powinny teraz rozpoznaje urządzenie jako A2DP sink.

Teraz będziesz musiał nawiązać kontakt z BlueZ, aby odpowiednio zareagować, gdy urządzenie źródłowe A2DP rozpocznie przesyłanie dźwięku do telefonu.

Android i BlueZ rozmawiają ze sobą przez D-BUS. W rzeczywistości Android łączy się z kanałem DBUS_SYSTEM i słucha każdej reklamy BlueZ, takiej jak zdarzenia, deskryptory plików ...

Pamiętam, że udało mi się powiązać moje własne przy użyciu natywnej aplikacji z tym kanałem D-Bus i uzyskać dostęp do różne wydarzenia, które opublikował BlueZ. Jest to stosunkowo łatwe do osiągnięcia przy użyciu jako odniesienia, dostępny interfejs API BlueZ here.Jeśli pójdziesz tą drogą, będziesz musiał zbudować natywną aplikację (C/C++) i skompilować ją dla swojej platformy. Musisz to zrobić, używając Android NDK.

Jeśli korzystanie z D-BUS jest utrudnione, możesz wypróbować tę bibliotekę Java, którą właśnie znalazłem i która obsługuje komunikację z D-BUS: http://jbluez.sourceforge.net/. Nigdy go nie używałem, ale warto spróbować w mojej opinii.

To, co naprawdę musisz zrobić, to dowiedzieć się, kiedy urządzenie źródłowe A2DP jest sparowane z telefonem i kiedy zaczyna odtwarzać muzykę. Możesz pobrać te zdarzenia przez D-BUS. Gdy ktoś spróbuje przesyłać strumieniowo muzykę, musisz powiedzieć BlueZ, że Twoja aplikacja natywna sobie z tym poradzi. Istnieje całkiem niezły dokument wyjaśniający przebieg zdarzeń, które należy wykonać, aby to zrobić. Ten dokument jest dostępny pod numerem here. Część, która Cię interesuje, znajduje się na stronie 7. Aplikacja zlewozmywakowa w tym przykładzie to PulseAudio, ale może to być również twoja aplikacja.

BlueZ przekaże ci gniazdo UNIX, gdy zadzwonisz na metodę org.bluez.MediaTransport.Acquire. Odczyt w tym gnieździe daje dane, które są aktualnie przesyłane strumieniowo przez urządzenie zdalne. Ale pamiętam, że ktoś, kto pracował na stosie BlueZ, powiedział, że dane odczytane z tego gniazda nie są czystym dźwiękiem PCM, lecz zakodowaną treścią audio. Dane są ogólnie kodowane w formacie zwanym SBC(kodowanie podpasma o niskiej złożoności).

Dekodowanie SBC nie jest trudne, można znaleźć dekoder right here.

Ostatecznym krokiem byłoby przekazanie dźwięku PCM do głośników.

Aby zapobiec utknięciu i łatwiej przetestować aplikację, można użyć pliku binarnego d-bus, który powinien być dostępny w systemie Android. Znajduje się w /system/bin.

Szybkie testy można zrobić zanim cokolwiek z powyższych może być:

Get listy urządzeń:

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

Powoduje wyświetlenie tablicy adapterów z ich ścieżkami. Po uzyskaniu tych ścieżek możesz pobrać listę wszystkich urządzeń bluetooth sparowanych z twoimi adapterami.

Get sparowane:

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

Daje to listę sparowanych urządzeń, które znajdują się w polu Tablica urządzeń.

Po zestawieniu urządzeń sparowanych z adapterem Bluetooth można sprawdzić, czy jest on podłączony do interfejsu AudioSource.

Get urządzenia podłączone do interfejsu AudioSource:

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

nadzieję, że to pomaga.

+0

Awesome! Wypróbuję to wkrótce. Ale myślę, że powinno być możliwe zignorowanie A2DP i po prostu użycie RFCOMM. Zdaję sobie sprawę, że prawdopodobnie otrzymam tylko mono audio, ale strumień audio jest w rzeczywistości strumieniem bitów, czyż nie? Dlaczego więc nie otrzymać go za pomocą RFCOMM, a następnie przekonwertować strumień bitów do strumienia audio PCM w mojej aplikacji? – Johnny

+1

Ponieważ A2DP jest standardem i jest używany domyślnie w każdym telefonie (tj. Nie wymaga żadnej aplikacji do pracy, po stronie klienta). Jeśli zdecydujesz się na korzystanie z RFCOMM, będziesz mieć, jak sądzę, udostępnienie aplikacji klienckiej, która będzie przesyłała dźwięk ze zdalnego urządzenia. Jeśli zdecydujesz się to zrobić, możesz również użyć wifi do strumieniowego przesyłania dźwięku przez zwykłe gniazdo.Wiele aplikacji w Sklepie Play zapewnia taką funkcję. –

+0

W związku z powyższym, jeśli zastosujesz zmiany, o których wspomniałem powyżej, urządzenie zlewozmywakowe będzie unikatowe, ponieważ zmiany nie będą dostępne na wszystkich telefonach z Androidem (chyba że zaaplikujesz w swojej aplikacji inny stos BlueZ przy użyciu JNI, a mimo to będzie to bardzo trudne). Z drugiej jednak strony każde urządzenie byłoby w stanie przesyłać dźwięk do zlewu. –

0

Wygląda na to, że audio.conf brakuje w systemie Android 4.2.2?

+1

Począwszy od Jellybean, stos bluez zostaje zastąpiony przez google do pakietu bluetooth broadcomm – ashish

+0

W 4.1.2 miałem wspomniany wyżej plik audio.conf. Po zainstalowaniu AOKP 4.2.2 brakuje pliku audio.config. – WoodsLink

+0

4.2.2 zawiera pakiet bluetooth od Broadcom, audio.conf jest częścią pakietu bluez [tutaj] (https://source.android.com/devices/bluetooth.html) – ashish

0

Aby odbierać strumień audio pcm za pośrednictwem rfcomm, można użyć przepływu kodu jako wyjaśnienia podpowiedzi (Reading Audio file in C and forwarding over bluetooth to play in Android Audio track) ze zmianą. Zmiana freq używane podczas inicjowania od 44100 do 22050

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

Uwaga: Ta strumieniowe nadal składa się trochę hałasu, ale twój „odbieranie strumienia danych PCM poprzez RFCOMM (SPP profil Bluetooth)

, a następnie odtworzyć używając AudioTrack. "

będzie działać.

1

Innym zadaniem jest używanie HandsFreeProfile.

w Androidzie, działa na nim BluetoothHeadset. Poczekaj, aż status zostanie zmieniony na BluetoothHeadset.STATE_AUDIO_CONNECTED.

następnie można nagrywać dźwięk z zestawu słuchawkowego 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

Czy masz pełny kod do połączenia i konfiguracji Zestaw głośnomówiący w systemie Android? Dziękujemy – user8264

+0

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

1

[nieistotne, ale działa] Ten Hack służy tylko mp3 strumieniowego przez WiFi hotspot (używam go w moim samochodzie, który ma tylko wejście AUX):

  1. zainstalować aplikację AirSong,
  2. Włącz hotspot Wi-Fi,
  3. Podłącz drugie urządzenie do tego hotspotu,
  4. Uzyskaj dostęp 192.168.43.1:8088 z przeglądarki urządzenia i tak jesteście na.

(zastanawiając się dlaczego "192.168.43.1" tylko? Bo ów domyślną bramę dowolnego urządzenia podłączonego do Android Hotspot)

Powiązane problemy