オーディオストリームを受信できるAndroidアプリケーションを作成します。A2DPプロファイルを使用することを考えましたが、Androidはこの問題の解決策を探している人がたくさんいるように見えますが、通常のビットストリームを受信し、アプリケーションでデータをオーディオに変換するのはどうですか? RFCOMM(SPP Bluetoothプロファイル)を介したMp3データストリーム。AudioTrackを使用して再生します。
まず、RFCOMM経由でAndroid電話でビットストリームを受信するにはどうすればよいですか?また、PCMまたはMp3ストリームとしてRFCOMM経由でビットストリームを受信することは可能ですか?
第二に、PCMまたはMp3ストリームとしてRFCOMMを介してビットストリームを受信できない場合、受信したビットストリームをオーディオに変換するにはどうすればよいですか?
第三に、受信したデータを音声に変換し、音声を「リアルタイム」で同時に再生するにはどうすればよいですか? onDataReceivedを使用できますか?
明確にするために、私はA2DPプロファイルを使用することに興味がありません! RFCOMM(SPP Bluetoothプロファイル)を介してデータをストリーミングしたい。受信したデータストリームはPCMまたはMp3になります。私は自分のアプリを書くことを考えましたが、これを解決するアプリを知っている人がいたら、それについて聞いてうれしいです!私はAndroid 2.3 Gingerbreadを使用しています。
/ジョニー
No。Androidこれを処理するアプリケーションを記述しようとしています少なくともA2DP Sink
ロールを使用する場合は解決策ではありません。
あなたが言ったように、Androidは BlueZ
(BluetoothスタックAndroidはJelly Bean 4.1まで使用します)へのAPI呼び出しを実装していません。 A2DP sink
の機能に関しては、自分で実装する必要があります。
Bluetooth対応のAndroidデバイスは、デフォルトでA2DP source
デバイスとして自身をアドバタイズします。これを最初に変更する必要があるため、近くのデバイスがデバイスをシンクとして認識します。 、audio.confファイル(通常は/ etc/bluetooth /)Enable
キーが存在し、値Source
が付加されていることを確認しますこのキーには、次のようなものが表示されます。
Enable=Source
再起動すると、近くのデバイスがデバイスをA2DP sink
として認識するようになります。
A2DPソースデバイスが電話へのオーディオのストリーミングを開始するときに適切に対応するには、BlueZと対話する必要があります。
AndroidとBlueZはD-BUS
を介して互いに通信しています。実際、AndroidはDBUS_SYSTEMチャネルに接続し、イベント、ファイル記述子などのすべてのBlueZ広告をリッスンします...
ネイティブアプリケーションを使用してこのd-busチャネルに自分をバインドし、BlueZが投稿したさまざまなイベントにアクセスできたことを覚えています。これは、参照として使用できるBlueZ APIを使用して比較的簡単に実現できます here 。この方法を使用する場合、ネイティブアプリケーション(C/C++)をビルドし、プラットフォーム用にコンパイルする必要があります。 Android NDK
を使用してこれを実行できる必要があります。
D-BUS
を使用するのが難しいと思うなら、これを試すことができますJava私が見つけたライブラリはあなたのためにD-BUSへの通信を処理します: http:// jbluez.sourceforge.net/ 。使用したことはありませんが、私の意見では試してみる価値があります。
あなたが本当にしなければならないことは、A2DPソースデバイスがあなたの電話にペアリングされたとき、そして彼が音楽をストリーミングし始めるときを見つけることです。これらのイベントは、D-BUSを介して取得できます。誰かが音楽をストリーミングしようとしたら、BlueZにネイティブアプリケーションが音楽を処理することを伝える必要があります。これを行うために処理する必要のあるイベントのフローを説明する非常に優れたドキュメントがあります。このドキュメントはアクセス可能です here 。興味のある部分は7ページにあります。指定された例のシンクアプリケーションはPulseAudio
ですが、あなたのアプリケーションでもかまいません。
BlueZは、org.bluez.MediaTransport.Acquire
メソッドを呼び出すときにUNIXソケットを転送します。このソケットを読み取ると、リモートデバイスによって現在ストリーミングされているデータが得られます。しかし、BlueZスタックに取り組んでいる人から、このソケットで読み取られたデータはPCMの純粋なオーディオではなく、エンコードされたオーディオコンテンツであると言われたことを覚えています。通常、データはSBC
(Low Complexity Subband Coding)と呼ばれる形式でエンコードされます。
SBCのデコードはそれほど難しくありません。デコーダーを見つけることができます 右 。
最終的なステップは、PCMオーディオをスピーカーに転送することです。
動けなくなるのを防ぎ、アプリケーションをより簡単な方法でテストするために、Androidシステムで使用できるはずのd-bus
バイナリを使用できます。彼は/ system/bin。
上記のいずれかを実行する前に作成できるクイックテストは次のとおりです。
デバイスリストの取得:
dbus-send --system --dest = org.bluez --print-reply/org.bluez.Manager.GetProperties
これにより、アダプターの配列とそのパスが返されます。これらのパスを取得したら、アダプターとペアになっているすべてのbluetoothデバイスのリストを取得できます。
ペアリングされたデバイスを取得する:
dbus-send --system --print-reply --dest = org.bluez/org/bluez/{pid}/hci0 org.bluez.Adapter.GetProperties
これにより、Devices配列フィールドにペアリングされたデバイスのリストが表示されます。
Bluetoothアダプターとペアリングされたデバイスのリストを取得したら、AudioSourceインターフェイスに接続されているかどうかを確認できます。
AudioSourceインターフェースに接続されたデバイスを取得します:
dbus-send --system --print-reply --dest = org.bluez/org/bluez/{pid}/hci0/dev_XX_XX_XX_XX_XX_XX org.bluez.AudioSource.GetProperties org.bluez.Manager.GetProperties
お役に立てれば。
別の回避策は、HandsFreeProfileを使用することです。
androidでは、BluetoothHeadsetがそれに取り組んでいます。ステータスがBluetoothHeadset.STATE_AUDIO_CONNECTEDに変わるまで待ちます。
その後、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();
[無関係だが機能する]このハックは、WIFIホットスポット経由でmp3ストリーミングのみを提供します(AUX入力のみを持っている車で使用しています) ):
(なぜ "192.168.43.1"だけなのか?それは、Android Hotspotに接続されたデバイスのデフォルトゲートウェイだからです)
audio.confはAndroid 4.2.2?
Rfcommを介してpcmオーディオストリームを受信するには、説明されたヒントとしてコードフローを使用できます( Cでオーディオファイルを読み取り、Bluetoothで転送してAndroidオーディオトラック ) 、44100から22050に初期化するときに使用される変更頻度
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM);
注:このストリーミングにはまだノイズが含まれていますが、
「RFCOMM(SPP Bluetoothプロファイル)を介してPCMデータストリームを受信し、AudioTrackを使用して再生します。」
働くでしょう。