Core-Telecom

Biblioteka Core-Telecom upraszcza proces integracji aplikacji wywołującej z platformą Android, zapewniając niezawodny i spójny zestaw interfejsów API.

Jeśli chcesz zapoznać się z praktycznymi implementacjami, znajdziesz przykładowe aplikacje na GitHub:

Konfigurowanie usługi Core-Telecom

Dodaj zależność androidx.core:core-telecom do pliku build.gradle aplikacji:

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

Deklaruj uprawnienie MANAGE_OWN_CALLS w pliku AndroidManifest.xml:

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

Rejestracja swojej aplikacji

Aby zacząć dodawać połączenia do systemu, zarejestruj aplikację do połączeń w Androidzie, używając CallsManager. Podczas rejestracji określ funkcje aplikacji (np. obsługę dźwięku lub wideo):

val callsManager = CallsManager(context)

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

callsManager.registerAppWithTelecom(capabilities)

Zarządzanie połączeniami

Używaj interfejsów Core-Telecom API do tworzenia i zarządzania cyklem życia połączeń.

Tworzenie połączenia

Obiekt CallAttributesCompat definiuje właściwości unikalnego połączenia, które może mieć te cechy:

  • displayName: nazwa dzwoniącego.
  • address: adres wywołania (np. numer telefonu, link do spotkania).
  • direction: przychodzące lub wychodzące.
  • callType: dźwięk lub obraz.
  • callCapabilities: obsługuje przenoszenie i blokowanie.

Oto przykład tworzenia połączenia przychodzącego:

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

Dodawanie połączenia

Użyj funkcji callsManager.addCall z użyciem funkcji CallAttributesCompat i wyzwań zwrotnych, aby dodać nowe wywołanie do systemu i zarządzać zdalnym aktualizowaniem powierzchni. W bloku addCall element callControlScope umożliwia aplikacji przejście do stanu połączenia i otrzymywanie aktualizacji dźwięku:

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

Odbieranie połączenia

Odbieranie połączenia przychodzącego w ciągu CallControlScope:

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

Odrzucanie połączenia

Odrzuć połączenie za pomocą aplikacji disconnect() w aplikacji DisconnectCause.REJECTED:CallControlScope

disconnect(DisconnectCause(DisconnectCause.REJECTED))

Aktywowanie połączenia wychodzącego

Aby uaktywnić połączenie wychodzące, gdy osoba po drugiej stronie odbierze:

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

Przełączanie połączenia w stan oczekiwania

Aby wstrzymać połączenie, naciśnij setInactive():

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

Rozłączanie połączenia

Rozłączanie połączenia za pomocą disconnect() z urządzeniem DisconnectCause:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

Zarządzanie punktami końcowymi dźwięku połączeń

Obserwowanie punktów końcowych dźwięku i zarządzanie nimi za pomocą currentCallEndpoint, availableEndpoints i isMuted Flow w CallControlScope

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

Zmień aktywne urządzenie audio za pomocą requestEndpointChange():

coroutineScope.launch {
     callControlScope.requestEndpointChange(callEndpoint)
}

Pomoc na pierwszym planie

Biblioteka używa ConnectionService (Android 13 API na poziomie 33 lub niższym) lub foregroundtypes (Android 14 API na poziomie 34 lub wyższym) do obsługi pierwszego planu.

Zgodnie z wymaganiami dotyczącymi działania na pierwszym planie aplikacja musi wyświetlać powiadomienie, aby użytkownicy wiedzieli, że działa ona na pierwszym planie.

Aby mieć pewność, że Twoja aplikacja będzie miała priorytet w wykonywaniu na pierwszym planie, utwórz powiadomienie po dodaniu wywołania na platformie. Priorytet na pierwszym planie jest usuwany, gdy aplikacja zakończy połączenie lub gdy powiadomienie nie jest już ważne.

Więcej informacji o usługach na pierwszym planie

Pomoc zdalna dla Surface

Urządzenia zdalne (smartwatche, słuchawki Bluetooth, Android Auto) mogą zarządzać połączeniami bez bezpośredniej interakcji z telefonem. Aplikacja musi implementować wywołania zwrotne lambda (onAnswerCall, onSetCallDisconnected, onSetCallActive, onSetCallInactive) udostępniane do usługi CallsManager.addCall w celu obsługi działań inicjowanych przez te urządzenia.

Gdy wystąpi działanie zdalne, zostanie wywołana odpowiednia funkcja lambda.

Pomyślne zakończenie lambda sygnalizuje, że polecenie zostało przetworzone. Jeśli polecenie nie może zostać wykonane, funkcja lambda powinna wyrzucić wyjątek.

Właściwe wdrożenie zapewnia płynne sterowanie rozmowami na różnych urządzeniach. Dokładnie przetestuj na różnych powierzchniach.