Core-Telecom
लाइब्रेरी, एपीआई का एक बेहतर और लगातार काम करने वाला सेट उपलब्ध कराकर, कॉल करने की सुविधा देने वाले ऐप्लिकेशन को Android प्लैटफ़ॉर्म के साथ इंटिग्रेट करने की प्रोसेस को आसान बनाती है
अगर आपको इसे लागू करने के बारे में जानना है, तो GitHub पर सैंपल ऐप्लिकेशन देखें:
- कम साइज़ वाला सैंपल ऐप्लिकेशन —
Core-Telecom
एपीआई के इस्तेमाल को दिखाने वाला छोटा उदाहरण. बुनियादी कॉन्सेप्ट को तुरंत समझने के लिए एकदम सही. - ज़्यादा सुविधाओं वाला सैंपल ऐप्लिकेशन (कोर-टेलीकॉम टीम ने डेवलप किया है) — यह ऐप्लिकेशन, टेलीकॉम की बेहतर सुविधाओं और सबसे सही तरीकों को दिखाता है. इंटिग्रेशन के जटिल मामलों को समझने के लिए, यह एक बेहतरीन संसाधन है.
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")
// 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
)
}
कॉल जोड़ना
सिस्टम में नया कॉल जोड़ने और रिमोट सरफ़ेस अपडेट मैनेज करने के लिए, CallAttributesCompat
और कॉलबैक के साथ callsManager.addCall
का इस्तेमाल करें. addCall
ब्लॉक में मौजूद callControlScope
, आपके ऐप्लिकेशन को कॉल की स्थिति में बदलाव करने और ऑडियो से जुड़े अपडेट पाने की अनुमति देता है:
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
का इस्तेमाल करके, ऑडियो एंडपॉइंट को मॉनिटर और मैनेज करना
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 एपीआई लेवल 33 और उससे पहले के वर्शन) या foregroundtypes (Android 14 एपीआई लेवल 34 और उसके बाद के वर्शन) का इस्तेमाल करती है.
फ़ोरग्राउंड की ज़रूरी शर्तों के तहत, ऐप्लिकेशन को सूचना पोस्ट करनी होगी, ताकि उपयोगकर्ताओं को पता चल सके कि ऐप्लिकेशन फ़ोरग्राउंड में चल रहा है.
यह पक्का करने के लिए कि आपके ऐप्लिकेशन को फ़ोरग्राउंड में चलाने की प्राथमिकता मिले, प्लैटफ़ॉर्म के साथ कॉल जोड़ने के बाद सूचना बनाएं. जब आपका ऐप्लिकेशन कॉल को खत्म करता है या आपकी सूचना अब मान्य नहीं रहती, तो फ़ोरग्राउंड में प्राथमिकता हटा दी जाती है.
फ़ोरग्राउंड सेवाओं के बारे में ज़्यादा जानें.
रिमोट Surface सहायता
स्मार्टवॉच, ब्लूटूथ हेडसेट, Android Auto जैसे रिमोट डिवाइसों से, फ़ोन के बिना कॉल मैनेज किया जा सकता है. आपके ऐप्लिकेशन को CallsManager.addCall
के लिए दिए गए कॉलबैक लैम्ब्डा (onAnswerCall
, onSetCallDisconnected
, onSetCallActive
,
onSetCallInactive
) लागू करने होंगे, ताकि इन डिवाइसों से शुरू की गई कार्रवाइयों को मैनेज किया जा सके.
जब कोई रिमोट ऐक्शन होता है, तो उससे जुड़ा लैम्ब्डा फ़ंक्शन चालू होता है.
निर्देश पूरा होने पर, lambda सिग्नल भेजता है. अगर कमांड को पूरा नहीं किया जा सकता, तो lambda को एक अपवाद फेंकना चाहिए.
सही तरीके से लागू करने पर, अलग-अलग डिवाइसों पर कॉल को आसानी से कंट्रोल किया जा सकता है. अलग-अलग रिमोट प्लैटफ़ॉर्म पर पूरी तरह से जांच करें.
कॉल एक्सटेंशन
यह लाइब्रेरी, कॉल की स्थिति और ऑडियो रूट को मैनेज करने के साथ-साथ, कॉल एक्सटेंशन की सुविधा भी देती है. ये सुविधाएं ज़रूरी नहीं हैं. आपका ऐप्लिकेशन, Android Auto जैसे रिमोट प्लैटफ़ॉर्म पर कॉल करने का बेहतर अनुभव देने के लिए, इन सुविधाओं को लागू कर सकता है. इन सुविधाओं में मीटिंग रूम, कॉल को म्यूट करने की सुविधा, और कॉल के लिए अन्य आइकॉन शामिल हैं. जब आपका ऐप्लिकेशन किसी एक्सटेंशन को लागू करता है, तो ऐप्लिकेशन से मिली जानकारी को उन सभी कनेक्ट किए गए डिवाइसों के साथ सिंक कर दिया जाएगा जो अपने यूज़र इंटरफ़ेस (यूआई) में इन एक्सटेंशन को दिखाने की सुविधा देते हैं. इसका मतलब है कि ये सुविधाएं, रिमोट डिवाइसों पर भी उपलब्ध होंगी, ताकि उपयोगकर्ता उनसे इंटरैक्ट कर सकें.
एक्सटेंशन के साथ कॉल बनाना
कॉल बनाते समय, CallManager#addCall
का इस्तेमाल करने के बजाय, CallManager#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, मोबाइल कॉल की ग्लोबल म्यूट स्थिति को मैनेज करने की जटिलता को मैनेज करता है. इससे, एक से ज़्यादा कॉल के दौरान, आउटगोइंग ऑडियो को साइलेंट करने की सुविधा में गड़बड़ी की संभावना कम हो जाती है. साथ ही, उपयोगकर्ता को "क्या आप बोल रहे हैं" जैसे काम की सुविधाएं भी मिलती हैं. ऐसा तब होता है, जब उपयोगकर्ता बोल रहा हो और उसे पता न हो कि कॉल साइलेंट है.
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)
}
}