Core-Telecom

Core-Telecom लाइब्रेरी, आपके कॉलिंग ऐप्लिकेशन को Android प्लैटफ़ॉर्म के साथ इंटिग्रेट करने की प्रोसेस को आसान बनाती है. इसके लिए, यह एपीआई का मज़बूत और एक जैसा सेट उपलब्ध कराती है

अगर आपको इसे लागू करने के तरीके के बारे में जानना है, तो GitHub पर सैंपल ऐप्लिकेशन देखें:

Core-Telecom सेट अप करना

अपने ऐप्लिकेशन की build.gradle फ़ाइल में, androidx.core:core-telecom डिपेंडेंसी जोड़ें:

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

अपने AndroidManifest.xml में MANAGE_OWN_CALLS अनुमति का एलान करें:

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

अपना ऐप्लिकेशन रजिस्टर करना

सिस्टम में कॉल जोड़ने के लिए, CallsManager का इस्तेमाल करके अपने कॉलिंग ऐप्लिकेशन को Android के साथ रजिस्टर करें. रजिस्टर करते समय, अपने ऐप्लिकेशन की क्षमताओं के बारे में बताएं. जैसे, ऑडियो, वीडियो सपोर्ट:

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

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

कोई कॉल जोड़ें

सिस्टम में नया कॉल जोड़ने और रिमोट सर्फ़ेस अपडेट मैनेज करने के लिए, callsManager.addCall के साथ CallAttributesCompat और कॉलबैक का इस्तेमाल करें. 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 */ }
}

कॉल अस्वीकार करना

CallControlScope में DisconnectCause.REJECTED के साथ disconnect() का इस्तेमाल करके कॉल अस्वीकार करने के लिए:

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 */ }
}

कॉल डिसकनेक्ट करना

DisconnectCause की मदद से, disconnect() का इस्तेमाल करके कॉल डिसकनेक्ट करने के लिए:

disconnect(DisconnectCause(DisconnectCause.LOCAL))

कॉल के ऑडियो एंडपॉइंट मैनेज करना

CallControlScope में मौजूद currentCallEndpoint, availableEndpoints, और isMuted Flow का इस्तेमाल करके, ऑडियो एंडपॉइंट को मॉनिटर और मैनेज करें. Telecom का इस्तेमाल करते समय, ऑडियो रूट मैनेज करने के लिए AudioManager#setCommunicationDevice या AudioManager#startBluetoothSco एपीआई का इस्तेमाल न करें. ऐसा करने से, कॉल में ऑडियो से जुड़ी समस्याएं आएंगी.

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

फ़ोरग्राउंड सपोर्ट

यह लाइब्रेरी, Android 13 (एपीआई लेवल 33) और इसके बाद के वर्शन पर ConnectionService का इस्तेमाल करती है. वहीं, Android 14 (एपीआई लेवल 34) और इसके बाद के वर्शन पर, यह फ़ोरग्राउंड सेवा के टाइप का इस्तेमाल करती है. ऐसा फ़ोरग्राउंड सेवा के लिए किया जाता है.

जब आपका ऐप्लिकेशन बैकग्राउंड में हो, तब कॉल चालू रखने के लिए, CallsManager को फ़ोरग्राउंड Service (जैसे कि LifecycleService) में होस्ट करें. साथ ही, AndroidManifest.xml में phoneCall फ़ोरग्राउंड सेवा के टाइप की जानकारी दें:

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

फ़ोरग्राउंड सेवा से जुड़ी ज़रूरी शर्तों के तहत, आपके ऐप्लिकेशन को NotificationCompat.CallStyle सूचना पोस्ट करनी होगी, ताकि लोगों को पता चल सके कि फ़ोरग्राउंड में कॉल चालू है. यह पक्का करने के लिए कि आपके ऐप्लिकेशन को फ़ोरग्राउंड में चलने की प्राथमिकता मिले, अपनी सेवा को फ़ोरग्राउंड में प्रमोट करें. इसके लिए, प्लैटफ़ॉर्म पर कॉल जोड़ने के बाद, startForeground का इस्तेमाल एक बार करें:

startForeground(
    notificationId,
    notification,
    ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL
)

फ़ोरग्राउंड सेवाओं के बारे में ज़्यादा जानें.

Surface के लिए रिमोट सपोर्ट

रिमोट डिवाइस (स्मार्टवॉच, ब्लूटूथ हेडसेट, Android Auto) पर, फ़ोन से सीधे इंटरैक्ट किए बिना कॉल मैनेज की जा सकती है. आपके ऐप्लिकेशन को CallsManager.addCall को दिए गए कॉलबैक लैम्डा (onAnswerCall, onSetCallDisconnected, onSetCallActive, onSetCallInactive) लागू करने होंगे, ताकि इन डिवाइसों से शुरू की गई कार्रवाइयों को मैनेज किया जा सके.

रिमोट ऐक्शन होने पर, उससे जुड़ा लैंबडा फ़ंक्शन शुरू हो जाता है.

लैंबडा के सिग्नल से पता चलता है कि कमांड प्रोसेस हो गई है. अगर कमांड का पालन नहीं किया जा सकता, तो लैंबडा को एक अपवाद दिखाना चाहिए.

इसे सही तरीके से लागू करने पर, अलग-अलग डिवाइसों पर कॉल को आसानी से कंट्रोल किया जा सकता है. अलग-अलग रिमोट डिवाइसों पर अच्छी तरह से टेस्ट करें.

कॉल एक्सटेंशन

कॉल की स्थिति और ऑडियो रूट को मैनेज करने के साथ-साथ, यह लाइब्रेरी कॉल एक्सटेंशन को भी सपोर्ट करती है. ये ऐसी वैकल्पिक सुविधाएं हैं जिन्हें आपका ऐप्लिकेशन, रिमोट प्लैटफ़ॉर्म पर कॉल करने का बेहतर अनुभव देने के लिए लागू कर सकता है. जैसे, Android Auto. इन सुविधाओं में मीटिंग रूम, कॉल साइलेंस, और कॉल के अतिरिक्त आइकॉन शामिल हैं. जब आपका ऐप्लिकेशन कोई एक्सटेंशन लागू करता है, तो ऐप्लिकेशन से मिली जानकारी को उन सभी कनेक्ट किए गए डिवाइसों के साथ सिंक किया जाएगा जो अपने यूज़र इंटरफ़ेस (यूआई) में इन एक्सटेंशन को दिखाने की सुविधा देते हैं. इसका मतलब है कि ये सुविधाएं, रिमोट डिवाइसों पर भी उपलब्ध होंगी, ताकि उपयोगकर्ता उनसे इंटरैक्ट कर सकें.

एक्सटेंशन की मदद से कॉल करना

कॉल बनाने के लिए, CallsManager.addCall का इस्तेमाल करने के बजाय, CallsManager.addCallWithExtensions का इस्तेमाल किया जा सकता है. इससे ऐप्लिकेशन को ExtensionInitializationScope नाम के एक अलग स्कोप का ऐक्सेस मिलता है. इस स्कोप की मदद से, ऐप्लिकेशन उन वैकल्पिक एक्सटेंशन के सेट को शुरू कर सकता है जिनके साथ यह काम करता है. इसके अलावा, इस स्कोप में एक और तरीका, onCall, शामिल है. इससे एक्सटेंशन की सुविधा के लिए, डेटा के आदान-प्रदान और उसे शुरू करने की प्रोसेस पूरी होने के बाद, ऐप्लिकेशन को CallControlScope मिलता है.

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

कॉल में हिस्सा लेने वाले लोगों के लिए सहायता

अगर आपका ऐप्लिकेशन, मीटिंग या ग्रुप कॉल में शामिल होने वाले लोगों के लिए कॉल की सुविधा देता है, तो इस एक्सटेंशन के लिए सहायता देने का एलान करने के लिए addParticipantExtension का इस्तेमाल करें. साथ ही, जब कॉल में शामिल होने वाले लोग बदलें, तब रिमोट डिवाइसों को अपडेट करने के लिए, इससे जुड़े एपीआई का इस्तेमाल करें.

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

कॉल में हिस्सा लेने वाले लोगों के बारे में रिमोट प्लैटफ़ॉर्म को सूचना देने के साथ-साथ, ParticipantExtension#updateActiveParticipant का इस्तेमाल करके सक्रिय हिस्सा लेने वाले व्यक्ति की जानकारी भी अपडेट की जा सकती है.

इसके अलावा, कॉल में हिस्सा लेने वाले लोगों से जुड़ी वैकल्पिक कार्रवाइयों के लिए भी सहायता उपलब्ध है. ऐप्लिकेशन, ParticipantExtension#addRaiseHandSupport का इस्तेमाल करके कॉल में शामिल लोगों को हाथ ऊपर करने की सुविधा दे सकता है. साथ ही, यह भी देख सकता है कि कॉल में शामिल किन अन्य लोगों ने हाथ ऊपर किया है.

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

सहायता टीम से कॉल आने पर आवाज़ बंद करने की सुविधा

कॉल साइलेंस की सुविधा की मदद से, कोई व्यक्ति ऐप्लिकेशन से कॉल के आउटगोइंग ऑडियो को बंद करने का अनुरोध कर सकता है. इसके लिए, उसे डिवाइस के माइक्रोफ़ोन को बंद करने की ज़रूरत नहीं होती. इस सुविधा को हर कॉल के हिसाब से मैनेज किया जाता है. इसलिए, Jetpack यह तय करता है कि VOIP कॉल चालू होने पर, सेल्युलर कॉल को ग्लोबल लेवल पर म्यूट करने की स्थिति को कैसे मैनेज किया जाए. इससे एक साथ कई कॉल के दौरान, आउटगोइंग ऑडियो को म्यूट करने में कम गड़बड़ियां होती हैं. साथ ही, इससे "क्या आप बोल रहे हैं" जैसे मददगार सुझाव भी मिलते हैं. ये सुझाव तब मिलते हैं, जब उपयोगकर्ता बोल रहा होता है, लेकिन उसे यह पता नहीं होता कि कॉल म्यूट करने की सुविधा चालू है.

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

सहायता के लिए कॉल करने के आइकॉन

कॉल आइकॉन की मदद से, ऐप्लिकेशन कॉल के दौरान रिमोट डिवाइसों पर दिखने वाले कॉल के लिए, कस्टम आइकॉन तय कर सकता है. कॉल के दौरान भी इस आइकॉन को अपडेट किया जा सकता है.

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

सिस्टम कॉल लॉग में जोड़ें

अपने ऐप्लिकेशन के वीओआईपी कॉल को सिस्टम कॉल लॉग में जोड़ा जा सकता है, ताकि वे सिस्टम डायलर में दिखें. इससे उपयोगकर्ता, कॉल लॉग से वापस कॉल कर सकते हैं. ज़्यादा जानकारी के लिए, कॉल इतिहास को एक साथ देखने की सुविधा लेख पढ़ें.