Library Core-Telecom
menyederhanakan proses integrasi aplikasi panggilan
Anda dengan platform Android dengan menyediakan kumpulan API
yang andal dan konsisten
Jika ingin mempelajari implementasi praktis, Anda dapat menemukan aplikasi contoh di GitHub:
- Aplikasi Contoh Ringan — Contoh minimal
yang menunjukkan penggunaan
Core-Telecom
API. Ideal untuk memahami konsep dasar dengan cepat. - Aplikasi Contoh Komprehensif (Dibuat oleh Tim Core-Telecom) — Aplikasi yang lebih kaya fitur yang menampilkan praktik terbaik dan fungsi Telekomunikasi lanjutan. Ini adalah resource yang bagus untuk memahami skenario integrasi yang kompleks.
Menyiapkan Core-Telecom
Tambahkan dependensi androidx.core:core-telecom
ke file build.gradle
aplikasi Anda:
dependencies {
implementation ("androidx.core:core-telecom:1.0.0")
}
Deklarasikan izin MANAGE_OWN_CALLS
di AndroidManifest.xml
Anda:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Daftarkan aplikasi Anda
Daftarkan aplikasi panggilan Anda ke Android menggunakan CallsManager
untuk mulai menambahkan
panggilan ke sistem. Saat mendaftar, tentukan kemampuan aplikasi Anda (misalnya, dukungan audio, video):
val callsManager = CallsManager(context)
val capabilities: @CallsManager.Companion.Capability Int =
(CallsManager.CAPABILITY_BASELINE or
CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING)
callsManager.registerAppWithTelecom(capabilities)
Pengelolaan Panggilan Telepon
Gunakan Core-Telecom API untuk membuat dan mengelola siklus proses panggilan.
Membuat panggilan
Objek CallAttributesCompat
menentukan properti panggilan unik,
yang dapat memiliki karakteristik berikut:
displayName
: nama pemanggil.address
: Alamat panggilan (misalnya, nomor telepon, link rapat).direction
: Masuk atau keluar.callType
: Audio atau video.callCapabilities
: Mendukung transfer dan tahan.
Berikut adalah contoh cara membuat panggilan masuk:
fun createIncomingCallAttributes(
callerName: String,
callerNumber: String,
isVideoCall: Boolean): CallAttributesCompat {
val addressUri = Uri.parse("YourAppScheme:$callerNumber")
// Define capabilities supported by your call.
val callCapabilities = CallAttributesCompat.CallCapability(
supportsSetInactive = CallAttributesCompat.SUPPORTS_SET_INACTIVE // Call can be made inactive (implies hold)
)
return CallAttributesCompat(
displayName = callerName,
address = addressUri,
direction = CallAttributesCompat.DIRECTION_INCOMING,
callType = if (isVideoCall) CallAttributesCompat.CALL_TYPE_VIDEO_CALL else CallAttributesCompat.CALL_TYPE_AUDIO_CALL,
callCapabilitiesCompat = callCapabilities
)
}
Menambahkan panggilan
Gunakan callsManager.addCall
dengan CallAttributesCompat
dan callback untuk menambahkan
panggilan baru ke sistem dan mengelola update platform jarak jauh. callControlScope
dalam blok addCall
terutama memungkinkan aplikasi Anda melakukan transisi status
panggilan dan menerima update audio:
try {
callsManager.addCall(
INCOMING_CALL_ATTRIBUTES,
onAnswerCall, // Watch needs to know if it can answer the call.
onSetCallDisconnected,
onSetCallActive,
onSetCallInactive
) {
// The call was successfully added once this scope runs.
callControlScope = this
}
}
catch(addCallException: Exception){
// Handle the addCall failure.
}
Menjawab telepon
Menjawab panggilan masuk dalam CallControlScope
:
when (val result = answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
is CallControlResult.Success -> { /* Call answered */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Menolak panggilan
Tolak panggilan menggunakan disconnect()
dengan DisconnectCause.REJECTED
dalam
CallControlScope
:
disconnect(DisconnectCause(DisconnectCause.REJECTED))
Membuat panggilan keluar aktif
Tetapkan panggilan keluar ke aktif setelah pihak jarak jauh menjawab:
when (val result = setActive()) {
is CallControlResult.Success -> { /* Call active */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Menahan panggilan
Gunakan setInactive()
untuk menahan panggilan:
when (val result = setInactive()) {
is CallControlResult.Success -> { /* Call on hold */ }
is CallControlResult.Error -> { /* Handle error */ }
}
Memutuskan sambungan panggilan
Putuskan sambungan panggilan menggunakan disconnect()
dengan DisconnectCause
:
disconnect(DisconnectCause(DisconnectCause.LOCAL))
Mengelola endpoint audio panggilan
Mengamati dan mengelola endpoint audio menggunakan currentCallEndpoint
,
availableEndpoints
, dan isMuted
Flow
dalam CallControlScope
fun observeAudioStateChanges(callControlScope: CallControlScope) {
with(callControlScope) {
launch { currentCallEndpoint.collect { /* Update UI */ } }
launch { availableEndpoints.collect { /* Update UI */ } }
launch { isMuted.collect { /* Handle mute state */ } }
}
}
Ubah perangkat audio aktif menggunakan requestEndpointChange()
:
coroutineScope.launch {
callControlScope.requestEndpointChange(callEndpoint)
}
Dukungan latar depan
Library ini menggunakan ConnectionService
(Android 13 API level 33 dan yang lebih lama) atau
foregroundtypes (Android 14 API level 34 dan yang lebih tinggi) untuk dukungan
latar depan.
Sebagai bagian dari persyaratan latar depan, aplikasi harus memposting notifikasi agar pengguna mengetahui bahwa aplikasi sedang berjalan di latar depan.
Untuk memastikan aplikasi Anda mendapatkan prioritas eksekusi latar depan, buat notifikasi setelah Anda menambahkan panggilan dengan platform. Prioritas latar depan akan dihapus saat aplikasi Anda menghentikan panggilan atau notifikasi Anda tidak lagi valid.
Pelajari layanan latar depan lebih lanjut.
Dukungan Surface jarak jauh
Perangkat jarak jauh (smartwatch, headset Bluetooth, Android Auto) mampu
mengelola panggilan tanpa interaksi langsung dengan ponsel. Aplikasi Anda harus mengimplementasikan
lambda callback (onAnswerCall
, onSetCallDisconnected
, onSetCallActive
,
onSetCallInactive
) yang disediakan ke CallsManager.addCall
untuk menangani tindakan
yang dimulai oleh perangkat ini.
Saat tindakan jarak jauh terjadi, lambda yang sesuai akan dipanggil.
Penyelesaian sinyal lambda yang berhasil bahwa perintah telah diproses. Jika perintah tidak dapat dipatuhi, lambda akan menampilkan pengecualian.
Penerapan yang tepat memastikan kontrol panggilan yang lancar di berbagai perangkat. Uji secara menyeluruh dengan berbagai platform jarak jauh.
Ekstensi Panggilan
Selain mengelola status panggilan dan rute audio panggilan Anda, library juga mendukung ekstensi panggilan, yang merupakan fitur opsional yang dapat diterapkan aplikasi Anda untuk pengalaman panggilan yang lebih kaya di platform jarak jauh, seperti Android Auto. Fitur ini mencakup ruang rapat, bisukan panggilan, dan ikon panggilan tambahan. Saat aplikasi Anda menerapkan ekstensi, informasi yang disediakan aplikasi akan disinkronkan dengan semua perangkat terhubung yang juga mendukung tampilan ekstensi ini di UI-nya. Artinya, fitur ini juga akan tersedia di perangkat jarak jauh untuk berinteraksi dengan pengguna.
Membuat Panggilan dengan Ekstensi
Saat membuat panggilan, Anda dapat menggunakan CallManager#addCallWithExtensions, yang memberi
aplikasi akses ke cakupan lain yang disebut ExtensionInitializationScope
, bukan menggunakan CallManager#addCall
untuk membuat panggilan. Cakupan
ini memungkinkan aplikasi melakukan inisialisasi kumpulan ekstensi opsional yang
didukung. Selain itu, cakupan ini menyediakan metode tambahan, onCall
,
yang memberikan CallControlScope
kembali ke aplikasi setelah pertukaran kemampuan
ekstensi dan inisialisasi selesai.
scope.launch {
mCallsManager.addCallWithExtensions(
attributes,
onAnswer,
onDisconnect,
onSetActive,
onSetInactive
) {
// Initialize extension-specific code...
// After the call has been initialized, perform in-call actions
onCall {
// Example: process call state updates
callStateFlow.onEach { newState ->
// handle call state updates and notify telecom
}.launchIn(this)
// Use initialized extensions...
}
}
}
Mendukung Peserta Panggilan
Jika aplikasi Anda mendukung peserta panggilan untuk rapat atau panggilan grup, gunakan
addParticipantExtension
untuk mendeklarasikan dukungan untuk ekstensi ini dan
gunakan API terkait untuk memperbarui platform jarak jauh saat peserta berubah.
mCallsManager.addCallWithExtensions(...) {
// Initialize extensions...
// Notifies Jetpack that this app supports the participant
// extension and provides the initial participants state in the call.
val participantExtension = addParticipantExtension(
initialParticipants,
initialActiveParticipant
)
// After the call has been initialized, perform in-call control actions
onCall {
// other in-call control and extension actions...
// Example: update remote surfaces when the call participants change
participantsFlow.onEach { newParticipants ->
participantExtension.updateParticipants(newParticipants)
}.launchIn(this)
}
}
Selain memberi tahu platform jarak jauh tentang peserta yang ada dalam panggilan,
peserta aktif juga dapat diperbarui menggunakan
ParticipantExtension#updateActiveParticipant
.
Ada juga dukungan untuk tindakan opsional yang terkait dengan peserta panggilan.
Aplikasi dapat menggunakan ParticipantExtension#addRaiseHandSupport
untuk mendukung
konsep peserta yang mengangkat tangan dalam panggilan dan melihat peserta
lain yang juga mengangkat tangan.
mCallsManager.addCallWithExtensions(...) {
// Initialize extensions...
// Notifies Jetpack that this app supports the participant
// extension and provides the initial list of participants in the call.
val participantExtension = addParticipantExtension(initialParticipants)
// Notifies Jetpack that this app supports the notion of participants
// being able to raise and lower their hands.
val raiseHandState = participantExtension.addRaiseHandSupport(
initialRaisedHands
) { onHandRaisedStateChanged ->
// handle this user's raised hand state changed updates from
// remote surfaces.
}
// After the call has been initialized, perform in-call control actions
onCall {
// other in-call control and extension actions...
// Example: update remote surfaces when the call participants change
participantsFlow.onEach { newParticipants ->
participantExtension.updateParticipants(newParticipants)
}.launchIn(this)
// notify remote surfaces of which of the participants have their
// hands raised
raisedHandsFlow.onEach { newRaisedHands ->
raiseHandState.updateRaisedHands(newRaisedHands)
}.launchIn(this)
}
}
Mendukung Senyapkan Panggilan
Mode bisu panggilan memungkinkan pengguna meminta aplikasi untuk membisukan audio keluar panggilan tanpa membisukan mikrofon perangkat secara fisik. Fitur ini dikelola per panggilan, sehingga Jetpack menangani kompleksitas pengelolaan status bisukan global panggilan seluler yang sedang berlangsung saat panggilan VOIP aktif. Hal ini membuat pembisuan audio keluar tidak terlalu rentan terhadap error dalam skenario multi-panggilan sekaligus memungkinkan fitur bermanfaat seperti indikasi "apakah Anda berbicara" saat pengguna berbicara tanpa menyadari bahwa bisukan panggilan diaktifkan.
mCallsManager.addCallWithExtensions(...) {
// Initialize extensions...
// Add support for locally silencing the call's outgoing audio and
// register a handler for when the user changes the call silence state
// from a remote surface.
val callSilenceExtension = addLocalCallSilenceExtension(
initialCallSilenceState = false
) { newCallSilenceStateRequest ->
// handle the user's request to enable/disable call silence from
// a remote surface
}
// After the call has been initialized, perform in-call control actions
onCall {
// other in-call control and extension actions...
// When the call's call silence state changes, update remote
// surfaces of the new state.
callSilenceState.onEach { isSilenced ->
callSilenceExtension.updateIsLocallySilenced(isSilenced)
}.launchIn(this)
}
}
Ikon Panggilan Dukungan
Ikon panggilan memungkinkan aplikasi menentukan ikon kustom yang mewakili panggilan untuk ditampilkan di platform jarak jauh selama panggilan. Ikon ini juga dapat diperbarui selama siklus proses panggilan.
mCallsManager.addCallWithExtensions(...) {
// Initialize extensions...
// Add support for a custom call icon to be displayed during the
// lifetime of the call.
val callIconExtension = addCallIconExtension(
initialCallIconUri = initialUri
)
// After the call has been initialized, perform in-call control actions
onCall {
// other in-call control and extension actions...
// When the call's icon changes, update remote surfaces by providing
// the new URI.
callIconUri.onEach { newIconUri ->
callIconExtension.updateCallIconUri(newIconUri)
}.launchIn(this)
}
}