Telecom

Library Jetpack Android Telecom yang baru memudahkan untuk memberi tahu platform apa yang status panggilan Anda. Anda dapat menemukan kode sumber dan aplikasi contoh di GitHub.

Dependensi dan izin

Pertama, buka file build.gradle modul aplikasi dan tambahkan dependensi untuk Modul androidx Telecom:

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

Dalam manifes aplikasi, deklarasikan bahwa aplikasi Anda menggunakan MANAGE_OWN_CALLS` izin akses:

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

Daftarkan aplikasi

Untuk memberi tahu Android tentang aplikasi, Anda harus mendaftarkannya dan kemampuannya. Informasi ini memberi tahu Android fitur apa yang didukung aplikasi Anda, seperti panggilan video, panggilan melakukan streaming, dan melakukan panggilan. Info ini penting agar Android dapat mengonfigurasi sendiri agar berfungsi dengan fitur aplikasi Anda.

 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)

Integrasi platform

Dua skenario panggilan yang paling umum untuk setiap aplikasi panggilan adalah maupun panggilan keluar. Untuk mencatat arah panggilan dengan benar dan memberi tahu pengguna dengan tepat melalui notifikasi, gunakan API di bawah ini.

Daftarkan panggilan

Contoh ini menunjukkan cara mendaftarkan panggilan masuk:

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)
}

Objek callAttributes dapat memiliki properti berikut:

  • displayName: Nama penelepon, rapat, atau sesi.
  • address: Alamat panggilan. Perhatikan bahwa ekstensi ini dapat diperluas ke rapat tautan.
  • direction: Arah panggilan, seperti masuk atau keluar.
  • callType: Informasi yang terkait dengan data yang dikirim, seperti video dan audio.
  • callCapabilities: Objek yang menentukan kemampuan panggilan.

Objek callCapabilities dapat memiliki properti berikut:

  • streaming: Menunjukkan apakah panggilan mendukung streaming audio ke audio lain Perangkat yang didukung Android.
  • transfer: Menunjukkan apakah panggilan dapat ditransfer.
  • hold: Menunjukkan apakah panggilan dapat ditahan.

Tambahkan panggilan

Metode addCall() akan menampilkan pengecualian jika perangkat tidak mendukung telekomunikasi, atau jika terjadi kesalahan saat menyiapkan panggilan.

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

Menjawab telepon

Setelah melakukan panggilan masuk, Anda harus menjawab atau menolak panggilan tersebut. Ini contoh menunjukkan cara menjawab panggilan:

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

    }

    is CallControlResult.Error -> {

    }
}

Jika panggilan lain sedang berlangsung, answer() akan kembali CallControlResult.Error, yang memberitahukan alasan panggilan tidak dapat dijawab. Di beberapa dalam hal ini, pengguna perlu menahan panggilan lain.

Menolak panggilan

Untuk menolak panggilan, putuskan panggilan dengan DisconnectCause.Rejected.

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

Panggilan keluar

Saat melakukan panggilan keluar, setelah pihak jarak jauh menjawab, Anda harus menyetel panggil ke active untuk membuat platform mengetahui bahwa panggilan sedang berlangsung:

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

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

Menahan panggilan

Jika aplikasi panggilan Anda mendukung fitur menahan panggilan, gunakan setInActive untuk memberi tahu platform saat panggilan Anda tidak aktif dan mikrofon serta kamera dapat digunakan oleh aplikasi lain:

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

    }

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

Putuskan koneksi

Untuk memutuskan panggilan, beri tahu stack Telecom untuk memutuskan sambungan dengan memberikan sebuah penyebab yang valid:

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

Audio rute

Selama panggilan, pengguna terkadang beralih antar-perangkat, seperti speaker, {i>earphone<i}, atau perangkat Bluetooth. Gunakan availableEndpoints dan currentCallEndpoint API untuk mendapatkan daftar semua perangkat yang tersedia untuk pengguna dan perangkat mana yang aktif.

Contoh ini menggabungkan kedua alur untuk membuat objek UI guna menampilkan kepada pengguna daftar perangkat dan perangkat yang aktif:

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

Untuk mengubah perangkat yang aktif, gunakan requestEndpointChange dengan CallEndpoint yang ingin Anda ubah.

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

Dukungan latar depan

Library Telecom dilengkapi dengan dukungan latar depan. Library ini menggunakan ConnectionService untuk perangkat yang menjalankan Android 13 dan yang lebih lama. Untuk Android 14 dan Untuk perangkat yang lebih tinggi, mikrofon dan kamera foregroundtypes mendukung layanan latar depan. Pelajari lebih lanjut layanan latar depan.

Sebagai bagian dari persyaratan latar depan, aplikasi harus memposting notifikasi bagi pengguna untuk mengetahui bahwa aplikasinya berjalan di latar depan.

Untuk memastikan aplikasi Anda mendapatkan prioritas eksekusi latar depan, buat setelah Anda mendaftarkan panggilan ke platform. Prioritas latar depan dihapus ketika aplikasi menghentikan panggilan atau notifikasi tidak lagi valid.

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

Tampilkan dukungan

Smartwatch memiliki aplikasi penerima endpoint generik. Aplikasi ini menyediakan pengguna dengan antarmuka dasar seperti menjawab, menolak, dan memutuskan panggilan telepon. Aplikasi mendukung tindakan ini dengan mengimplementasikan fungsi lambda yang memberi tahu platform bahwa Anda telah melakukan tindakan pada perangkat.

Waktu setiap fungsi lambda habis setelah 5 detik dengan transaksi yang gagal jika aplikasi tidak merespons.

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 = {}