يسمح تطبيق الهاتف التلقائي لإطار عمل Android Telecom بإعلام تطبيقك بحالة الاتصال من خلال استخدام مدير الدور والخدمة أثناء الاتصال لإنشاء بديل لتطبيق الهاتف التلقائي على جهاز Android، وتنفيذ واجهة برمجة تطبيقات InCallService. يجب أن تستوفي عملية التنفيذ المتطلبات التالية:
ويجب ألا تتضمّن أي إمكانية للاتصال، ويجب أن تتكون فقط من واجهة مستخدم للاتصال. ويجب أن يتعامل مع جميع المكالمات التي يُدرك إطار عمل الاتصالات بها، ولا يضع افتراضات حول طبيعة المكالمات. على سبيل المثال، يجب ألّا يتم افتراض أنّ المكالمات الهاتفية هي مكالمات هاتفية مستنِدة إلى شريحة SIM، كما يجب عدم تطبيق قيود على المكالمات تستند إلى أيٍ من ConnectionService، مثل فرض قيود الاتصال الهاتفي لمكالمات الفيديو.
يسمح تطبيق الاتصال للمستخدمين بتلقّي المكالمات الصوتية أو مكالمات الفيديو أو إجراؤها على الخاص بك. تستخدم تطبيقات الاتصال واجهة المستخدم الخاصة بها لإجراء المكالمات بدلاً من استخدامها واجهة تطبيق الهاتف التلقائية، كما هو موضح في لقطة الشاشة التالية.
يتضمّن إطار عمل Android حزمة android.telecom
التي تتيح
يحتوي على فئات تساعدك في إنشاء تطبيق للاتصالات وفقًا للاتصالات
إطار العمل. يوفّر إنشاء تطبيقك وفقًا لإطار عمل الاتصالات
الفوائد التالية:
- يتوافق تطبيقك بشكل صحيح مع النظام الفرعي للاتصالات في نظام التشغيل الخاص بك.
- يتوافق تطبيقك بشكل صحيح مع تطبيقات الاتصال الأخرى التي تلتزم أيضًا بما يلي: إطار العمل.
- يساعد إطار العمل تطبيقك في إدارة توجيه الصوت والفيديو.
- يساعد إطار العمل تطبيقك في تحديد ما إذا كانت مكالماته موضع تركيز أم لا.
بيانات البيان والأذونات
في بيان التطبيق، يجب التصريح بأنّ تطبيقك يستخدم
MANAGE_OWN_CALLS
إذن، كما هو موضَّح في المثال التالي:
<manifest … >
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
</manifest>
لمزيد من المعلومات حول الإعلان عن أذونات التطبيق، يُرجى الاطّلاع على الأذونات:
يجب الإفصاح عن خدمة تحدّد الفئة التي تنفِّذ
صف واحد (ConnectionService
) في تطبيقك. الاتصالات
أن تقدّم الخدمة بيانًا عن إذن BIND_TELECOM_CONNECTION_SERVICE
قادرًا على الالتزام بها. يوضّح المثال التالي كيفية الإعلان عن الخدمة في
بيان التطبيق:
<service android:name="com.example.MyConnectionService"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
<intent-filter>
<action android:name="android.telecom.ConnectionService" />
</intent-filter>
</service>
لمزيد من المعلومات حول الإفصاح عن مكوّنات التطبيق، بما في ذلك الخدمات، يُرجى الاطّلاع على مكوّنات التطبيق:
تنفيذ خدمة الاتصال
يجب أن يوفّر تطبيق الاتصال فئة ConnectionService
التي يمكن أن يرتبط بها النظام الفرعي للاتصالات.
يجب أن يتم إلغاء تنفيذ ConnectionService
الطرق التالية:
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
يستدعي النظام الفرعي للاتصالات هذه الطريقة استجابةً تطبيقك يتصل بخدمة
placeCall(Uri, Bundle)
لإنشاء مكالمة صادرة جديدة يعرض تطبيقك مثالاً جديدًا لتنفيذ فئةConnection
(لمزيد من المعلومات، يُرجى الاطّلاع على تنفيذ الربط) لتمثيل التجربة الجديدة مكالمة صادرة. يمكنك زيادة تخصيص الاتصال الصادر من خلال تنفيذ الإجراءات التالية:- يجب أن يستدعي تطبيقك الطريقة
setConnectionProperties(int)
مع استخدام ثابتPROPERTY_SELF_MANAGED
كوسيطة. للإشارة إلى أن الاتصال قد نشأ من تطبيق اتصال. - إذا كان تطبيقك يتيح تعليق المكالمات، يمكنك الاتصال بطريقة
setConnectionCapabilities(int)
وضبط وسيطة إلى قيمة قناع البت للثوابتCAPABILITY_HOLD
وCAPABILITY_SUPPORT_HOLD
. - لتحديد اسم المتصل، استخدِم الطريقة
setCallerDisplayName(String, int)
. اجتيازPRESENTATION_ALLOWED
ثابتًا مثل المعلمةint
للإشارة إلى أنه ينبغي أن يكون اسم المتصل عرضها. - للتأكّد من أنّ المكالمة الصادرة في حالة الفيديو المناسبة، اتصل
setVideoState(int)
للكائنConnection
وإرسال القيمة التي تعرضها الطريقةgetVideoState()
من الكائنConnectionRequest
.
- يجب أن يستدعي تطبيقك الطريقة
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
يطلب النظام الفرعي للاتصالات هذه الطريقة عندما يستدعي تطبيقك طريقة
placeCall(Uri, Bundle)
ولا يمكن لهذه المكالمة الصادرة. النهج التحليلي. واستجابةً لهذا الموقف، يجب أن يخبر التطبيق المستخدم (بخصوص مثلًا، استخدام مربع تنبيه أو إشعار منبثق) بأنه يتعذر إرسال المكالمة الصادرة . قد لا يتمكّن تطبيقك من إجراء مكالمة إذا كانت هناك مشكلة جارية. أو إذا كانت هناك مكالمة جارية في تطبيق آخر لا يمكن الانتظار قبل إجراء مكالمتك.onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
يطلب النظام الفرعي للاتصالات هذه الطريقة عندما يستدعي تطبيقك طريقة
addNewIncomingCall(PhoneAccountHandle, Bundle)
. لإبلاغ النظام بمكالمة واردة جديدة في التطبيق. يعرض تطبيقك مثال جديد لعملية تنفيذConnection
(على سبيل المثال للحصول على مزيد من المعلومات، يمكنك الاطّلاع على مقالة تنفيذ الربط) لتمثيل المكالمة الواردة الجديدة. يمكنك زيادة تخصيص الإشعارات الواردة الاتصال عن طريق تنفيذ الإجراءات التالية:- يجب أن يستدعي تطبيقك الطريقة
setConnectionProperties(int)
مع استخدام ثابتPROPERTY_SELF_MANAGED
كوسيطة. للإشارة إلى أن الاتصال قد نشأ من تطبيق اتصال. - إذا كان تطبيقك يتيح تعليق المكالمات، يمكنك الاتصال بطريقة
setConnectionCapabilities(int)
وضبط وسيطة إلى قيمة قناع البت للثوابتCAPABILITY_HOLD
وCAPABILITY_SUPPORT_HOLD
. - لتحديد اسم المتصل، استخدِم الطريقة
setCallerDisplayName(String, int)
. اجتيازPRESENTATION_ALLOWED
ثابتًا مثل المعلمةint
للإشارة إلى أنه ينبغي أن يكون اسم المتصل عرضها. - لتحديد رقم الهاتف أو عنوان المكالمة الواردة، يمكنك استخدام
الطريقة
setAddress(Uri, int)
للكائنConnection
. - للتأكّد من أنّ المكالمة الصادرة في حالة الفيديو المناسبة، اتصل
setVideoState(int)
للكائنConnection
وإرسال القيمة التي تعرضها الطريقةgetVideoState()
من الكائنConnectionRequest
.
- يجب أن يستدعي تطبيقك الطريقة
onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
يطلب النظام الفرعي للاتصالات هذه الطريقة عندما يطلب تطبيقك طريقة
addNewIncomingCall(PhoneAccountHandle, Bundle)
لإعلام شركة الاتصالات مكالمة واردة جديدة، ولكن لا يُسمح بالمكالمة الواردة (للمزيد من المعلومات، راجع قيود الاتصال). يجب أن رفض المكالمة الواردة تلقائيًا، ويمكنك نشر إشعار اختياريًا مستخدم المكالمة الفائتة.
تنفيذ عملية الربط
يجب أن ينشئ تطبيقك فئة فرعية من Connection
من أجل
لتمثيل المكالمات في تطبيقك. يجب عليك إلغاء الطرق التالية في
عملية التنفيذ:
onShowIncomingCallUi()
يستدعي النظام الفرعي للاتصالات هذه الطريقة عند إضافة مكالمة واردة جديدة يجب أن يعرض التطبيق واجهة المستخدم للمكالمات الواردة
onCallAudioStateChanged(CallAudioState)
يستدعي النظام الفرعي للاتصالات هذه الطريقة لإعلام التطبيق بأنّ الصوت الحالي تغيير المسار أو الوضع. ويتم استدعاء ذلك استجابةً لتغيير تطبيقك وضع الصوت باستخدام
setAudioRoute(int)
. يمكن أيضًا استخدام هذه الطريقة في حال غيّر النظام مسار الصوت. (على سبيل المثال، عند فصل سماعة رأس بلوتوث).onHold()
يستدعي النظام الفرعي للاتصالات هذه الطريقة عندما يريد تعليق المكالمة. استجابةً لهذا الطلب، يجب أن يعلّق تطبيقك المكالمة ثم يستدعي طريقة واحدة (
setOnHold()
) لإبلاغ النظام إجراء المكالمة. وقد يستدعي النظام الفرعي للاتصالات هذه الطريقة في حال خدمة أثناء المكالمة، مثل Android Auto، والتي تعرض مكالمتك تريد ترحيل طلب مستخدم لتعليق المكالمة. كما يستدعي النظام الفرعي للاتصالات هذه الطريقة إذا أجرى المستخدم مكالمة نشطة في تطبيق آخر. لمزيد من المعلومات، معلومات عن الخدمات الواردة أثناء الاتصال، يُرجى الاطّلاع علىInCallService
.onUnhold()
ويستدعي النظام الفرعي للاتصالات هذه الطريقة عندما يريد استئناف مكالمة معلّقة. بعد استئناف تطبيقك المكالمة، من المفترض أن يستدعي
setActive()
لإبلاغ النظام بأن المكالمة لم تعد معلَّقة. الاتصالات هذه الطريقة عند طلب خدمة أثناء الاتصال، مثل Android Auto، الذي يشير إلى مكالمتك تريد إرسال طلب لاستئناف المكالمة. بالنسبة مزيد من المعلومات عن الخدمات الواردة في المكالمة، يُرجى الاطّلاع علىInCallService
.onAnswer()
يستدعي النظام الفرعي للاتصالات هذه الطريقة لإبلاغ لتطبيقك بأن يتم الرد على أي مكالمة واردة. بعد ردّ التطبيق المكالمة، من المفترض أن يستدعي
setActive()
لإبلاغ النظام بأنه تم الرد على المكالمة. الاتصالات هذه الطريقة عندما يضيف تطبيقك مكالمة واردة جديدة هناك مكالمة جارية حاليًا في تطبيق آخر لا يمكن تعليقها. يعرض النظام الفرعي للاتصالات واجهة مستخدم المكالمات الواردة نيابةً عن تطبيقك في هذه الحالات. يوفر إطار العمل طريقة مع تحميل زائد توفر لتحديد حالة الفيديو التي يتم الرد بها على المكالمة. لمزيد من المعلومات، المعلومات، يمكنك الاطّلاع علىonAnswer(int)
.onReject()
يطلب النظام الفرعي للاتصالات هذه الطريقة عندما يريد رفض رسالة الاتصال. بعد رفض تطبيقك للمكالمة، من المفترض أن يطلب
setDisconnected(DisconnectCause)
مع تحديدREJECTED
كمعلَمة. يجب أن ثم استدعاء طريقةdestroy()
لإعلام النظام الذي عالج فيه التطبيق المكالمة. اتصالات النظام الفرعي للاتصالات لهذه الطريقة عندما يرفض المستخدم مكالمة واردة من تطبيقك.onDisconnect()
يطلب النظام الفرعي للاتصالات هذه الطريقة عندما يريد قطع مكالمة. بعد انتهاء المكالمة، من المفترض أن يستدعي تطبيقك طريقة
setDisconnected(DisconnectCause)
ويحدّدLOCAL
كمَعلمة للإشارة إلى أنّ تسبّب طلب المستخدم في قطع الاتصال. من المفترض أن يستدعي التطبيق بعد ذلك طريقةdestroy()
لإعلام شركة الاتصالات النظام الفرعي الذي عالج فيه التطبيق المكالمة. قد يستدعي النظام هذه الطريقة عندما يقطع المستخدم مكالمة من خلال خدمة أخرى أثناء الاتصال، مثل Android Auto: يستدعي النظام أيضًا هذه الطريقة عندما يجب أن يكون اتصالك غير متصل للسماح بإجراء مكالمة أخرى، على سبيل المثال، إذا أراد المستخدم لإجراء مكالمة طوارئ. لمزيد من المعلومات عن الخدمات الواردة أثناء الاتصال، يُرجى الاطّلاع علىInCallService
التعامل مع سيناريوهات الاتصال الشائعة
الاستفادة من واجهة برمجة التطبيقات ConnectionService
في مكالمتك
التفاعل مع الفئات الأخرى في android.telecom
طرد. توضّح الأقسام التالية سيناريوهات الاتصال الشائعة وكيفية
التطبيقات استخدام واجهات برمجة التطبيقات لمعالجتها.
الرد على المكالمات الواردة
يتغيّر مسار التعامل مع المكالمات الواردة عمّا إذا كانت هناك مكالمات في التطبيقات الأخرى أم لا. أم لا. يرجع سبب الاختلاف في التدفقات إلى أنّ إطار عمل الاتصالات بعض القيود عندما تكون هناك طلبات نشطة في التطبيقات الأخرى لضمان بيئة مستقرة لجميع تطبيقات الاتصال على الجهاز. لمزيد من المعلومات، معلومات، راجع قيود الاتصال.
ما مِن مكالمات نشطة في التطبيقات الأخرى
للردّ على المكالمات الواردة عندما لا تكون هناك مكالمات نشطة في التطبيقات الأخرى، اتّبِع الخطوات التالية: الخطوات التالية:
- يتلقّى تطبيقك مكالمة واردة جديدة باستخدام الآليات المعتادة.
- استخدِم طريقة
addNewIncomingCall(PhoneAccountHandle, Bundle)
من أجل لإعلام النظام الفرعي للاتصالات بشأن المكالمة الواردة الجديدة. - يرتبط النظام الفرعي للاتصالات بتنفيذ
ConnectionService
في تطبيقك ويطلب نسخة افتراضية جديدة. من الفئةConnection
التي تمثل البيانات الواردة الجديدة باستخدام طريقةonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - يُعلِم النظام الفرعي للاتصالات تطبيقك بأنّه يجب أن يعرض مكالمته الواردة.
من واجهة المستخدم باستخدام طريقة
onShowIncomingCallUi()
. - يعرض تطبيقك واجهة المستخدم الواردة باستخدام إشعار مرتبط
الإذن بالعرض ملء الشاشة. لمزيد من المعلومات، يُرجى الاطّلاع على "
onShowIncomingCallUi()
". - ويجب استدعاء الطريقة
setActive()
إذا كان المستخدم المكالمة الواردة، أوsetDisconnected(DisconnectCause)
مع تحديدREJECTED
على أنها المعلمة متبوعة إلى طريقةdestroy()
إذا كان المستخدم يرفض المكالمة الواردة.
المكالمات النشطة في التطبيقات الأخرى التي لا يمكن تعليقها
للرد على المكالمات الواردة عندما تكون هناك مكالمات نشطة في تطبيقات أخرى لا يمكنها قيد الانتظار، يُرجى اتّباع الخطوات التالية:
- يتلقّى تطبيقك مكالمة واردة جديدة باستخدام الآليات المعتادة.
- استخدِم طريقة
addNewIncomingCall(PhoneAccountHandle, Bundle)
من أجل لإعلام النظام الفرعي للاتصالات بشأن المكالمة الواردة الجديدة. - يرتبط النظام الفرعي للاتصالات بتنفيذ
ConnectionService
في تطبيقك ويطلب نسخة افتراضية جديدة. للكائنConnection
الذي يمثل العنصر الجديد مكالمة واردة باستخدام طريقةonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - يعرض النظام الفرعي للاتصالات واجهة مستخدم المكالمات الواردة لمكالمتك الواردة.
- إذا قبل المستخدم المكالمة، يطلب النظام الفرعي للاتصالات باستخدام طريقة
onAnswer()
. يجب استدعاء طريقة "setActive()
" للإشارة إلى شركة الاتصالات. النظام الفرعي الذي يتصل فيه الاتصال الآن. - إذا رفض المستخدم المكالمة، يطلب النظام الفرعي للاتصالات باستخدام طريقة
onReject()
. يجب استدعاء طريقةsetDisconnected(DisconnectCause)
مع تحديدREJECTED
كمعلمة متبوعة لاستدعاء طريقةdestroy()
.
إجراء مكالمات صادرة
يتضمن تدفق إجراء مكالمة صادرة التعامل مع احتمالية لا يمكن إجراء مكالمة نظرًا للقيود التي يفرضها إطار عمل الاتصالات. لمزيد من المعلومات، يُرجى الاطّلاع على قيود الاتصال.
لإجراء مكالمة صادرة، اتبع الخطوات التالية:
- يبدأ المستخدم مكالمة صادرة داخل تطبيقك.
- استخدِم الطريقة
placeCall(Uri, Bundle)
لإبلاغ النظام الفرعي للاتصالات حول المكالمات الصادرة الجديدة. اتّبِع الخطوات التالية اعتبارات معلمات الطريقة:- تمثل المعلمة
Uri
العنوان الذي يمكن فيه الذي يتم إجراء اتصاله إليه. بالنسبة إلى أرقام الهواتف العادية، استخدِم معرّف الموارد المنتظم (URI)tel:
. . - تتيح لك مَعلمة
Bundle
تقديم المعلومات. حول تطبيق الاتصال من خلال إضافة العنصرPhoneAccountHandle
في تطبيقك إلى العنصر الإضافيEXTRA_PHONE_ACCOUNT_HANDLE
. يجب أن يوفّر التطبيق الكائنPhoneAccountHandle
في كل مكالمة صادرة. - وتتيح لك مَعلمة
Bundle
أيضًا تحديد ما إذا كانت تشتمل المكالمة الصادرة على فيديو من خلال تحديد قيمةSTATE_BIDIRECTIONAL
في السمة الإضافيةEXTRA_START_CALL_WITH_VIDEO_STATE
. ضع في الاعتبار أنه بشكل افتراضي، يوجه النظام الفرعي للاتصالات مكالمات الفيديو إلى مكبّر الصوت.
- تمثل المعلمة
- يرتبط النظام الفرعي للاتصالات بـ
ConnectionService
في تطبيقك. التنفيذ. - إذا تعذّر على تطبيقك إجراء مكالمة صادرة، يتم إجراء مكالمات النظام الفرعي للاتصالات
طريقة
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
إبلاغ تطبيقك بتعذُّر إجراء المكالمة في الوقت الحالي. تطبيقك إبلاغ المستخدم بتعذُّر إجراء المكالمة. - إذا كان تطبيقك قادرًا على إجراء مكالمة صادرة، فإن النظام الفرعي للاتصالات
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
. من المفترض أن يعرض تطبيقك نسخة افتراضية من فئةConnection
لتمثيل المكالمة الصادرة الجديدة. بالنسبة مزيد من المعلومات عن الخصائص التي يجب إعدادها في عملية الربط راجِع تنفيذ خدمة الاتصال. - عندما يتم إجراء المكالمة الصادرة، يُرجى الاتصال بطريقة "
setActive()
" لإبلاغ النظام الفرعي للاتصالات. أن المكالمة نشطة.
إنهاء مكالمة
لإنهاء مكالمة، اتبع الخطوات التالية:
- يجب استدعاء الدالة
setDisconnected(DisconnectCause)
التي ترسلLOCAL
كمَعلمة إذا كان المستخدم. أنهى المكالمة، أو إرسالREMOTE
كمعلمة إذا أنهى الطرف الآخر الاتصال. - وعليك استدعاء الطريقة
destroy()
.
قيود المكالمات
لضمان تجربة اتصال متسقة وبسيطة للمستخدمين، يجب أن تتواصل
بعض القيود لإدارة المكالمات على الجهاز. بالنسبة
ضع في اعتبارك أن المستخدم قد ثبَّت تطبيقين للاتصال يقدمان
واجهة برمجة التطبيقات ConnectionService
المُدارة ذاتيًا وFooTalk
BarTalk. في هذه الحالة، تنطبق القيود التالية:
بالنسبة إلى الأجهزة التي تعمل بالإصدار 27 من واجهة برمجة التطبيقات أو المستويات الأدنى، يمكن لتطبيق واحد فقط الاحتفاظ مكالمة جارية في أي وقت محدد. يعني هذا القيد أنه في حين أن المستخدم لديه مكالمة جارية باستخدام تطبيق FooTalk، لا يمكن لتطبيق BarTalk بدء أو استقبال مكالمة جديدة.
على الأجهزة التي تعمل بالمستوى 28 من واجهة برمجة التطبيقات أو المستويات الأعلى، في حال استخدام كل من FooTalk وBarTalk بيان
CAPABILITY_SUPPORT_HOLD
أوCAPABILITY_HOLD
ثم يمكن للمستخدم الاحتفاظ بأكثر من مكالمة جارية عن طريق التبديل بين التطبيقات لبدء مكالمة أخرى أو الرد عليها.إذا كان المستخدم يشارك في مكالمات مُدارة عادية (على سبيل المثال، باستخدام تطبيق الهاتف أو برنامج الاتصال المدمج)، لا يمكن أن يكون المستخدم في المكالمات التي نشأت من تطبيقات الاتصال وهذا يعني أنه إذا كان المستخدم يجري مكالمة عادية باستخدام مشغّل شبكة الجوّال، فلا يمكن أن يكونا أيضًا في مكالمة FooTalk أو BarTalk بشكل متزامن.
ينقطع النظام الفرعي للاتصالات مكالمات تطبيقك إذا طلب المستخدم مكالمة طوارئ.
لا يمكن لتطبيقك استقبال المكالمات أو إجراؤها أثناء إجراء المستخدم لمكالمة طوارئ.
إذا كانت هناك مكالمة جارية في تطبيق آخر للاتصال عند تلقّي تطبيقك مكالمة واردة، فإن الرد على المكالمة الواردة يؤدي إلى إنهاء أي مكالمات جارية في تطبيق آخر. يجب ألا يعرض التطبيق واجهة المستخدم المعتادة للمكالمات الواردة. يعرض إطار عمل الاتصالات واجهة مستخدم المكالمات الواردة ويبلغك إنهاء مكالماته الجارية عند ردّ المستخدم على المكالمة الجديدة هذا النمط يعني أنه إذا كان المستخدم في مكالمة FooTalk ويتلقى تطبيق BarTalk مكالمة واردة، يُعلم إطار عمل الاتصالات المستخدم بأن لديه مكالمة BarTalk الواردة وأن الرد على مكالمة BarTalk سوف ينتهي مكالمة FooTalk.
استخدام تطبيق الهاتف التلقائي
تطبيق الاتصال/الهاتف الافتراضي هو أحد التطبيقات التي توفر واجهة المستخدم أثناء المكالمة أثناء إجراء
في مكالمة. إضافةً إلى ذلك، يوفّر التطبيق للمستخدم وسيلة لبدء المكالمات والاطّلاع على سجلّ المكالمات.
على أجهزتهم. يتم تضمين جهاز مع تطبيق برنامج الاتصال/الهاتف التلقائي الذي يوفّره النظام. المستخدِم
اختيار تطبيق واحد لتولي هذا الدور من تطبيق النظام. هو تطبيق يريد
نفِّذ هذا الدور باستخدام RoleManager
لطلب ملء
الدور RoleManager.ROLE_DIALER
.
يوفّر تطبيق الهاتف التلقائي واجهة مستخدم أثناء إجراء مكالمة، ويتم تشغيل
ليس في وضع السيارة (أي أن UiModeManager#getCurrentModeType()
ليس في وضع السيارة
Configuration.UI_MODE_TYPE_CAR
).
لملء الدور "RoleManager.ROLE_DIALER
"، يجب أن يستوفي التطبيق
عدد المتطلبات:
- ويجب أن يتعامل مع هدف
Intent#ACTION_DIAL
. وهذا يعني أنّ التطبيق يجب أن يوفّر واجهة مستخدم لوحة اتصال يمكن للمستخدم من خلالها بدء مكالمات صادرة. - يجب أن تنفيذ واجهة برمجة التطبيقات
InCallService
بالكامل وأن يوفّر مكالمة واردة واجهة مستخدم، بالإضافة إلى واجهة مستخدم للمكالمات الجارية.
ملاحظة: إذا كان التطبيق الذي يملأ RoleManager.ROLE_DIALER
يعرض
null
InCallService
أثناء الربط، سينخفض إطار عمل الاتصالات تلقائيًا.
استخدام تطبيق "برنامج الاتصال" المُحمَّل مُسبَقًا على الجهاز. سيعرض النظام إشعارًا
المستخدم لإعلامه بأن مكالمته استمرت باستخدام تطبيق برنامج الاتصال المُحمَّل مُسبَقًا.
يجب ألا يعرض التطبيق مطلقًا ربط null
، فإن القيام بذلك يعني أنه لا يفي
متطلبات RoleManager.ROLE_DIALER
.
ملاحظة: إذا كان تطبيقك يملأ RoleManager.ROLE_DIALER
ويُجري تغييرات على
عدم تلبية متطلبات هذا الدور بعد الآن،
سيُزيل RoleManager
تطبيقك تلقائيًا من الدور ويغلقه.
تطبيقك. على سبيل المثال، إذا كنت تستخدم
من PackageManager.setComponentEnabledSetting(ComponentName, int, int)
إلى
إيقاف InCallService
الذي يفصح عنه تطبيقك آليًا في ملف البيان الخاص به: تطبيقك
الشركة بعد الآن في تلبية المتطلبات
المتوقعة من
RoleManager.ROLE_DIALER
سيتم استخدام برنامج الاتصال المُحمَّل مُسبَقًا دائمًا عندما يُجري المستخدم مكالمة طوارئ، حتى إذا كان
يملأ التطبيق الدور "RoleManager.ROLE_DIALER
". لضمان النموذج الأمثل
المستخدم عند إجراء مكالمة طوارئ، على برنامج الاتصال التلقائي "دائمًا"
TelecomManager.placeCall(Uri, Bundle)
لإجراء المكالمات (بما في ذلك
مكالمات الطوارئ). يضمن هذا الإجراء أنّ المنصة قادرة على التحقق من أنّ الطلب وارد من
برنامج الاتصال الافتراضي. إذا كان تطبيق برنامج اتصال غير محمَّل مسبقًا يستخدم Intent#ACTION_CALL
لوضع
مكالمة طوارئ، ستتم زيادتها إلى تطبيق برنامج الاتصال المُحمَّل مُسبَقًا باستخدام Intent#ACTION_DIAL
.
للتأكيد؛ فهذه تجربة مستخدم دون المستوى الأمثل.
في ما يلي مثال على تسجيل البيان لنطاق InCallService
. البيانات الوصفية
تشير السمة TelecomManager#METADATA_IN_CALL_SERVICE_UI
إلى أنّ هذا الخيار
يهدف تنفيذ InCallService
إلى استبدال واجهة المستخدم المضمَّنة أثناء المكالمة.
تشير البيانات الوصفية TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
إلى أن
سيشغِّل تطبيق "InCallService
" نغمة الرنين للمكالمات الواردة. عرض
أدناه لمزيد من المعلومات حول عرض المكالمة الواردة
واجهة المستخدم وتشغيل نغمة الرنين في التطبيق.
<service android:name="your.package.YourInCallServiceImplementation"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
<meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
ملاحظة: يجب عدم وضع علامة على InCallService
باستخدام السمة.
android:exported="false"
؛ قد يؤدي ذلك إلى عدم الالتزام بعملية التنفيذ
أثناء المكالمات
بالإضافة إلى تنفيذ واجهة برمجة تطبيقات InCallService
، عليك أيضًا الإفصاح عن نشاط في
البيان الذي يعالج هدف Intent#ACTION_DIAL
يوضح المثال أدناه
كيفية القيام بذلك:
<activity android:name="your.package.YourDialerActivity"
android:label="@string/yourDialerActivityLabel">
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
عندما يثبّت أحد المستخدمين تطبيقك ويشغِّله لأول مرة، يجب عليك استخدام
RoleManager
ليطلب من المستخدم معرفة ما إذا كان يريد من تطبيقك
ليكون تطبيق الهاتف الافتراضي الجديد.
يوضّح الرمز أدناه كيف يمكن لتطبيقك أن يطلب أن يصبح تطبيق الهاتف أو برنامج الاتصال التلقائي:
private static final int REQUEST_ID = 1;
public void requestRole() {
RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER);
startActivityForResult(intent, REQUEST_ID);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ID) {
if (resultCode == android.app.Activity.RESULT_OK) {
// Your app is now the default dialer app
} else {
// Your app is not the default dialer app
}
}
}
الوصول إلى InCallService في الأجهزة القابلة للارتداء
-
إذا كان تطبيقك مصاحبًا تابعًا لجهة خارجية ويريد الوصول إلى واجهات برمجة تطبيقات InCallService، ما
يمكن أن تفعله هذه التطبيقات هي:
- بيان إذن MANAGE_ONGOING_CALLS في ملف البيان
- الإقران بجهاز فعلي قابل للارتداء عبر
CompanionDeviceManager
API كتطبيق مصاحب. يمكنك الاطّلاع على: https://developer.android.com/guide/topics/connectivity/companion-device-pairing - تنفيذ InCallService هذا باستخدام إذن BIND_INCALL_SERVICE
عرض إشعار المكالمات الواردة
عندما يتلقّى تطبيقك مكالمة واردة جديدة عبرInCallService#onCallAdded(Call)
،
المسئول عن عرض واجهة المستخدم الخاصة بالمكالمات الواردة. يجب أن يقوم بذلك باستخدام
NotificationManager
واجهات برمجة تطبيقات لنشر إشعار بمكالمات واردة جديدة
في الحالات التي يفصح فيها تطبيقك عن البيانات الوصفية TelecomManager#METADATA_IN_CALL_SERVICE_RINGING
،
سيكون مسؤولاً عن تشغيل نغمة الرنين للمكالمات الواردة. يجب أن ينشئ تطبيقك
NotificationChannel
التي تحدّد نغمة الرنين المطلوبة مثلاً:
NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
NotificationManager.IMPORTANCE_MAX);
// other channel setup stuff goes here.
// We'll use the default system ringtone for our incoming call notification channel. You can
// use your own audio resource here.
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
channel.setSound(ringtoneUri, new AudioAttributes.Builder()
// Setting the AudioAttributes is important as it identifies the purpose of your
// notification sound.
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
NotificationManager mgr = getSystemService(NotificationManager.class);
mgr.createNotificationChannel(channel);
عندما يتلقّى تطبيقك مكالمة واردة جديدة، يُنشئ Notification
مكالمة واردة وربطها بقناة إشعارات المكالمات الواردة يمكنك تحديد
PendingIntent
في الإشعار الذي سيؤدي إلى تشغيل وضع ملء الشاشة
واجهة المستخدم للمكالمات الواردة وسيعرض إطار عمل "إدارة الإشعارات" إشعارك على شكل
إذا كان المستخدم يستخدم الهاتف بشكل نشط. عندما لا يستخدم المستخدم
يتم استخدام واجهة مستخدم المكالمات الواردة بملء الشاشة بدلاً من ذلك.
مثلاً:
// Create an intent which triggers your fullscreen incoming call user interface.
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(context, YourIncomingCallActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
// Build the notification as an ongoing high priority item; this ensures it will show as
// a heads up notification which slides down over top of the current content.
final Notification.Builder builder = new Notification.Builder(context);
builder.setOngoing(true);
builder.setPriority(Notification.PRIORITY_HIGH);
// Set notification content intent to take user to the fullscreen UI if user taps on the
// notification body.
builder.setContentIntent(pendingIntent);
// Set full screen intent to trigger display of the fullscreen UI when the notification
// manager deems it appropriate.
builder.setFullScreenIntent(pendingIntent, true);
// Setup notification content.
builder.setSmallIcon( yourIconResourceId );
builder.setContentTitle("Your notification title");
builder.setContentText("Your notification content.");
// Use builder.addAction(..) to add buttons to answer or reject the call.
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
```