Intent
هو عنصر مراسلة يمكنك استخدامه لطلب إجراء
من مكوّن تطبيق آخر.
على الرغم من أن الأهداف تسهل التواصل بين المكونات بعدة طرق، إلا أن هناك ثلاثة
تشمل حالات الاستخدام الأساسية التالية:
- بدء نشاط
يمثّل
Activity
شاشة واحدة في التطبيق. يمكنك بدء مثيل جديد لعنصرActivity
من خلال تمريرIntent
إلىstartActivity()
. تصف السمةIntent
النشاط المطلوب بدؤه وتحمل أي بيانات ضرورية.إذا كنت تريد الحصول على نتيجة من النشاط عند الانتهاء، الاتصال بخدمة
startActivityForResult()
يتلقّى نشاطك النتيجة كعنصرIntent
منفصل في ردّ الاتصالonActivityResult()
لنشاطك. لمزيد من المعلومات، يُرجى الاطّلاع على دليل الأنشطة. - بدء خدمة
Service
هو مكوِّن ينفذ العمليات في الخلفية. بدون واجهة مستخدم. باستخدام الإصدار 5.0 من نظام التشغيل Android (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك بدء خدمة باستخدامJobScheduler
. لمزيد من المعلومات عنJobScheduler
، يُرجى الاطّلاع علىAPI-reference documentation
.بالنسبة إلى الإصدارات الأقدم من Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات)، يمكنك بدء خدمة باستخدام methods من فئة
Service
. يمكنك بدء خدمة لإجراء عملية لمرة واحدة (مثل تنزيل ملف) من خلال تمريرIntent
إلىstartService()
. يصفIntent
الخدمة التي سيتمّ تشغيلها ويحمل أي بيانات ضرورية.إذا تم تصميم الخدمة باستخدام واجهة بين العميل والخادم، يمكنك الربط بالخدمة من مكوّن آخر عن طريق تمرير
Intent
إلىbindService()
. لمزيد من المعلومات، يُرجى الاطّلاع على دليل الخدمات. - إرسال بث
البث هو رسالة يمكن أن يتلقاها أي تطبيق. يُرسِل النظام محتوًى مختلفًا للبثّ لأحداث النظام، مثل بدء تشغيل النظام أو بدء شحن الجهاز. يمكنك إرسال بث إلى تطبيقات أخرى من خلال ضبط
Intent
. إلىsendBroadcast()
أوsendOrderedBroadcast()
توضّح هذه الصفحة آلية عمل الأهداف وكيفية استخدامها. للحصول على معلومات ذات صلة، يُرجى مراجعة التفاعل مع التطبيقات الأخرى ومشاركة المحتوى
أنواع الأهداف
هناك نوعان من النوايا:
- تحدِّد المقصودات الصريحة المكوّن الذي سيلبّي المقصود من التطبيق، وذلك من خلال تحديد
ComponentName
كامل. وسوف هدفًا صريحًا لبدء مكون في تطبيقك الخاص، لأنك تعرف اسم فئة النشاط أو الخدمة التي تريد بدئها. على سبيل المثال، يمكنك بدء نشاط جديد في تطبيقك استجابةً للإجراء الذي يتّخذه المستخدم، أو بدء خدمة لتنزيل ملف في الخلفية. - لا تحدِّد الأهداف الضمنية اسم مكوّن معيّنًا، بل تحدِّد بدلاً من ذلك إجراءً عامًا لإجرائه، ما يسمح لمكوّن من تطبيق آخر بتنفيذه. على سبيل المثال، إذا كنت تريد إظهار موقع جغرافي للمستخدم على خريطة، يمكنك استخدام نية ضمنية لطلب أن يعرض تطبيق آخر مزوّد بإمكانية عرض موقع جغرافي محدّد على الخريطة.
يوضِّح الشكل 1 كيفية استخدام النية عند بدء نشاط. عندما يُحدِّد عنصر
Intent
اسمًا لمكوّن نشاط معيّن بشكل صريح، يبدأ النظام
هذا المكوّن على الفور.

الشكل 1. كيف يكون الغرض الضمني
تسليمه من خلال النظام لبدء نشاط آخر: [1] يُنشئ النشاط أ
Intent
يتضمن وصف الإجراء ويمرره إلى startActivity()
[2] يبحث نظام Android في جميع
التطبيقات لفلتر أهداف يتطابق مع الهدف. عند العثور على مطابقة، [3] يشغّل النظام
النشاط المطابق (العملية ب) من خلال استدعاء طريقة onCreate()
ونقل القيمة Intent
إليها.
عند استخدام هدف ضمني، يعثر نظام Android على المكوّن المناسب لبدء
من خلال مقارنة محتوى intent بفلاتر الأهداف المعرَّفة في ملف البيان للتطبيقات الأخرى على
الخاص بك. إذا تطابق الغرض مع فلتر غرض، يبدأ النظام هذا المكوّن ويرسله
كائن Intent
. إذا كانت عدّة فلاتر أهداف متوافقة،
يعرض النظام مربّع حوار حتى يتمكّن المستخدم من اختيار التطبيق الذي يريد استخدامه.
فلتر الأهداف هو تعبير في ملف بيان التطبيق نوع الأهداف التي يمكن للمكوِّن يرغب في الحصول عليه. فعلى سبيل المثال، بإعلان فلتر أهداف لأحد الأنشطة، تُتيح للتطبيقات الأخرى بدء نشاطك مباشرةً بنيّة معيّنة من النية. وبالمثل، إذا لم تحدِّد أي فلاتر أهداف لنشاط معيّن، لا يمكن بدؤه إلا باستخدام هدف صريح.
تحذير: لضمان أمان تطبيقك، يجب استخدام Service
معيّن عند بدء Service
وعدم تحديد فلاتر Service
لخدماتك. يشكّل استخدام نية ضمنية لبدء خدمة خطرًا على
الأمن لأنّه لا يمكنك التأكّد من الخدمة التي ستستجيب للنية،
ولا يمكن للمستخدم معرفة الخدمة التي يتم تشغيلها. بدءًا من الإصدار 5.0 من Android (المستوى 21 لواجهة برمجة التطبيقات)، يُرسِل النظام
استثناءً في حال استدعاء bindService()
باستخدام نية ضمنية.
بناء هدف
يحتوي عنصر Intent
على معلومات يستخدمها نظام Android.
لتحديد المكون الذي سيتم البدء فيه (مثل اسم المكون أو المكون بالضبط
فئة يجب أن تتلقى intent)، بالإضافة إلى المعلومات التي يستخدمها مكون المستلم في
من أجل تنفيذ الإجراء بشكل صحيح (مثل الإجراء المطلوب اتخاذه والبيانات التي يجب التصرف بناءً عليها).
في ما يلي المعلومات الأساسية الواردة في Intent
:
- اسم المكوّن
- اسم المكوّن المطلوب بدؤه
هذا الإجراء اختياري، ولكنه يُعدّ المعلومات المهمة التي تجعل الintent واضحًا، ما يعني أنّه يجب إرسال الintent إلى مكوّن التطبيق فقط الذي يحدّده اسم المكوّن. وبدون اسم المكوِّن، يكون الغرض ضمنيًا يقرر المكون الذي يجب أن يتلقى الغرض بناءً على معلومات النية الأخرى (مثل الإجراء والبيانات والفئة - كما هو موضَّح أدناه). إذا كنت بحاجة إلى بدء مخطط في تطبيقك، فيجب تحديد اسم المكوِّن.
ملاحظة: عند بدء
Service
، حدِّد دائمًا اسم المكوّن. وبخلاف ذلك، لا يمكنك التأكد من الخدمة وسوف يستجيب للغرض، ولا يمكن للمستخدم معرفة أي خدمة تبدأ.هذا الحقل من
Intent
عبارة عنComponentName
، الذي يمكنك تحديده باستخدام اسم الفئة المؤهلة للمكون المستهدف، بما في ذلك اسم حزمة التطبيق، على سبيل المثال،com.example.ExampleActivity
يمكنك ضبط اسم المكوِّن باستخدامsetComponent()
أوsetClass()
أوsetClassName()
أو أو باستخدام الدالة الإنشائيةIntent
. - الإجراء
- سلسلة تحدد الإجراء العام المطلوب تنفيذه (مثل عرض أو اختيار).
في حال حدوث نية بث، هذا هو الإجراء الذي تم تنفيذه ويتم الإبلاغ عنه. يحدد الإجراء إلى حد كبير كيفية تنظيم بقية الهدف، خاصةً المعلومات الموجودة في البيانات والإضافات.
يمكنك تحديد إجراءاتك الخاصة لاستخدامها من قِبل النوايا داخل تطبيقك (أو لاستخدامها من قِبل التطبيقات الأخرى لاستدعاء المكوّنات في تطبيقك)، ولكنك عادةً ما تحدّد ثوابت الإجراءات التي تحدّدها فئة
Intent
أو فئات إطار العمل الأخرى. إليك بعض الأمثلة الإجراءات الشائعة لبدء نشاط وهي:ACTION_VIEW
- استخدِم هذا الإجراء في نية مع
startActivity()
عندما يكون لديك بعض المعلومات التي يمكن أن يعرضها النشاط للمستخدم، مثل صورة لعرضها في تطبيق معرض صور أو عنوان لعرضه في تطبيق خرائط. ACTION_SEND
- يُعرف أيضًا باسم نية المشاركة، ويجب استخدام هذا الغرض في
startActivity()
، عندما يكون لديك بعض البيانات التي يمكن للمستخدم استخدامها. مشاركتها من خلال تطبيق آخر، مثل تطبيق البريد الإلكتروني أو تطبيق المشاركة على وسائل التواصل الاجتماعي
اطّلِع على مرجع فئة
Intent
لمعرفة المزيد. الثوابت التي تحدد الإجراءات العامة. تم تحديد إجراءات أخرى مكان آخر في إطار عمل Android، مثلSettings
لتنفيذ الإجراءات تفتح شاشات محدّدة في تطبيق "الإعدادات" على النظام.يمكنك تحديد الإجراء لطلب باستخدام
setAction()
أو باستخدام عنصر إنشاءIntent
.إذا حدّدت إجراءاتك الخاصة، احرص على تضمين اسم حزمة تطبيقك كبادئة، كما هو موضّح في المثال التالي:
- البيانات
- معرّف الموارد المنتظم (URI) (كائن
Uri
) الذي يشير إلى البيانات التصرف على و/أو نوع MIME لتلك البيانات. ويعتمد نوع البيانات المقدَّمة بشكل عام على إجراء الغرض. بالنسبة على سبيل المثال، إذا كان الإجراءACTION_EDIT
، يجب أن تحتوي البيانات على السمة معرّف الموارد المنتظم (URI) للمستند المطلوب تعديله.عند إنشاء هدف، من المهم غالبًا تحديد نوع البيانات (نوع MIME) بالإضافة إلى معرّف الموارد المنتظم (URI). على سبيل المثال، النشاط الذي يمكنه عرض الصور قد لا يتمكن من تشغيل ملف صوتي، على الرغم من أنّ تنسيقات معرّفات الموارد المنتظمة قد تكون متشابهة. يساعد تحديد نوع MIME لبياناتك نظام Android أفضل مكون للحصول على هدفك. ومع ذلك، يمكن في بعض الأحيان استنتاج نوع MIME من معرّف الموارد المنتظم (URI)، خاصةً عندما تكون البيانات هي معرّف موارد
content:
المنتظم. يشيرcontent:
URI إلى أنّ البيانات متوفّرة على الجهاز ويتحكم فيهاContentProvider
، ما يجعل نوع MIME للبيانات مرئيًا للنظام.لضبط عنوان URI للبيانات فقط، اتصل بالرقم
setData()
. لضبط نوع MIME فقط، يمكنك طلبsetType()
. إذا لزم الأمر، يمكن ضبط كليهما بشكلٍ صريح باستخدامsetDataAndType()
.تنبيه: إذا كنت تريد ضبط كل من معرّف الموارد المنتظم (URI) ونوع MIME، عدم الاتصال بـ
setData()
setType()
لأن كل منهما يؤدي إلى إبطال قيمة الآخر. استخدامsetDataAndType()
دائمًا لضبط كليهما معرّف الموارد المنتظم (URI) ونوع MIME - الفئة
- سلسلة تحتوي على معلومات إضافية عن نوع المكوّن
الذي من المفترض أن يعالج النية يمكن أن يكون أي عدد من أوصاف الفئات
موضوعة في هدف، ولكن معظم الأهداف لا تتطلب فئة.
في ما يلي بعض الفئات الشائعة:
CATEGORY_BROWSABLE
- يسمح النشاط المستهدَف لمتصفّح الويب ببدءه لعرض البيانات التي يشير إليها رابط، مثل صورة أو رسالة إلكترونية.
CATEGORY_LAUNCHER
- النشاط هو النشاط الأولي للمهمة ويتم إدراجه في مشغّل تطبيقات النظام.
راجِع وصف الصف
Intent
للحصول على القائمة الكاملة الفئات.يمكنك تحديد فئة باستخدام
addCategory()
.
تمثل هذه الخصائص المدرجة أعلاه (اسم المكون والإجراء والبيانات والفئة) تحديد خصائص النية. من خلال قراءة هذه السمات، يتمكّن نظام Android من تحديد مكوّن التطبيق الذي يجب تشغيله. ومع ذلك، يمكن أن يحمل النية معلومات إضافية لا تؤثر وكيف يتم حلها إلى مكون التطبيق. يمكن أن يوفّر النيّة أيضًا المعلومات التالية:
- الإضافات
- أزواج المفتاح/القيمة التي تتضمّن المعلومات الإضافية المطلوبة لإنجازها
الإجراء المطلوب.
تمامًا كما تستخدم بعض الإجراءات أنواعًا معيّنة من عناوين URL للبيانات، تستخدم بعض الإجراءات أيضًا عناصر إضافية معيّنة.
يمكنك إضافة بيانات إضافية باستخدام طرق
putExtra()
مختلفة، تقبل كل منهما معلمتين وهما: اسم المفتاح والقيمة. يمكنك أيضًا إنشاء عنصرBundle
يتضمّن كل البيانات الإضافية، ثم إدراجBundle
فيIntent
باستخدامputExtras()
.على سبيل المثال، عند إنشاء نية لإرسال رسالة بريد إلكتروني تحتوي
ACTION_SEND
، يمكنك تحديد مستلم إلى من خلالEXTRA_EMAIL
، وحدد الموضوع المفتاحEXTRA_SUBJECT
:تحدّد فئة
Intent
العديد من الثوابتEXTRA_*
لأنواع البيانات الموحدة. إذا كنت بحاجة إلى الإفصاح عن مفاتيحك الإضافية (للأغراض التي الذي يتلقّاه تطبيقك)، فتأكد من تضمين اسم حزمة التطبيق كبادئة، كما هو موضح في المثال التالي:const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
تحذير: لا تستخدِم بيانات
Parcelable
أوSerializable
عند إرسال نية تتوقّع أن يتلقّاها تطبيق آخر. إذا حاول تطبيق الوصول إلى البيانات في عنصرBundle
ولكن ليس لديه إذن الوصول إلى الفئة المجزّأة أو المتسلسلة، يُنشئ النظام سوىRuntimeException
. - العلامات
- يتم تحديد العلامات في الفئة
Intent
والتي تعمل كبيانات وصفية والنية. قد تُعلم العلامات نظام Android بكيفية بدء نشاط (على سبيل المثال، المهمة يجب أن ينتمي النشاط إليه) وكيفية التعامل معه بعد إطلاقه (على سبيل المثال، ما إذا كان ينتمي إلى قائمة المواقع الإلكترونية الأنشطة).لمزيد من المعلومات، يُرجى الاطّلاع على طريقة
setFlags()
.
مثال على نية صريحة
الغرض الصريح هو ذلك الذي تستخدمه لتشغيل مكون تطبيق معين، مثل
نشاط أو خدمة معيّنة في تطبيقك لإنشاء نية صريحة، حدد
اسم المكوِّن للكائن Intent
—كل
خصائص intent الأخرى اختيارية.
على سبيل المثال، إذا أنشأت خدمة في تطبيقك باسم DownloadService
مصمّمة لتنزيل ملف من الويب، يمكنك تشغيلها باستخدام الرمز البرمجي التالي:
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse
(fileUrl)); startService(downloadIntent);
يزوِّد Intent(Context, Class)
المنشئ التطبيق Context
والمكوّن
بكائن Class
. وبناءً على ذلك،
يبدأ هذا القصد صراحةً فئة DownloadService
في التطبيق.
لمزيد من المعلومات حول إنشاء خدمة وبدء تشغيلها، يمكنك الاطلاع على دليل الخدمات.
مثال على النية الضمنية
تحدِّد النية الضمنية إجراءً يمكنه استدعاء أي تطبيق على الجهاز يمكنه تنفيذ الإجراء. يكون استخدام النية الضمنية مفيدًا عندما لا يستطيع تطبيقك تنفيذ الإجراء، ولكن من المحتمل أن تتمكّن تطبيقات أخرى من تنفيذه وتريد من المستخدم اختيار التطبيق الذي يريد استخدامه.
على سبيل المثال، إذا كان لديك محتوى تريد أن يشاركه المستخدم مع أشخاص آخرين،
أنشِئ هدفًا
مع إجراء ACTION_SEND
وتضيف ميزات إضافية تحدد المحتوى الذي تريد مشاركته. عند استدعاء startActivity()
بهذه النية، يمكن للمستخدم اختيار تطبيق لمشاركة المحتوى من خلاله.
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
// Create the text message with a string. Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
عند استدعاء startActivity()
، يفحص النظام
جميع التطبيقات المثبَّتة لتحديد التطبيقات التي يمكنها معالجة هذا النوع من النية (نية
تتضمّن الإجراء ACTION_SEND
وتحمل بيانات "text/plain"
). إذا كان هناك تطبيق واحد فقط يمكنه معالجة الطلب، سيتم فتح هذا التطبيق على الفور وسيتم منحه
الهدف. إذا لم تتمكّن أي تطبيقات أخرى من معالجة ذلك، يمكن لتطبيقك رصد
ActivityNotFoundException
التي تحدث. إذا كانت أنشطة متعدّدة تقبل النية، يُعرِض النظام مربّع حوار مثل مربّع الحوار المعروض في الشكل 2، ليتمكّن المستخدم من اختيار التطبيق الذي يريد استخدامه.
يمكنك أيضًا الاطّلاع على مزيد من المعلومات حول تشغيل تطبيقات أخرى في الدليل المتعلّق بإرسال المستخدم إلى تطبيق آخر.

الشكل 2. مربّع حوار اختيار
فرض أداة اختيار التطبيقات
عندما يستجيب أكثر من تطبيق واحد لهدفك الضمني، يمكن للمستخدم اختيار التطبيق الذي يريد استخدامه وجعله هو الخيار التلقائي اتخاذ القرار. تُعد القدرة على تحديد خيار افتراضي مفيدة عند تنفيذ إجراء يريد المستخدم من أجله ربما يريد استخدام التطبيق نفسه في كل مرة، على سبيل المثال عند فتح صفحة ويب (المستخدمون يفضلون غالبًا متصفح ويب واحدًا فقط).
ومع ذلك، إذا كان بإمكان تطبيقات متعددة الاستجابة لطلب البحث وقد يريد المستخدم استخدام
تطبيق مختلف في كل مرة، يجب عرض مربّع حوار اختيار بشكل صريح. يسأل مربع حوار المُختار
المستخدم لتحديد التطبيق الذي يريد استخدامه في الإجراء (لا يمكن للمستخدم اختيار تطبيق تلقائي
الإجراء). على سبيل المثال، عندما ينفِّذ تطبيقك "مشاركة" من خلال الإجراء ACTION_SEND
، قد يرغب المستخدمون في المشاركة باستخدام تطبيق مختلف، وذلك حسب ما يلي:
على الوضع الحالي، لذا يجب عليك دائمًا استخدام مربع حوار المُختار، كما هو موضح في الشكل 2.
لعرض أداة الاختيار، أنشئ Intent
باستخدام createChooser()
ونقلها إلى startActivity()
، كما هو موضّح في المثال التالي.
يعرض هذا المثال مربّع حوار يتضمّن قائمة بالتطبيقات التي تستجيب للهدف الذي تم تمريره إلى طريقة createChooser()
وتستخدم النص المقدّم على أنّه
عنوان مربع الحوار.
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... // Always use string resources for UI text. // This says something like "Share this photo with" String title = getResources().getString(R.string.chooser_title); // Create intent to show the chooser dialog Intent chooser = Intent.createChooser(sendIntent, title); // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
رصد عمليات الإطلاق غير الآمنة حسب نية العميل
قد يطلق تطبيقك أهدافًا للتنقّل بين المكوّنات داخل تطبيقك، أو لتنفيذ إجراء نيابةً عن تطبيق آخر. لتحسين أمان النظام الأساسي، يوفّر نظام التشغيل Android 12 (المستوى 31 من واجهة برمجة التطبيقات) والإصدارات الأحدث ميزة تصحيح الأخطاء التي تحذرك إذا كان تطبيقك يُجري عملية إطلاق غير آمنة لهدف. على سبيل المثال، قد يؤدي تطبيقك إلى إجراء عملية إطلاق غير آمنة لرسالة غرض مُدمَجة، وهي رسالة غرض يتم تمريرها كإضافة في رسالة غرض أخرى.
إذا نفَّذ تطبيقك كلا الإجراءَين التاليَين، يرصد النظام عملية إطلاق intent غير آمنة، ويحدث انتهاك StrictMode:
- يفصل تطبيقك عن هدف مدمَج من العناصر الإضافية لما يتم إرساله.
- يبدأ تطبيقك على الفور في تشغيل تطبيق.
باستخدام هذا الغرض المتداخل،
مثل تمرير النية إلى
startActivity()
,startService()
، أوbindService()
لمزيد من التفاصيل حول كيفية تحديد هذا الموقف وإجراء تغييرات في تطبيقك، الاطّلاع على مشاركة المدونة حول دمج Android النوايا على Medium.
التحقّق من عمليات الإطلاق غير الآمنة حسب نية العميل
للتحقّق من عمليات إطلاق النوايا غير الآمنة في تطبيقك، يمكنك استدعاء detectUnsafeIntentLaunch()
عند ضبط VmPolicy
، كما هو موضّح في مقتطف الرمز البرمجي التالي. إذا رصد
تطبيقك انتهاكًا لـ StrictMode، قد تحتاج إلى إيقاف تنفيذ التطبيق للحماية
من المعلومات الحسّاسة المحتملة.
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
استخدام النوايا بشكل أكثر مسؤولية
لتقليل احتمالية إطلاق نية غير آمنة وانتهاك StrictMode، اتّبِع أفضل الممارسات التالية.
انسخ العناصر الإضافية الأساسية فقط ضمن الأهداف، ونفِّذ أي إجراءات ضرورية
والصحة والتحقق من الصحة قد ينسخ تطبيقك الميزات الإضافية من intent إلى
نية أخرى تُستخدم لإطلاق مكون جديد. يحدث هذا عندما
مكالمات التطبيقات
putExtras(Intent)
أو
putExtras(Bundle)
فإذا كان التطبيق يجري إحدى هذه العمليات، فانسخ فقط الميزات الإضافية التي
يتوقعه مكون الاستقبال. إذا كان الغرض الآخر (الذي يتلقّى النسخة)
يشغّل مكوّنًا لم يتم
تصديره، عليك إزالة البيانات غير الصالحة من ملف extras و
التحقّق منه قبل نسخه إلى الغرض الذي يشغّل المكوّن.
لا تصدِّر مكوّنات تطبيقك بدون داعٍ. على سبيل المثال، إذا
تعتزم تشغيل أحد مكونات التطبيق باستخدام هدف داخلي مدمج، تعيين
سمة android:exported
للمكون إلى false
.
استخدام PendingIntent
بدلاً من
هدف مدمَج. بهذه الطريقة، عندما يفكك تطبيق آخر حِزمة PendingIntent
من Intent
المضمّنة فيه، يمكن للتطبيق الآخر تشغيل PendingIntent
باستخدام هوية تطبيقك. ويسمح هذا الإعداد للتطبيق الآخر بتشغيل أي مكوّن بأمان في تطبيقك، بما في ذلك المكوّن الذي لم يتم تصديره.
يوضح المخطّط البياني في الشكل 2 طريقة التحكّم في النظام من (العميل) تطبيق آخر (خدمة) ثم الرجوع إلى تطبيقك:
- ينشئ تطبيقك هدفًا يستدعي نشاطًا في تطبيق آخر. ضمن
هذا الغرض، تضيف كائن
PendingIntent
كعنصر إضافي. هذا الطلب في انتظار المراجعة يستدعي مكونًا في تطبيقك؛ لا يتم تصدير هذا المكون. - وعند تلقّي هدف التطبيق، يعمل التطبيق الآخر على استخراج البيانات المدمجة
عنصر
PendingIntent
. - يستدعي التطبيق الآخر الطريقة
send()
على عنصرPendingIntent
. - بعد إعادة عنصر التحكّم إلى تطبيقك، يستدعي النظام الطلب الذي كانت في انتظار المراجعة. نية الشراء باستخدام سياق التطبيق.
الشكل 2. مخطّط بياني للتواصل بين التطبيقات عند استخدام قيد ملف شخصي مُدمج
تلقّي نية ضمنية
للإعلان عن الأهداف الضمنية التي يمكن أن يتلقّاها تطبيقك، اذكر فلترًا واحدًا أو أكثر من فلاتر الأهداف بالنسبة إلى
كل مكوّن من مكوّنات تطبيقك مع <intent-filter>
عنصر في ملف البيان.
يحدد كل فلتر أهداف نوع الأهداف التي يقبلها بناءً على إجراء intent،
والبيانات والفئة. لا يقدِّم النظام هدفًا ضمنيًا لمكوِّن تطبيقك إلا إذا
يمكن أن يمرّ intent عبر أحد فلاتر الأهداف.
ملاحظة: دائمًا ما يتمّ تحقيق النية الصريحة في الهدف المحدّد لها. بصرف النظر عن فلاتر الأهداف التي يفصح عنها المكوِّن.
يجب أن يفصح مكوّن التطبيق عن فلاتر منفصلة لكل مهمة فريدة يمكنه تنفيذها.
على سبيل المثال، قد يحتوي نشاط واحد في تطبيق معرض الصور على فلترَين: فلتر واحد.
لعرض الصورة، وفلتر آخر لتعديل الصورة. عندما يبدأ النشاط،
يفحص "Intent
" ويقرِّر كيفية التصرف بناءً على المعلومات المطلوبة
في Intent
(مثل عرض عناصر تحكُّم المحرِّر أو عدم عرضها)
يتم تعريف كل فلتر أهداف باستخدام عنصر <intent-filter>
في ملف بيان التطبيق، ويتم إدراجه في مكوّن التطبيق المقابل (مثل
عنصر <activity>
).
في كل مكون تطبيق يتضمن عنصر <intent-filter>
،
قم بتعيين قيمة
android:exported
تشير هذه السمة إلى ما إذا كان يمكن للتطبيقات الأخرى الوصول إلى مكوِّن التطبيق. في بعض
مثل الأنشطة التي تتضمن فلاتر الأهداف
LAUNCHER
الفئة، من المفيد تعيين هذه السمة على true
. وبخلاف ذلك،
من الأفضل ضبط هذه السمة على false
.
تحذير: إذا كان النشاط أو الخدمة أو android:exported
المستلِم في تطبيقك يستخدم فلاتر الأهداف ولا يضبط القيمة
لـ android:exported
بشكل صريح، لا يمكن تثبيت تطبيقك على جهاز
يعمل بنظام التشغيل Android 12 أو إصدار أحدث.
داخل <intent-filter>
،
يمكنك تحديد نوع النوايا التي تريد قبولها باستخدام واحد أو أكثر
من هذه العناصر الثلاثة:
<action>
- يُعلن عن قبول إجراء النية في السمة
name
. يجب أن تكون القيمة هي القيمة الحرفية للسلسلة للإجراء، وليس ثابت الفئة. <data>
- تعريف نوع البيانات المقبولة باستخدام سمة واحدة أو أكثر من السمات التي تحدد
المتعلقة بمعرّف الموارد المنتظم (URI) للبيانات (
scheme
، وhost
، وport
،path
) ونوع MIME. <category>
- توضيح فئة الهدف المقبولة في السمة
name
القيمة يجب أن يكون قيمة السلسلة الحرفية لأحد الإجراءات، وليس ثابت الفئة.ملاحظة: لتلقّي أغراض ضمنية، يجب إجراء ما يلي: يجب أن يتضمن الفئة
CATEGORY_DEFAULT
في فلتر الأهداف. الطرقstartActivity()
و تتعاملstartActivityForResult()
مع كل الأهداف كما لو كانوا قد أعلنوا عن الفئةCATEGORY_DEFAULT
. إذا لم تحدِّد هذه الفئة في فلتر الأهداف، لن يتم تحويل أي أهداف ضمنية إلى نشاطك.
على سبيل المثال، إليك بيان نشاط يتضمّن فلتر نية لتلقّي نية
ACTION_SEND
عندما يكون نوع البيانات نصًا:
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
يمكنك إنشاء فلتر يتضمّن أكثر من مثيل واحد من
<action>
أو
<data>
أو
<category>
.
إذا فعلت ذلك، فيجب أن تكون متأكدًا من أن المكون يمكنه التعامل مع جميع
مجموعات من عناصر التصفية هذه.
عندما تريد التعامل مع أنواع متعدّدة من النوايا، ولكن في مجموعات محدّدة فقط من نوع الإجراء والبيانات والفئة، عليك إنشاء فلاتر متعددة للنوايا.
يتم اختبار هدف ضمني مقابل فلتر من خلال مقارنة الغرض من كل نوع ثلاثة عناصر. لكي يتم إرسال النية إلى المكوّن، يجب أن تجتاز النية جميع الاختبارات الثلاثة. وفي حال تعذّر مطابقة أيٍّ منها، لن يرسل نظام Android النية إلى الادخال. ومع ذلك، بما أنّ المكوّن قد يحتوي على فلاتر متعددة للنوايا، قد يتمكّن أحد الفلاتر من السماح بمرور نية لا تَجتاز أحد فلاتر المكوّن. يمكنك الاطّلاع على مزيد من المعلومات حول كيفية حلّ النظام للنوايا في القسم أدناه المتعلق بحلّ النوايا.
تحذير: لا يُعدّ استخدام فلتر الأهداف طريقة آمنة لمنع التطبيقات الأخرى من بدء
مكوناتك. على الرغم من أنّ فلاتر ملفات Intent تحدّ من استجابة المكوّن لأنواع معيّنة فقط من ملفات Intent الضمنية، يمكن لتطبيق آخر بدء مكوّن تطبيقك باستخدام ملف Intent صريح إذا حدّد المطوّر أسماء المكوّنات.
إذا كان من المهم أن يتمكّن تطبيقك فقط من بدء أحد مكوّناتك،
يجب عدم الإفصاح عن فلاتر الأهداف في البيان. بدلاً من ذلك، اضبط سمة
exported
على "false"
لهذا المكوّن.
وبالمثل، لتجنب تشغيل تطبيق مختلف عن غير قصد
Service
، يُرجى دائمًا استخدام نية صريحة لبدء الخدمة الخاصة بك.
ملاحظة:
بالنسبة إلى جميع الأنشطة، يجب الإفصاح عن فلاتر الأهداف في ملف البيان.
ومع ذلك، يمكن تسجيل فلاتر مستلمي البث ديناميكيًا من خلال الاتصال
registerReceiver()
يمكنك بعد ذلك إلغاء تسجيل جهاز الاستقبال لدى unregisterReceiver()
. يؤدي ذلك إلى السماح لتطبيقك
للاستماع إلى رسائل بث معيّنة خلال فترة زمنية محدّدة فقط أثناء استخدام تطبيقك
قيد التشغيل.
أمثلة على الفلاتر
لتوضيح بعض سلوكيات فلاتر الأهداف، إليك مثال من ملف البيان الخاص بتطبيق مشاركة على الشبكات الاجتماعية:
<activity android:name="MainActivity" android:exported="true"> <!-- This activity is the main entry, should appear in app launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ShareActivity" android:exported="false"> <!-- This activity handles "SEND" actions with text data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/vnd.google.panorama360+jpg"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity>
النشاط الأول، MainActivity
، هو نقطة الدخول الرئيسية للتطبيق - النشاط الذي
عندما يشغِّل المستخدم التطبيق للمرة الأولى باستخدام رمز مشغّل التطبيقات:
- الإجراء
ACTION_MAIN
تشير إلى أن هذه هي نقطة الدخول الرئيسية ولا تتوقع أي بيانات نية. - تشير فئة
CATEGORY_LAUNCHER
إلى أنّه يجب وضع رمز هذا النشاط في مشغّل تطبيقات النظام. إذا لم يحدّد عنصر<activity>
رمزًا باستخدامicon
، سيستخدم النظام الرمز من عنصر<application>
.
يجب إقران هذين العنصرَين معًا لكي يظهر النشاط في مشغّل التطبيقات.
يهدف النشاط الثاني، ShareActivity
، إلى تسهيل مشاركة المحتوى النصي ومحتوى الوسائط
. رغم أنّ المستخدمين قد يدخلون هذا النشاط من خلال الانتقال إليه من MainActivity
،
يمكنه أيضًا الدخول إلى ShareActivity
مباشرةً من تطبيق آخر يصدر رسالة إلكترونية
أهداف تتطابق مع أحد فلترَي الأهداف.
ملاحظة: نوع MIME،
application/vnd.google.panorama360+jpg
، هو نوع بيانات خاص يحدّد
الصور البانورامية، والتي يمكنك التعامل معها باستخدام واجهات برمجة تطبيقات Google
panorama.
مطابقة الأهداف مع التطبيقات الأخرى فلاتر الأهداف
إذا كان تطبيق آخر يستهدف Android 13 (المستوى 33 لواجهة برمجة التطبيقات) أو إصدارًا أحدث، يمكنه التعامل مع
الغرض من التطبيق فقط إذا تطابق هدفك مع إجراءات وفئات
العنصر <intent-filter>
في ذلك التطبيق الآخر. وإذا لم يعثر النظام على
تطابق، تطرح
ActivityNotFoundException
يجب أن يعالج التطبيق المُرسِل
هذا الاستثناء.
وبالمثل، عند تحديث تطبيقك بحيث يستهدف Android 13
أو أعلى، يتم تسليم جميع الأهداف الناشئة من تطبيقات خارجية إلى
الذي تم تصديره من تطبيقك فقط إذا تطابق هذا الغرض مع الإجراءات
فئات عنصر <intent-filter>
التي يفصح عنها تطبيقك. ويحدث هذا السلوك
بغض النظر عن إصدار حزمة SDK المستهدَف للتطبيق المُرسِل.
في الحالات التالية، لا يتم فرض مطابقة الأهداف:
- الأهداف التي يتم إرسالها إلى المكوّنات التي لا تشير إلى أي فلاتر أهداف.
- الأهداف التي تنشأ من داخل التطبيق نفسه
- النوايا التي تأتي من النظام، أي النوايا التي يتم إرسالها من
"معرّف مستخدم النظام" (uid=1000). تتضمن تطبيقات النظام
system_server
والتطبيقات التي يتم ضبط إعداداتها منandroid:sharedUserId
إلىandroid.uid.system
. - النوايا التي تنشأ من الجذر.
اطّلِع على مزيد من المعلومات عن مطابقة الرغبة في الشراء.
استخدام طلب في انتظار المراجعة
الكائن PendingIntent
هو التفاف حول كائن Intent
. الغرض الأساسي من PendingIntent
هو منح إذن لتطبيق أجنبي
باستخدام Intent
المضمّنة كما لو تم تنفيذها من عملية
تطبيقك الخاصة.
تشمل حالات الاستخدام الرئيسية لهدف في انتظار المراجعة ما يلي:
- الإعلان عن نية للتنفيذ عندما يتّخذ المستخدم إجراءً من خلال الإشعار
(
NotificationManager
الخاص بنظام Android لتنفيذIntent
). - تحديد نية لتنفيذها عندما ينفِّذ المستخدم إجراءً باستخدام
أداة التطبيق
(ينفِّذ تطبيق الشاشة الرئيسية
Intent
). - الإعلان عن نية تنفيذ في وقت مستقبلي محدّد (ينفّذ
AlarmManager
في نظام AndroidIntent
).
وتمامًا كما تم تصميم كل عنصر من عناصر Intent
للتعامل معه من خلال مجموعة محدّدة من العناصر
نوع مكوِّن التطبيق (إما Activity
أو Service
أو
BroadcastReceiver
)، لذا يجب أيضًا أن يكون PendingIntent
أنشأناها بنفس الاعتبارات. وعند استخدام هدف في انتظار المراجعة، لا
يمكن تنفيذ الغرض باستخدام طلب مثل startActivity()
. وبدلاً من ذلك، يجب تعريف نوع المكوِّن المقصود عند إنشاء
PendingIntent
من خلال استدعاء طريقة صانع المحتوى المعني:
PendingIntent.getActivity()
مقابلIntent
يبدأActivity
.PendingIntent.getService()
مقابلIntent
يبدأService
.PendingIntent.getBroadcast()
لمحاولةIntent
لبدءBroadcastReceiver
ما لم يكن تطبيقك يتلقّى الأهداف المعلّقة من تطبيقات أخرى
من المحتمل أن تكون الطرق أعلاه لإنشاء PendingIntent
هي الوحيدة
ستحتاج إلى PendingIntent
طريقة.
تأخذ كل طريقة التطبيق الحالي Context
،
علامة Intent
التي تريد التفافها، وعلامة واحدة أو أكثر تحدد
طريقة استخدام الغرض (مثلاً، تحديد ما إذا كان بالإمكان استخدام الغرض أكثر من مرة)
لمزيد من المعلومات عن استخدام الأهداف التي في انتظار المراجعة، اطّلِع على المستندات لكلّ من حالات الاستخدام المعنية، كما هو الحال في الإشعارات والتطبيقات المصغّرة للتطبيقات.
تحديد قابلية التغيّر
إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث، يجب تحديد
قابلية التغيّر لكل عنصر من عناصر PendingIntent
التي ينشئها تطبيقك. للإقرار بأنّ
كائن PendingIntent
محدد قابل للتغيير أو غير قابل للتغيير، استخدم
PendingIntent.FLAG_MUTABLE
أو
PendingIntent.FLAG_IMMUTABLE
على التوالي.
إذا حاول تطبيقك إنشاء عنصر PendingIntent
بدون تعيين أيٍ من علامات قابلية التغيّر، يعرض النظام
IllegalArgumentException
،
ستظهر الرسالة التالية في Logcat:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
أنشئ نوايا غير قابلة للتغيير في انتظار المراجعة كلما أمكن ذلك.
في معظم الحالات، يجب أن ينشئ تطبيقك عناصر PendingIntent
غير قابلة للتغيير، على النحو التالي:
كما هو موضح في مقتطف الرمز التالي. إذا كان الكائن PendingIntent
غير قابل للتغيير،
فلا يمكن للتطبيقات الأخرى تعديل نية تعديل نتيجة استدعاء الإجراء
والنية.
val pendingIntent = PendingIntent.getActivity(applicationContext,REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
ومع ذلك، تتطلّب بعض حالات الاستخدام عناصر PendingIntent
قابلة للتغيّر بدلاً من ذلك:
- إتاحة إجراءات الرد المباشر في
الإشعارات تشير رسالة الأشكال البيانية
يجب إدخال تغيير على بيانات المقطع في الكائن PendingIntent
المرتبط بالرد. وعادةً ما تطلب هذا التغيير من خلال تمرير
FILL_IN_CLIP_DATA
كعلامة إلى الأسلوبfillIn()
. - ربط الإشعارات بإطار عمل Android Auto باستخدام مثيلات
CarAppExtender
- وضع المحادثات في فقاعات باستخدام مثيلات
PendingIntent
يسمح كائنPendingIntent
قابل للتغيير للنظام بتطبيق العلامات الصحيحة، مثلFLAG_ACTIVITY_MULTIPLE_TASK
وFLAG_ACTIVITY_NEW_DOCUMENT
. - يتم طلب معلومات الموقع الجغرافي للجهاز من خلال الاتصال
requestLocationUpdates()
أو واجهات برمجة تطبيقات مشابهة يسمح العنصر القابل للتغييرPendingIntent
للنظام بإضافة إضافات الطلبات التي تمثّل أحداث دورة حياة الموقع الجغرافي. وتشمل هذه الأحداث تغييرًا في الموقع الجغرافي وظهور مقدّم خدمة. - جدولة المنبّهات باستخدام
AlarmManager
. يسمح كائنPendingIntent
القابل للتغيير للنظام بإضافة السمةEXTRA_ALARM_COUNT
النية الإضافية. يمثّل هذا المقياس الإضافي عدد المرات التي تم فيها تشغيل المنبّه المتكرّر. من خلال تضمين هذه المعلومات الإضافية، يمكن لهدف الغرض إبلاغه بدقة أحد التطبيقات لمعرفة ما إذا كان قد تم تشغيل منبّه متكرر عدة مرات، مثل عندما كان الجهاز في وضع السكون.
إذا أنشأ تطبيقك عنصر PendingIntent
قابل للتغيّر، ننصحك بشدة باستخدام
استخدام هدف صريح وملء
ComponentName
بهذه الطريقة، كلما شغّل تطبيق آخر PendingIntent
ونقل التحكّم مرة أخرى إلى تطبيقك، يبدأ المكوّن نفسه في تطبيقك دائمًا.
استخدام النوايا الصريحة ضمن النوايا التي في انتظار المراجعة
لتحديد الطريقة التي يمكن بها للتطبيقات الأخرى استخدام الأهداف التي في انتظار المراجعة في تطبيقك، يُرجى دائمًا إحاطة هدف في انتظار المراجعة بنيّة صريحة للمساعدة في اتّباع أفضل الممارسات هذه، اتّبِع الخطوات التالية:
- تحقَّق من أنّ حقول الإجراء والحزمة والمكوِّن خاصة بالهدف الأساسي تحديدها.
-
استخدِم
FLAG_IMMUTABLE
، الذي تمت إضافته في الإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات)، لإنشاء نوايا في انتظار المراجعة. تمنع هذه العلامة التطبيقات التي تتلقّىPendingIntent
من ملء الخصائص الفارغة. إذا كانminSdkVersion
لتطبيقك:22
أو أقل، يمكنك توفير الأمان والتوافق معًا باستخدام التعليمة البرمجية التالية:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
دقة النية بالشراء
عندما يتلقّى النظام نية ضمنية لبدء نشاط، يبحث عن أفضل نشاط للنية من خلال مقارنته بفلاتر النيّات استنادًا إلى ثلاثة جوانب:
- الحركة.
- البيانات (معرّف URI ونوع البيانات)
- الفئة.
توضّح الأقسام التالية كيفية مطابقة الأهداف مع المكوّنات المناسبة، وذلك تبعًا لبيان فلتر الأهداف في ملف بيان التطبيق.
اختبار الإجراء
لتحديد إجراءات النية المقبولة، يمكن لفلتر الأهداف الإعلان عن صفر أو أكثر
<action>
، كما هو موضّح في المثال التالي:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
لاجتياز هذا الفلتر، يكون الإجراء المحدّد في Intent
يجب أن يتطابق مع أحد الإجراءات المدرَجة في الفلتر.
إذا لم يدرج عامل التصفية أي إجراءات، فلا يوجد شيء
ونية المطابقة، لذلك تفشل جميع الأهداف في الاختبار. ومع ذلك، إذا لم يحدِّد Intent
إجراءً، يجتاز الاختبار ما دام الفلتر
يحتوي على إجراء واحد على الأقل.
اختبار الفئة
لتحديد فئات الأهداف المقبولة، يمكن أن يعلن فلتر الأهداف عن صفر أو أكثر من عناصر
<category>
، كما هو موضّح في المثال التالي:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
لاجتياز اختبار الفئة، يجب أن تتطابق كل فئة في Intent
مع فئة في الفلتر. العكس ليس ضروريًا، إذ قد يعمل فلتر الأهداف
الإعلان عن فئات أكثر من الفئات المحدّدة في Intent
لا يزال هناك Intent
بطاقات محفوظة. وبالتالي، يجتاز الإجراء الذي لا يتضمّن أي فئات
هذا الاختبار دائمًا، بغض النظر عن الفئات التي تمّ الإعلان عنها في الفلتر.
ملاحظة:
يطبّق Android تلقائيًا فئة CATEGORY_DEFAULT
على جميع النوايا الضمنية التي يتم تمريرها إلى startActivity()
وstartActivityForResult()
.
إذا كنت تريد أن يتلقّى نشاطك أهدافًا ضمنية، يجب أن يحتوي على فئة "android.intent.category.DEFAULT"
في فلاتر الأهداف، كما هو موضّح في مثال <intent-filter>
السابق.
اختبار البيانات
لتحديد بيانات الأهداف المقبولة، يمكن أن يذكر فلتر الأهداف صفرًا أو أكثر
<data>
، كما هو موضّح في المثال التالي:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
كل <data>
تحديد عنوان URI ونوع البيانات (نوع وسائط MIME).
يُعد كل جزء من معرف الموارد المنتظم (URI) منفصلاً
السمة: scheme
، host
، port
،
وpath
:
<scheme>://<host>:<port>/<path>
يوضّح المثال التالي القيم المحتملة لهذه السمات:
content://com.example.project:200/folder/subfolder/etc
في عنوان URI هذا، المخطط هو content
، والمضيف هو com.example.project
،
المنفذ هو 200
والمسار هو folder/subfolder/etc
.
كلّ من هذه السمات اختيارية في عنصر <data>
،
ولكن هناك تبعيات خطية:
- في حال عدم تحديد مخطط، يتم تجاهل المضيف.
- في حال عدم تحديد مضيف، يتم تجاهل المنفذ.
- في حال عدم تحديد كل من المخطط والمضيف، سيتم تجاهل المسار.
عند مقارنة معرّف الموارد المنتظم في طلب بحث مع مواصفات معرّف الموارد المنتظم في فلتر، تتم المقارنة فقط مع أجزاء معرّف الموارد المنتظم المضمّنة في الفلتر. مثلاً:
- إذا حدّد أحد الفلاتر مخططًا فقط، تتطابق جميع معرّفات الموارد المنتظمة (URI) التي تتضمّن هذا المخطط عامل التصفية.
- إذا كان هناك فلتر يحدد مخططًا ومرجعًا ولكن بدون مسار، سيتم استخدام جميع معرفات الموارد المنتظمة (URI) باستخدام نفس المخطط والسلطة يجتازوا عامل التصفية، بغض النظر عن مساراتهم.
- إذا حدّد الفلتر مخطّطًا وهيئة ومسارًا، لن تمرّ سوى عناوين URL التي تتضمّن المخطّط والهيئة والمسار نفسه.
ملاحظة: يمكن أن يحدد مواصفات المسار أن يحتوي على علامة نجمية حرف بدل (*) لطلب تطابق جزئي فقط لاسم المسار.
يقارن اختبار البيانات كلاً من معرّف الموارد المنتظم (URI) ونوع MIME في الطلب مع معرّف موارد منتظم ونوع MIME محدّدَين في الفلتر. في ما يلي القواعد:
- ينفي الغرض الذي لا يحتوي على معرّف موارد منتظم (URI) أو نوع MIME لاختباره فقط إذا لم يحدد الفلتر أي معرّفات موارد منتظمة (URI) أو أنواع MIME.
- غرض يحتوي على معرّف موارد منتظم (URI) ولكن بدون نوع MIME (ليس صريحًا ولا يمكن استنتاجه من URI) يجتاز الاختبار فقط إذا كان عنوان URI يتوافق مع تنسيق معرّف الموارد المنتظم (URI) للفلتر وبالمثل، لا يحدد الفلتر نوع MIME.
- يجتاز الغرض الذي يحتوي على نوع MIME ولكن ليس معرّف موارد منتظم (URI) الاختبار فقط إذا كان الفلتر يعرض نوع MIME نفسه ولا يحدد تنسيق معرّف موارد منتظم (URI).
- عبارة عن هدف يحتوي على كل من معرّف الموارد المنتظم (URI) ونوع MIME (سواء كان صريحًا أو يمكن استنتاجه من
URI) يجتاز الجزء من نوع MIME من الاختبار فقط إذا كان ذلك
النوع يتطابق مع النوع المدرج في الفلتر. يجتاز الاختبار جزء معرّف الموارد المنتظم (URI)
إما إذا كان معرّف الموارد المنتظم يتطابق مع معرّف موارد منتظم في الفلتر أو إذا كان يحتوي على معرّف موارد منتظم
content:
أوfile:
ولم يحدّد الفلتر معرّف موارد منتظمًا. بعبارة أخرى، يُفترض أنّ المكوّن متوافق مع بياناتcontent:
وfile:
إذا كانت قائمة الفلتر تتضمّن نوع MIME فقط.
ملاحظة: إذا حدّد الغرض من نوع معرّف الموارد المنتظم (URI) أو نوع MIME، فسيحدّد اختبار البيانات
وسيتعذّر تنفيذ الإجراء إذا لم تتوفّر عناصر <data>
في <intent-filter>
.
تعكس هذه القاعدة الأخيرة، القاعدة (د)، التوقع
أن المكونات قادرة على الحصول على بيانات محلية من موفر ملف أو محتوى.
وبالتالي، يمكن أن تسرد الفلاتر نوع بيانات فقط ولا تحتاج إلى إدراجها بشكل صريح
لتسمية المخططَين content:
وfile:
.
يعرض المثال التالي حالة نموذجية يُعلم فيها عنصر <data>
نظام التشغيل Android بأنّ المكوّن يمكنه الحصول على بيانات الصورة من مقدّم محتوى وعرضه:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
الفلاتر التي نوع البيانات ولكن ليس عنوان URI هي الأكثر شيوعًا لأن معظمها يقوم مزودو المحتوى بتوزيع البيانات.
هناك تكوين شائع آخر وهو عامل تصفية بمخطط ونوع بيانات. بالنسبة
مثال: <data>
مثل ما يلي يخبر Android أنه
يمكن للمكوِّن استرداد بيانات الفيديو من الشبكة لتنفيذ الإجراء:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
مطابقة النية
تتم مطابقة النوايا مع فلاتر النوايا ليس فقط لاكتشاف المكوّن المستهدف
لتفعيله، ولكن أيضًا لاكتشاف معلومات عن مجموعة
المكوّنات على الجهاز. على سبيل المثال، يملأ تطبيق Home مشغّل التطبيقات.
من خلال العثور على جميع الأنشطة باستخدام فلاتر الأهداف التي تحدّد
إجراء ACTION_MAIN
الفئة CATEGORY_LAUNCHER
.
لا تنجح المطابقة إلا إذا كانت الإجراءات والفئات في "الهدف" متطابقة
مع الفلتر، كما هو موضّح في مستندات فئة IntentFilter
.
يمكن لتطبيقك استخدام ميزة مطابقة النوايا بطريقة مشابهة لتلك التي يستخدمها تطبيق Home.
يتضمّن PackageManager
مجموعة من query...()
.
الطرق التي تُرجع جميع المكونات التي يمكن أن تقبل غرضًا معينًا
سلسلة مماثلة من طرق resolve...()
التي تحدد أفضل
للاستجابة لهدف ما. على سبيل المثال، تعرِض queryIntentActivities()
قائمة بجميع الأنشطة التي يمكنها تنفيذ القصْد الذي تم تمريره كوسيطة، وتعرِض queryIntentServices()
قائمة مشابهة بالخدمات.
لا تعمل أي من الطريقتين على تنشيط المكونات؛ فإنهم فقط يسردون تلك التي
الاستجابة. هناك طريقة مشابهة،
queryBroadcastReceivers()
، لمستلمي البث.