# ハンズフリー

iOS と Android デバイスでのみ `IAudioOutputHelper` を利用することでハンズフリーができます。

ハンズフリーではヘッドセットの接続有無によって以下のように挙動が変わります。

- ヘッドセットが接続されていない場合は通話用スピーカーと通常のスピーカーが切り替わります
- ヘッドセットが接続されている場合は、ヘッドセットのスピーカーとマイクから端末の通常のスピーカーとマイクへ切り替わります
- マイクなしイヤホン接続時の動作は考慮されておらず、イヤホンによりマイクが利用できなくなることがあります

## ハンズフリーの挙動について

ハンズフリーの挙動は実行するプラットフォームによって以下のような違いがあります。

### Android の Bluetooth ヘッドセット接続時に音声通話スピーカーから音が出るケースがある

- Android は ハンズフリーの状態から Bluetooth ヘッドセットに切り替えを行う際に一度音声通話スピーカーから音が出たあとに Bluetooth ヘッドセットに切り替わります- Bluetooth ヘッドセット接続までにタイムラグがあるため、切り替わるまでの時間に音声通話スピーカーから音が出ます
- iOS では Bluetooth ヘッドセット接続時に音声通話スピーカーから音が出ることはありません

### ハンズフリー機能を有効にしてから切断し、再接続した場合の動作差異

- iOS ではハンズフリー機能を有効にしてから切断し、再接続した場合にはハンズフリー機能が有効の状態となります。
- Android ではハンズフリー機能を有効にしてから切断し、再接続した場合に、切断前の有効状態を維持せずにハンズフリーは無効の状態に戻ります- Android でハンズフリー機能有効の状態で開始した際に Android API が正常に動作せずハンズフリー無効の状態に切り替えられなくなる事象があったため、ハンズフリーは必ず無効の状態から開始する対応としましたAndroid でハンズフリーの設定を維持する場合はアプリ側で設定を保持し、再接続後に切断前の状態を再設定する必要があります

## 利用方法

ハンズフリーの利用方法は以下の通りです。

ここでは例として、UI ボタンのクリックイベントを利用してハンズフリーの ON/OFF を切り替えています。

```csharp
// IAudioOutputHelper のインスタンスを取得する
Sora.IAudioOutputHelper audioOutputHelper;

void Start()
{
    // アプリケーションの初期処理で AudioOutputHelper のインスタンスを作成する
    // 引数には Action を設定する。一例としてここではルート変更時にログ出力を行う
    audioOutputHelper = Sora.AudioOutputHelperFactory.Create(() => { Debug.Log("OnChangeRoute"); });
}

void OnApplicationQuit()
{
    DisposeSora();

    // audioOutputHelper のインスタンスが存在しない場合は処理を抜ける
    if (audioOutputHelper == null)
    {
        return;
    }

    // アプリケーション終了時に IAudioOutputHelper のインスタンスを破棄する
    audioOutputHelper.Dispose();
}

/*
ハンズフリーの ON/OFF を切り替える。
例として UI ボタンのクリックイベント用に OnClickSetHandsfree() を作成する。
*/
public void OnClickSetHandsfree()
{
    // Sora がいない場合は何もしない
    if (sora == null)
    {
        return;
    }

    // audioOutputHelper のインスタンスが存在しない場合は処理を抜ける
    if (audioOutputHelper == null)
    {
        return;
    }

    // 現在のハンズフリーの状態を取得する
    bool isHandsfree = audioOutputHelper.IsHandsfree();
    // ハンズフリーの状態を反転させる
    audioOutputHelper.SetHandsfree(!isHandsfree);
}
```

## ハンズフリー利用時の注意点

ハンズフリーは音声の送受信利用を前提としています。

そのため、Sendonly, Recvonly や NoAudioDevice といった設定ではハンズフリーは利用できません。

上記の補足として iOS の音声デバイスの仕様を以下に記載します。

Sora Unity SDK 内の iOS の実装では音声デバイスを利用しない場合、 AVAudioSession の カテゴリを PlayAndRecord にせず、デフォルトのまま利用します。

Sora Unity SDK のハンズフリーは Sora C++ SDK で実装されています。

その中で iOS のハンズフリー実装は `overrideOutputAudioPort(_:)` を使用して実現しており、このメソッドは PlayAndRecord 以外のカテゴリでは利用できません。

参考：[overrideOutputAudioPort(_:)](https://developer.apple.com/documentation/avfaudio/avaudiosession/1616443-overrideoutputaudioport)
