Core-Telecom

Core-Telecom kitaplığı, sağlam ve tutarlı bir API grubu sağlayarak arama uygulamanızı Android platformuyla entegre etme sürecini kolaylaştırır.

Pratik uygulamaları incelemek isterseniz GitHub'da örnek uygulamalar bulabilirsiniz:

Core-Telecom'u ayarlama

Uygulamanızın build.gradle dosyasına androidx.core:core-telecom bağımlılığını ekleyin:

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

MANAGE_OWN_CALLS iznini AndroidManifest.xml dosyanızda tanımlayın:

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

Uygulamanızı kaydettirme

Sisteme görüşme eklemeye başlamak için CallsManager kullanarak görüşme uygulamanızı Android'e kaydedin. Kaydolurken uygulamanızın özelliklerini (ör. ses, video desteği) belirtin:

val callsManager = CallsManager(context)

val capabilities: @CallsManager.Companion.Capability Int =
    (CallsManager.CAPABILITY_BASELINE or
          CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING)

callsManager.registerAppWithTelecom(capabilities)

Çağrı Yönetimi

Arama yaşam döngüsü oluşturmak ve yönetmek için Core-Telecom API'lerini kullanın.

Arama oluşturma

CallAttributesCompat nesnesi, benzersiz bir görüşmenin özelliklerini tanımlar. Bu özellikler şunlar olabilir:

  • displayName: arayanın adı.
  • address: Arama adresi (örneğin, telefon numarası, toplantı bağlantısı).
  • direction: Gelen veya giden.
  • callType: Ses veya video.
  • callCapabilities: Aktarma ve bekletme özelliklerini destekler.

Aşağıda, gelen arama oluşturma örneği verilmiştir:

fun createIncomingCallAttributes(
    callerName: String,
    callerNumber: String,
    isVideoCall: Boolean): CallAttributesCompat {
    val addressUri = Uri.parse("YourAppScheme:$callerNumber")

    return CallAttributesCompat(
        displayName = callerName,
        address = addressUri,
        direction = CallAttributesCompat.DIRECTION_INCOMING,
        callType = if (isVideoCall) {
            CallAttributesCompat.CALL_TYPE_VIDEO_CALL
        } else {
            CallAttributesCompat.CALL_TYPE_AUDIO_CALL
        },
        callCapabilities = CallAttributesCompat.SUPPORTS_SET_INACTIVE
    )
}

Görüşme ekleme

Sisteme yeni bir görüşme eklemek ve uzaktan yüzey güncellemelerini yönetmek için callsManager.addCall ile CallAttributesCompat ve geri aramaları kullanın. callControlScope içindeki addCall bloğu, öncelikle uygulamanızın arama durumunu geçiş yapmasına ve ses güncellemelerini almasına olanak tanır:

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

Çağrı yanıtlama

Gelen aramayı CallControlScope içinde yanıtlama:

when (val result = answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
    is CallControlResult.Success -> { /* Call answered */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

Aramayı reddetme

CallControlScope içinde disconnect() ile DisconnectCause.REJECTED kullanarak aramayı reddetme:

disconnect(DisconnectCause(DisconnectCause.REJECTED))

Giden aramayı etkinleştirme

Karşı taraf yanıtladığında giden aramayı etkin olarak ayarlama:

when (val result = setActive()) {
    is CallControlResult.Success -> { /* Call active */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

Çağrıyı beklemeye alma

Aramayı bekletmek için setInactive() telefon numarasını kullanın:

when (val result = setInactive()) {
    is CallControlResult.Success -> { /* Call on hold */ }
    is CallControlResult.Error -> { /* Handle error */ }
}

Aramayı sonlandırma

disconnect() ile DisconnectCause kullanarak bir görüşmenin bağlantısını kesme:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

Arama ses uç noktalarını yönetme

currentCallEndpoint, availableEndpoints ve isMuted Flow'lerini kullanarak CallControlScope içindeki ses uç noktalarını gözlemleyin ve yönetin. Telecom'u kullanırken ses rotalarını yönetmek için AudioManager#setCommunicationDevice veya AudioManager#startBluetoothSco API'lerini kullanmayın. Aksi takdirde, görüşmenizde ses sorunları yaşanır.

fun observeAudioStateChanges(callControlScope: CallControlScope) {
    with(callControlScope) {
        launch { currentCallEndpoint.collect { /* Update UI */ } }
        launch { availableEndpoints.collect { /* Update UI */ } }
        launch { isMuted.collect { /* Handle mute state */ } }
    }
}

requestEndpointChange() kullanarak etkin ses sistemini değiştirin:

coroutineScope.launch {
     callControlScope.requestEndpointChange(callEndpoint)
}

Ön plan desteği

Kitaplık, Android 13 (API düzeyi 33) ve önceki sürümlerde ConnectionService, Android 14 (API düzeyi 34) ve sonraki sürümlerde ise ön plan hizmeti türlerini kullanarak ön plan desteği sağlar.

Uygulamanız arka plandayken aramaların etkin kalması için CallsManager öğesini bir ön plan hizmeti Service (ör. LifecycleService) içinde barındırın ve phoneCall ön plan hizmeti türünü AndroidManifest.xml dosyanızda bildirin:

<service
    android:name=".TelecomVoipService"
    android:foregroundServiceType="phoneCall" />

Ön plan şartları kapsamında, uygulamanızın NotificationCompat.CallStyle bildirimi yayınlaması gerekir. Böylece kullanıcılar, ön planda etkin bir görüşme olduğunu bilir. Uygulamanızın ön planda yürütme önceliği almasını sağlamak için platformla görüşmeyi ekledikten sonra startForeground kullanarak hizmetinizi ön plana çıkarın:

startForeground(
    notificationId,
    notification,
    ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL
)

Ön plan hizmetleri hakkında daha fazla bilgi edinin.

Uzaktan Surface desteği

Uzak cihazlar (akıllı saatler, Bluetooth kulaklıklar, Android Auto), doğrudan telefon etkileşimi olmadan arama yönetimi yapabilir. Uygulamanız, bu cihazlar tarafından başlatılan işlemleri yönetmek için CallsManager.addCall'e sağlanan geri çağırma lambda'larını (onAnswerCall, onSetCallDisconnected, onSetCallActive, onSetCallInactive) uygulamalıdır.

Uzaktan işlem gerçekleştiğinde ilgili lambda çağrılır.

Lambda'nın başarıyla tamamlanması, komutun işlendiğini gösterir. Komuta uyulamazsa lambda bir istisna oluşturmalıdır.

Doğru uygulama, farklı cihazlarda sorunsuz görüşme kontrolü sağlar. Çeşitli uzak yüzeylerle kapsamlı bir şekilde test edin.

Telefon uzantıları

Kitaplık, aramalarınızın arama durumunu ve ses rotasını yönetmenin yanı sıra, uygulamanızın Android Auto gibi uzak yüzeylerde daha zengin bir arama deneyimi için uygulayabileceği isteğe bağlı özellikler olan arama uzantılarını da destekler. Bu özellikler arasında toplantı odaları, görüşme sırasında sesi kapatma ve ek görüşme simgeleri yer alır. Uygulamanız bir uzantı uyguladığında, uygulamanın sağladığı bilgiler, bu uzantıların kullanıcı arayüzünde gösterilmesini destekleyen tüm bağlı cihazlarla senkronize edilir. Bu özellikler, kullanıcıların etkileşimde bulunabilmesi için uzak cihazlarda da kullanılabilir.

Uzantılarla görüşme oluşturma

Arama oluştururken aramayı oluşturmak için CallsManager.addCall yerine CallsManager.addCallWithExtensions kullanabilirsiniz. Bu, uygulamaya ExtensionInitializationScope adlı farklı bir kapsamda erişim izni verir. Bu kapsam, uygulamanın desteklediği isteğe bağlı uzantıların kümesini başlatmasına olanak tanır. Ayrıca bu kapsam, uzantı özelliği değişimi ve başlatma tamamlandıktan sonra uygulamaya CallControlScope sağlayan ek bir yöntem (onCall) sunar.

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

Destek ekibini arayan katılımcılar

Uygulamanız toplantılar veya grup görüşmeleri için görüşme katılımcılarını destekliyorsa bu uzantı için desteği bildirmek üzere addParticipantExtension öğesini kullanın ve katılımcılar değiştiğinde uzak yüzeyleri güncellemek için ilgili API'leri kullanın.

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

Aramadaki katılımcılarla ilgili olarak uzak yüzeyleri bilgilendirmenin yanı sıra, etkin katılımcı ParticipantExtension#updateActiveParticipant kullanılarak da güncellenebilir.

Aramaya katılanlarla ilgili isteğe bağlı işlemler de desteklenir. Uygulama, katılımcıların görüşmede söz isteme fikrini desteklemek ve söz isteyen diğer katılımcıları görmek için ParticipantExtension#addRaiseHandSupport kullanabilir.

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

Destek çağrısı sessize alma

Aramayı sessize alma özelliği, kullanıcının cihazın mikrofonunu fiziksel olarak kapatmadan uygulamanın aramanın giden sesini sessize almasını istemesine olanak tanır. Bu özellik, arama bazında yönetilir. Bu nedenle, Jetpack, VOIP araması etkin durumdayken devam eden hücresel aramaların genel sessize alma durumunu yönetme karmaşıklığını ele alır. Bu sayede, çoklu görüşme senaryolarında giden sesin kapatılması daha az hataya neden olur. Ayrıca, kullanıcının görüşme sessizliğini etkinleştirdiğini fark etmeden konuşması durumunda "Konuşuyor musunuz?" gibi faydalı özellikler de kullanılabilir.

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

Destek Çağrısı Simgeleri

Arama simgesi, uygulamanın, arama sırasında uzak yüzeylerde gösterilecek aramayı temsil eden özel bir simge belirtmesine olanak tanır. Bu simge, görüşme süresince de güncellenebilir.

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

Sistem arama kaydına ekleme

Uygulamanızın VoIP aramalarını sistem arama kaydına ekleyerek sistem çeviricisinde görünmelerini sağlayabilir ve kullanıcıların buradan geri aramasına olanak tanıyabilirsiniz. Ayrıntılar için Birleştirilmiş arama geçmişi başlıklı makaleyi inceleyin.