mucchinのAndroid戦記

Bluetoothヘッドセットとマイクを用いてのSIP通話方法

SIP通話を使うアプリを実装している方がどのくらいおられるかわかりませんが、今回はSIP通話とBluetoothの組み合わせについてです。
ちょっとマニアックなテーマかもしれませんが・・・。

インターネット上の多くの記事では、Bluetoothでの通話開始時は、AudioManager#startBluetoothSco()を実行し、終了時はAudioManager#stopBluetoothSco()を実行するようなやり方がほとんどです。

このやり方で実装すると、以下のような現象に悩まされました。
SIP通話終了後、キー効果音やメディアの音がBluetoothスピーカーからではなく、端末のスピーカーから鳴るようになってしまう。
しかも、これが発生する確率が100%というわけではなく、半々程度です。

通常、Android端末とBluetooth機器を接続すると、正常な場合は、端末の設定→Bluetoothのところで該当機器の状態を見てみると「接続中」となっているはずです。この状態だと、全ての音声はBluetoothのスピーカーから聞こえているはずです。

しかし、通話開始時にAudioManager#startBluetoothSco()を実行させた後、Bluetoothの状態を見てみると、「接続済み(メディアを除く)」となっていました。(これはもしかすると正常な動作なのかもしれません。)

となると、終了時にAudioManager#stopBluetoothSco()を実行すれば、「(メディアを除く)」が解除されるはず、、、と思うのですが、解除される場合とそうでない場合が混在しておりまして、それが原因でSIP通話終了後にメディア音が端末のスピーカーから鳴り出したり、そうでもなかったりとするようでした。
つまり、AudioManager#stopBluetoothSco()がどうも不安定な動作となっている、という推測が出来ます。

いくら処理順序を変更する等の悪あがきをしても全く解消されず諦めかけていましたが、使用するAPIを全く別の以下に変える事で、この現象が解決しました。
以下を利用します。
・通話開始時にはBluetoothHeadset#startVoiceRecognition()
・通話終了時にはBluetoothHeadset#stopVoiceRecognition()

メソッド名からすると、音声認識用の処理のような気がして違和感がありますが、これでBluetoothヘッドセットのマイクとスピーカーでの通話と、終話後のメディアの音声共に正常に動作するようになりました。
上記のBluetoothHeadsetインスタンスの取得方法は、先日書いた「アプリケーション起動時のBluetoothのHeadset接続状態の取得方法」という記事を参照してください。
ちなみに、これを利用する場合はAPIバージョンが11以上である必要があります。

最後に、なぜ上記のAPIを使おうと思ったかといいますと、「Using the Android RecognizerIntent with a bluetooth headset」のサンプルコードから、それらしき事が書いていたので試してみた次第です。
日本人のサイトやブログには、全くピンポイントの情報は皆無でした。

なお、BluetoothHeadset#startVoiceRecognition()を使って音声通話を開始した場合は、Bluetoothの状態は「接続中」のままとなっていました。
これがAudioManager#startBluetoothSco()との違いですが、となると、AudioManager#stopBluetoothSco()ではなく、もしかするとAudioManager#startBluetoothSco()の方がバグっているのかもしれないですね。真相はわかりません。

今回は以上です。