Core-Telecom

ספריית Core-Telecom מייעלת את תהליך השילוב של האפליקציה הקוראת עם פלטפורמת Android, על ידי מתן קבוצה חזקה ועקבית של ממשקי API.

אם אתם רוצים לבדוק הטמעות מעשיות, תוכלו למצוא אפליקציות לדוגמה ב-GitHub:

הגדרת Core-Telecom

מוסיפים את התלות ב-androidx.core:core-telecom לקובץ build.gradle של האפליקציה:

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

מגדירים את ההרשאה MANAGE_OWN_CALLS ב-AndroidManifest.xml:

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

רישום האפליקציה

כדי להתחיל להוסיף שיחות למערכת, צריך לרשום את אפליקציית השיחות ב-Android באמצעות CallsManager. במהלך הרישום, צריך לציין את היכולות של האפליקציה (לדוגמה, תמיכה באודיו ובווידאו):

val callsManager = CallsManager(context)

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

callsManager.registerAppWithTelecom(capabilities)

ניהול השיחות

שימוש בממשקי Core-Telecom API כדי ליצור ולנהל את מחזור החיים של שיחה.

יצירת שיחה

האובייקט CallAttributesCompat מגדיר את המאפיינים של קריאה ייחודית, שיכולה להיות בעלת המאפיינים הבאים:

  • displayName: שם מבצע הקריאה.
  • address: כתובת השיחה (לדוגמה, מספר טלפון, קישור לפגישה).
  • direction: נכנסות או יוצאות.
  • callType: אודיו או וידאו.
  • callCapabilities: תמיכה בהעברה ובהחזקה.

דוגמה ליצירת שיחה נכנסת:

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

הוספת שיחה

אפשר להשתמש ב-callsManager.addCall עם CallAttributesCompat ועם קריאות חזרה (callbacks) כדי להוסיף קריאה חדשה למערכת ולנהל עדכונים מרוחקים של ממשק. ה-callControlScope בתוך הבלוק addCall מאפשר לאפליקציה לשנות את מצב השיחה ולקבל עדכוני אודיו:

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

מענה לשיחה

מענה לשיחה נכנסת בתוך CallControlScope:

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

דחיית שיחה

דחיית שיחה באמצעות disconnect() עם DisconnectCause.REJECTED בתוך CallControlScope:

disconnect(DisconnectCause(DisconnectCause.REJECTED))

הפעלת שיחה יוצאת

מגדירים שיחה יוצאת כפעילה ברגע שהצד השני עונה:

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

העברת שיחה להמתנה

כדי להעביר שיחה למצב המתנה, מקישים על setInactive():

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

ניתוק שיחה

כדי לנתק שיחה באמצעות disconnect() עם DisconnectCause:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

ניהול נקודות קצה של אודיו בשיחות

מעקב אחרי נקודות קצה של אודיו וניהול שלהן באמצעות Flow של currentCallEndpoint,‏ availableEndpoints ו-isMuted ב-CallControlScope

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

משנים את התקן האודיו הפעיל באמצעות requestEndpointChange():

coroutineScope.launch {
     callControlScope.requestEndpointChange(callEndpoint)
}

תמיכה בחזית

הספרייה משתמשת ב-ConnectionService (Android 13 API ברמה 33 ומטה) או ב-foregroundtypes (Android 14 API ברמה 34 ואילך) לתמיכה בחזית.

כחלק מדרישות הפעילות בחזית, האפליקציה חייבת לפרסם התראה כדי שהמשתמשים ידעו שהיא פועלת בחזית.

כדי להבטיח שהאפליקציה תקבל עדיפות ביצוע בחזית, צריך ליצור התראה אחרי שמוסיפים את הקריאה לפלטפורמה. העדיפות בחזית תוסר כשהאפליקציה תסיים את השיחה או שההתראה לא תהיה תקפה יותר.

מידע נוסף על שירותים בחזית

תמיכה מרחוק ב-Surface

מכשירים מרוחקים (שעונים חכמים, אוזניות Bluetooth, Android Auto) יכולים לנהל שיחות בלי אינטראקציה ישירה עם הטלפון. האפליקציה צריכה להטמיע פונקציות callback מסוג lambda‏ (onAnswerCall, onSetCallDisconnected, onSetCallActive, onSetCallInactive) שסופקו ל-CallsManager.addCall כדי לטפל בפעולות שהמכשירים האלה יוזמנו.

כשמתרחשת פעולה מרחוק, הפונקציה Lambda המתאימה מופעלת.

השלמת ה-lambda בהצלחה מסמנת שהפקודה טופלה. אם אי אפשר לבצע את הפקודה, הפונקציה Lambda צריכה להוציא חריגה.

הטמעה נכונה מבטיחה שליטה חלקה בשיחות במכשירים שונים. כדאי לבדוק היטב עם משטחים שונים מרחוק.