通信

新しい Android Telecom Jetpack ライブラリを使用すると、プラットフォームに 現在の状態を表します。ソースコードとサンプルアプリは次の場所にあります。 GitHub

依存関係と権限

まず、アプリ モジュールの build.gradle ファイルを開き、 androidx Telecom モジュール:

dependencies {
    implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}

アプリ マニフェストで、アプリが MANAGE_OWN_CALLS を使用することを宣言します。 権限:

<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />

アプリケーションを登録する

Android にアプリを認識させるには、アプリとその機能を登録する必要があります。 ビデオ通話、ビデオ通話など、アプリがサポートする機能を Android に伝えます 通話の保留などですこの情報は、Android が アプリの機能と連携させることができます。

 private val callsManager = CallsManager(context)

var capabilities: @CallsManager.Companion.Capability Int =
    CallsManager.CAPABILITY_BASELINE or
          CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING or
          CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING

callsManager.registerAppWithTelecom(capabilities)

プラットフォームの統合

通話アプリケーションで最も一般的な 2 つの通話シナリオは、 利用できます通話の方向を正しく登録し、 ユーザーに通知を適切に通知するには、以下の API を使用します。

通話を登録する

次の例は、着信を登録する方法を示しています。

companion object {
  const val APP_SCHEME = "MyCustomScheme"
  const val ALL_CALL_CAPABILITIES = (CallAttributes.SUPPORTS_SET_INACTIVE
    or CallAttributes.SUPPORTS_STREAM or CallAttributes.SUPPORTS_TRANSFER)

  const val INCOMING_NAME = "Luke"
  val INCOMING_URI: Uri = Uri.fromParts(APP_SCHEME, "", "")
  // Define all possible properties for CallAttributes
  val INCOMING_CALL_ATTRIBUTES =
    CallAttributes(
      INCOMING_NAME,
      INCOMING_URI,
      DIRECTION_INCOMING,
      CALL_TYPE_VIDEO_CALL,
      ALL_CALL_CAPABILITIES)
}

callAttributes オブジェクトには次のプロパティがあります。

  • displayName: 発信者、会議、セッションの名前。
  • address: 呼び出しのアドレス。なお、これは会議でも 表示されます。
  • direction: 通話の方向(「着信」や「発信」など)。
  • callType: 送信されるデータに関連する情報(動画など) 生成できます。
  • callCapabilities: 呼び出しの機能を指定するオブジェクト。

callCapabilities オブジェクトには次のプロパティがあります。

  • streaming: 通話が他への音声ストリーミングをサポートしているかどうかを示します。 Android デバイス。
  • transfer: 通話が転送可能かどうかを示します。
  • hold: 通話を保留にできるかどうかを表します。

通話を追加

デバイスがサポートしていない場合、addCall() メソッドは例外を返します。 または通話の設定時にエラーが発生した場合などです。

try {
    callsManager.addCall(
        INCOMING_CALL_ATTRIBUTES,
        onIsCallAnswered, // Watch needs to know if it can answer the call
        onIsCallDisconnected,
        onIsCallActive,
        onIsCallInactive
    ) {
        callControlScope = this
    }
}

着信に応答する

着信後に、電話に出るか拒否する必要があります。この 電話に出る方法を示します。

when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
    is CallControlResult.Success -> {

    }

    is CallControlResult.Error -> {

    }
}

別の呼び出しが進行中の場合は、answer() が戻ります。 CallControlResult.Error: 通話に応答できなかった理由を示します。イン この場合は、ユーザーは通話を保留にする必要があります。

通話を拒否する

通話を拒否するには、DisconnectCause.Rejected との通話を切断してください。

fun onRejectCall(){
    coroutineScope.launch {
        callControlScope?.let {
            it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
        }
    }
}

発信

発信を行う場合、リモート パーティが応答したら、 active を呼び出して、通話が進行中であることをプラットフォームに通知します。

when (setActive()) {
    is CallControlResult.Success -> {
        onIsCallActive()
    }

    is CallControlResult.Error -> {
        updateCurrentCall {
            copy(errorCode = result.errorCode)
        }
    }
}

通話を保留にする

通話アプリが通話の保留をサポートしている場合は、setInActive を使用して 通話がアクティブではなく、マイクとカメラが無料で 他のアプリで使用可能:

when (setInActive()) {
    is CallControlResult.Success -> {

    }

    is CallControlResult.Error -> {
        updateCurrentCall {
            copy(errorCode = result.errorCode)
        }
    }
}

接続を解除する

通話を切断するには、 正当な原因:

coroutineScope.launch {
    callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}

音声をルーティングする

通話中、ユーザーはスピーカー、 イヤホン、Bluetooth デバイスなどです。availableEndpoints と 利用可能なすべてのデバイスのリストを取得するための currentCallEndpoint API アクティブなデバイスを特定できます

この例では、両方のフローを組み合わせて、ユーザーに表示させる UI オブジェクトを作成します。 デバイスのリストとどのデバイスがアクティブか:

availableEndpoint = combine(callControlScope.availableEndpoints,
    callControlScope.currentCallEndpoint) {
    availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
    availableDevices.map {
        EndPointUI(
            isActive = activeDevice.endpointName == it.endpointName, it
        )
    }
}

アクティブなデバイスを変更するには、requestEndpointChange を 変更後の CallEndpoint

coroutineScope.launch {
     callControlScope?.requestEndpointChange(callEndpoint)
}

フォアグラウンド サポート

Telecom ライブラリはフォアグラウンド サポートを備えています。このライブラリで使用するもの ConnectionService: Android 13 以前を搭載したデバイスの場合。Android 14 以降の場合 高いレベルでは、フォアグラウンド タイプのマイクとカメラを使用して、 フォアグラウンド サービスをサポートします。詳しくは、フォアグラウンド サービスについての説明をご覧ください。

フォアグラウンド要件の一環として、アプリは通知を送信する必要があります。 アプリがフォアグラウンドで実行されていることをユーザーに知らせます。

アプリがフォアグラウンド実行を優先できるようにするには、 通知を受け取ることができます。フォアグラウンドの優先度 アプリは通話を終了するか、通知が不要になったときに削除されます。 有効です。

is TelecomCall.Registered -> {
    val notification = createNotification(call)
    notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}

サーフェス サポート

スマートウォッチには汎用のエンドポイント レシーバ アプリケーションがあります。このアプリケーションは、 応答、拒否、切断などの基本的なインターフェースを使用して、 できます。アプリケーションは、ラムダ関数を実装することでこれらのアクションをサポートします。 ユーザーがデバイス上でアクションを実行したことをプラットフォームに通知します。

トランザクションが失敗すると、各ラムダ関数は 5 秒後にタイムアウトし、トランザクションが失敗します。 応答がありません。

callsManager.addCall(
        attributes,
        onIsCallAnswered, // Watch/Auto need to know if they can answer the call
        onIsCallDisconnected,
        onIsCallActive,
        onIsCallInactive
    ) {
//Call Scope
}
/**
  *  Can the call be successfully answered??
  *  TIP: Check the connection/call state to see if you can answer a call
  *  Example you may need to wait for another call to hold.
  **/
val onIsCallAnswered: suspend(type: Int) -> Unit = {}

/**
  * Can the call perform a disconnect
  */
val onIsCallDisconnected: suspend (cause: DisconnectCause) -> Unit = {}

/**
  *  Check is see if you can make the call active.
  *  Other calls and state might stop us from activating the call
  */
val onIsCallActive: suspend () -> Unit = {
    updateCurrentCall {
    }
}

/**
  * Check to see if you can make the call inactivate
  */
val onIsCallInactive: suspend () -> Unit = {}