الأغراض ومرشحات الغرض

الإعلانات

 الأغراض ومرشحات الغرض

 

 

 

 الأغراض ومرشحات الغرض

الغرض هو كائن مراسلة، يمكنك إستخدامه لطلب إجراء من مكون تطبيق آخر. و على الرغم

من أن الأغراض تسهل الإتصال بين المكونات بعدة طرق، فهناك ثلاث حالات إستخدام أساسية لها: الأغراض ومرشحات الغرض

  • بدء نشاط

يمثل النشاط شاشة واحدة في التطبيق. يمكنك بدء نسخة جديدة من النشاط بتمرير غرض لـ ()startActivity..

الغرض يصف النشاط، لبدء وتحميل أي بيانات ضرورية.

إذا كنت ترغب في تلقي نتيجة من النشاط، عند إنتهاؤه، قم بإستدعاء ()startActivityForResult.

يتلقى نشاطك النتيجة، ككائن غرض مستقل، في دالة الإستدعاء ()onActivityResult الخاصة بنشاطك. لمزيد من المعلومات، راجع دليل الأنشطة.

 

 

  • بدء خدمه

الخدمة هي مكون يقوم بتنفيذ عمليات في الخلفيه، بدون واجهة مستخدم. في أندرويد 5.0 (المستوى 21) و أحدث، يمكنك بدء خدمة بإستخدام JobScheduler.

لمزيد من المعلومات حول JobScheduler، اقرأ الوثائق المرجعية لواجهة برمجة التطبيقات الخاصة به.

للإصدارات الأقدم من أندرويد 5.0 (المستوى 21)، يمكنك بدء خدمة بإستخدام دوال فئة الخدمه.

يمكنك بدء خدمة لتنفيذ عملية لمرة واحدة (مثل تحميل ملف)، من خلال تمرير غرض إلى ()startService.

الغرض يصف الخدمه لبدء وحمل أي بيانات ضرورية.

إذا كانت الخدمة مصممة بإستخدام واجهة سيرفر العميل، يمكنك الربط بالخدمة من مكون آخر، من خلال تمرير غرض إلى ()bindService.

لمزيد من المعلومات، راجع دليل الخدمات.

 

  • توصيل البث

البث عبارة عن رسالة، يمكن أن يتلقاها أي تطبيق. يقوم النظام بإيصال بثوث مختلفة لأحداث النظام، مثل: عندما يقوم النظام بالإقلاع أو عند بدء شحن الجهاز.

يمكن إيصال البث إلى تطبيق آخر، من خلال تمرير غرض إلى ()sendBroadcast أو ()sendOrderedBroadcast.

بقية هذه الصفحه تشرح طريقة عمل الأغراض، و طريقة إستخدامهم. للحصول على معلومات ذات صله، راجع التفاعل مع التطبيقات الأخرى و مشاركة المحتوى.

 

 

 

 

أنواع الأغراض


هناك نوعان من الأغراض:

  • الأغراض الصريحه تحدد التطبيق الذي يلبي متطلبات الغرض، إما من خلال تقديم، اسم حزمة التطبيق المستهدف، أو اسم فئة المكون المؤهل بالكامل.

عادة سوف تستخدم الغرض الصريح لبدء مكون في تطبيقك، لأنك تعرف اسم فئة النشاط أو خدمة ترغب في بدئها.

مثال، قد تبدأ نشاطاً جديداً بداخل تطبيقك رداً على تفاعل المستخدم، أو تبدأ خدمة لتحميل ملف في الخلفيه.

 

 

  • الأغراض الضمنيه لا تحدد مكوناً بعينه، ولكن بدلاً من ذلك تقوم بإعلان إجراء عام لتنفيذه، مما يسمح لمكون من تطبيق آخر بالتعامل معه.

مثال، إذا أردت عرض موقع للمستخدم على الخريطه، يمكنك إستخدام غرض ضمني للطلب من ذلك التطبيق الآخر القادر على عرض الخرائط، أن يقوم بعرض موقع معين على الخريطه.

 

 

يوضح الشكل 1 كيفية إستخدام غرض، عند بدء نشاط ما.

عندما يقوم كائن Intent بتسمية “تحديد” مكون نشاط معين، بشكلٍ صريح، يقوم النظام بتشغيل هذا المكون على الفور.


عندما تستخدم غرض ضمني، يعثر نظام الأندرويد عن المكون المناسب لبدأه..

 

 

الشكل 1. كيف يتم تسليم غرض ضمني من خلال النظام لبدء نشاط آخر: 1- النشاط أ ينشئ غرض مع وصف إجراء، ويمرره إلى

startActivity() – 2 يبحث نظام الاندرويد في جميع التطبيقات، عن مرشح غرض مطابق للغرض.

عند العثور على غرض مطابق، [3] يبدأ النظام النشاط المطابق (النشاط ب) عن طريق إستدعاء دالة ()onCreate وتمرير الغرض.

 

 

من خلال مقارنة محتويات الغرض بمرشحات الغرض المعلنه في ملفات إيضاح التطبيقات الأخرى على الجهاز.

 

إذا تطابق الغرض مع مرشح غرض، يقوم النظام ببدء ذلك المكون و يسلمه إلى كائن الغرض.

إذا تطابقت عدة مرشحات غرض، يقوم النظام بعرض مربع حوار لكي يقوم المستخدم بإختيار تطبيق لإستخدامه.

مرشح الغرض عبارة عن تعبير في ملف إيضاح التطبيق، والذي يحدد أنواع الأغراض التي يرغب المكون في تلقيها.

مثال، من خلال الإعلان عن مرشح غرض لنشاطٍ ما، فأنت تجعل من السهل على التطبيقات الأخرى..

أن تبدأ نشاطك مباشرة، بواسطة نوع معين من الأغراض.

وبالمثل، إذا لم تقم بالإعلان عن أي مرشحات غرض لنشاطٍ ما، فلن يمكن تشغيله إلا بواسطة غرض صريح.

تحذير: للتأكد من أمان تطبيقك، إستخدم دائماً غرضاً صريحاً عند بدء الخدمة، ولا تعلن عن مرشحات غرض لخدماتك.

يعتبر إستخدام غرض ضمني لبدء الخدمة، خطراً أمنياً، لأنك لا تستطيع التأكد من الخدمة التي ستستجيب للغرض، ولا يستطيع المستخدم رؤية الخدمة التي بدأت.

بدءاً من أندريد 5.0 (المستوى 21)، يطرح النظام إستثناءً إذا قمت بإستدعاء ()bindService مع غرض ضمني.

 

 

 

 

تصميم الأغراض


يحتوي كائن الغرض Intent على معلومات يستخدمها نظام الأندرويد، لتحديد أي مكون يبدأ تشغيله..

(مثل اسم المكون أو صنف المكون الذي يجب أن يتلقى الغرض)، بالإضافة إلى المعلومات التي يستخدمها المكون المستلم..

لتنفيذ الإجراء بشكلٍ صحيح (مثل الإجراء الواجب إتخاذه والبيانات التي سوف يتم العمل بناءً عليها).

المعلومات الأساسية الواردة في الغرض هي ما يلي:

 

اسم المكون

اسم المكون للبدء.

هذا أمر إختياري، ولكنه يمثل جزءاً هاماً من المعلومات التي تجعل الغرض صريحاً، بمعنى أنه يجب تسليم الغرض فقط، إلى مكون التطبيق المحدد بواسطة اسم المكون.

بدون اسم مكون ، يكون الغرض ضمني، وعندها يقرر النظام المكون الذي يجب أن يتلقى الغرض إستناداً إلى معلومات الغرض الأخرى..

(مثل الإجراء، البيانات، التصنيف – الموضحة أدناه). إذا كنت بحاجة إلى بدء مكون معين، في تطبيقك، فعليك تحديد اسم المكون.

ملاحظة: عند بدء الخدمة، حدد دائماً اسم المكون. بخلاف ذلك، لا يمكنك التأكد من الخدمة التي ستستجيب للغرض، ولا يمكن للمستخدم معرفة الخدمة التي بدأت.

 

هذا الحقل من الغرض Intent عبارة عن كائن ComponentName، والذي يمكنك تحديده بإستخدام اسم فئة مؤهل بالكامل، للمكون المستهدف..

بما في ذلك أسم حزمة التطبيق، على سبيل المثال، com.example.ExampleActivity. يمكنك تعيين اسم المكون بإستخدام…

()setComponent أو ()setClass أو ()setClassName أو بإستخدام منشئ الغرض Intent.

 

 

 

إجراء

سلسلة تحدد الإجراء العام المراد تنفيذه (مثل العرض أو الإختيار).

في حالة غرض البث، هذا هو الإجراء الذي حدث ويتم الإبلاغ عنه. يحدد الإجراء إلى حدٍ كبير كيفية إنشاء بقية الغرض – خاصة المعلومات الموجودة في البيانات والإضافات.

يمكنك تحديد إجراءاتك الخاصة، لإستخدامها بواسطة الأغراض بداخل تطبيقك (أو لإستخدامها من قبل التطبيقات الأخرى، لإستدعاء المكونات في تطبيقك)..

ولكنك عادةً ما تحدد ثوابت الإجراء، المحددة بواسطة فئة الغرض Intent أو فئات إطار العمل الأخرى.

في ما يلي بعض الإجراءات الشائعة لبدء أحد الأنشطة:

ACTION_VIEW

إستخدم هذا الإجراء، في غرض ما بإستخدام ()startActivity ، عندما يكون لديك بعض المعلومات، التي يمكن أن يظهرها النشاط للمستخدم..

مثل صورة لعرضها في تطبيق الأستوديو، أو عنوان لعرضه في تطبيق الخريطة.

ACTION_SEND

يُعرف أيضاً بأسم الغرض المشترك، ويجب عليك إستخدام هذا في غرض ما بإستخدام ()startActivity ..

عندما يكون لديك بعض البيانات، التي يمكن للمستخدم مشاركتها من خلال تطبيق آخر، مثل تطبيق البريد الإلكتروني أو تطبيق المشاركة الإجتماعية.

راجع مرجع فئة الغرض Intent لمزيد من الثوابت، التي تقوم بتعريف الإجراءات العامة.

يتم تحديد إجراءات أخرى، في مكان آخر في إطار عمل الأندرويد، كما هو الحال في إعدادات الإجراءات..

التي تفتح شاشات معينة في تطبيق إعدادات النظام.

يمكنك تحديد إجراء للغرض، بإستخدام ()setAction أو بإستخدام منشئ الغرض intent.

إذا حددت إجراءاتك الخاصة، فتأكد من تضمين اسم حزمة التطبيق كبادئة، كما هو موضح في المثال التالي:

KOTLIN

const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"

JAVA

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";

 

 

 

البيانات

عنوان URI (كائن Uri) الذي يشير إلى البيانات المطلوب التصرف بها و/أو نوع MIME لتلك البيانات.

يتم إملاء نوع البيانات التي تم توفيرها، بشكلٍ عام بواسطة إجراء الغرض. مثال، إذا كان الإجراء ACTION_EDIT، يجب أن تحتوي البيانات على URI الخاص بالمستند، لتحريره.

عند إنشاء غرض، يكون من المهم في كثير من الأحيان، تحديد نوع البيانات (نوع MIME الخاص بها) بالإضافة إلى عنوان URI الخاص بها.

مثال، لن يتمكن أحد الأنشطة التي يمكنها عرض الصور، من تشغيل ملف صوتي، على الرغم من أن صيغ URI قد تكون متشابهة.

تحديد نوع بيانات MIME، يساعد من نظام الأندرويد في العثور على أفضل مكون، لتلقي غرضك.

ومع ذلك، يمكن في بعض الأحيان إستنتاج نوع MIME من عنوان URI – لا سيما عندما تكون البيانات عبارة عن محتوى:

URI. هو محتوى: يشير URI إلى أن البيانات موجودة على الجهاز، ويتم التحكم فيها بواسطة ContentProvider، مما يجعل نوع بيانات MIME مرئياً للنظام.

لتعيين URI الخاص بالبيانات فقط، قم بإستدعاء ()setData . لتعيين نوع MIME فقط، قم بإستدعاء ()setType .

إذا لزم الأمر، يمكنك تعيين كليهما صراحة بإستخدام ()setDataAndType .

 

تنبيه: إذا كنت ترغب في تعيين كلٍ من نوع URI و MIME ، فلا تقم بإستدعاء ()setData و ()setType لأن كلٍ منهما يبطل قيمة الآخر. إستخدم دوماً ()setDataAndType لتعيين كلٍ من نوع URI و MIME.

 

الصنف

سلسلة تحتوي على معلومات إضافية، حول نوع المكون الذي يجب أن يتعامل مع الغرض. يمكن وضع أي عدد من أوصاف التصنيفات category في الغرض..

ولكن معظم الأغراض لا تتطلب تصنيف. فيما يلي بعض التصنيفات الشائعة:

CATEGORY_BROWSABLE

النشاط المستهدف يسمح ببدء نفسه بواسطة متصفح ويب، لعرض البيانات المشار إليها بواسطة الرابط، مثل صورة أو رسالة بريد إلكتروني.

CATEGORY_LAUNCHER

النشاط عبارة عن نشاط أولي للمهمة، ويتم إدراجه في مشغل تطبيقات النظام.
راجع وصف فئة الغرض Intent للحصول على قائمة كاملة بالتصنيفات.

يمكنك تحديد تصنيف بإستخدام ()addCategory.

 

تمثل الخصائص المذكورة أعلاه (اسم المكون، الإجراء، البيانات، والتصنيف) الخصائص المميزة للأغراض.

من خلال قراءة هذه الخصائص، يستطيع نظام الأندرويد أن يقرر، أي مكون تطبيق، يجب أن يبدأ تشغيله.

ومع ذلك، يمكن أن يحمل الغرض معلومات إضافية، لا تؤثر في كيفية حلها إلى “التعامل معها بواسطة” أحد مكونات التطبيق.

 

 

يمكن للغرض أيضاً توفير المعلومات التالية:

الإضافات

أزواج قيمه\مفتاح، التي تحمل معلومات إضافية، مطلوبة لإنجاز الإجراء المطلوب.

تماماً مثلما تستخدم بعض الإجراءات، أنواعاً معينة من معرفات URI، فإن بعض الإجراءات تستخدم أيضاً إضافات معينة.

يمكنك إضافة بيانات إضافية بإستخدام دوال ()putExtra المختلفة، كلٍ منها يقبل معاملين “معطيين”: اسم المفتاح والقيمة.

يمكنك أيضاً إنشاء كائن حزمه Bundle مع كافة البيانات الإضافية، ومن ثم إدراج الحزمة في الغرض بإستخدام ()putExtras.

على سبيل المثال، عند إنشاء غرض، لإرسال بريد إلكتروني بإستخدام ACTION_SEND، يمكنك تحديد المرسل إليه..

بواسطة المفتاح EXTRA_EMAIL، وتحديد الموضوع بإستخدام المفتاح EXTRA_SUBJECT.

تحدد فئة الغرض Intent العديد من ثوابت *_EXTRA لأنواع البيانات القياسية.

إذا كنت بحاجة إلى الإعلان عن مفاتيحك الإضافية ( للأغراض التي يتلقاها تطبيقك)، فتأكد من تضمين اسم حزمة التطبيق كبادئة، كما هو موضح في المثال التالي:

KOTLIN
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
JAVA
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";

 

تحذير: لا تستخدم البيانات القابلة للتسلسل من النوعين Parcelable أو Serializable عند إرسال غرض، تتوقع أن يتلقاه تطبيق آخر.

إذا حاول أحد التطبيقات الوصول إلى البيانات في كائن الحزمة ولكن ليس لديه حق الوصول إلى فئة parceled أو serialized..

يقوم النظام بزيادة “إستثناء وقت التشغيل” RuntimeException.

 

 

 

 

الأعلام

يتم تعريف الأعلام في فئة الغرض Intent، التي تعمل كبيانات وصفية للغرض.

قد تقوم الأعلام بتوجيه نظام الأندرويد إلى كيفية إطلاق النشاط (مثال، المهمة التي يجب أن ينتمي إليها النشاط)..

وكيفية التعامل معه بعد إطلاقه (مثال، ما إذا كان ينتمي إلى قائمة الأنشطة الأخيرة أم لا).

لمزيد من المعلومات، راجع دالة ()setFlags.

 

 

 

 

 

مثال على غرض صريح

الغرض الصريح هو الغرض الذي تستخدمه لتشغيل مكون تطبيق معين، مثل نشاط أو خدمة معينة في تطبيقك.

لإنشاء غرض صريح، قم بتعريف اسم المكون لكائن الغرض Intent– تكون جميع خصائص الغرض الأخرى إختيارية.

مثال، إذا كنت قد أنشأت خدمة في تطبيقك، تُسمى DownloadService، وتم تصميمها لتنزيل ملف من الويب، فيمكنك البدء بإستخدام الكود التالي:

KOTLIN

// Executed in an Activity, so 'this' is the Context
// 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)

JAVA

// Executed in an Activity, so 'this' is the Context
// 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 سياق التطبيق و مكون كائن الفئه Class.

على هذا النحو، هذا الغرض يبدأ صراحة فئة DownloadService في التطبيق.

لمزيد من المعلومات حول إنشاء وتشغيل خدمة، راجع دليل الخدمات.

 

 

 

مثال على غرض ضمني

يحدد الغرض الضمني إجراءً يمكنه إستدعاء، أي تطبيق على الجهاز قادر على تنفيذ الإجراء.

يُعد إستخدام الغرض الضمني أمراً مفيداً عندما يتعذر على تطبيقك تنفيذ الإجراء، ولكن التطبيقات الأخرى على الأرجح يمكنها تنفيذ الإجراء..

وقد ترغب في أن يختار المستخدم التطبيق الذي يريد إستخدامه.

مثال، إذا كان لديك محتوى تريد أن يشاركه المستخدم مع أشخاص آخرين، فقم بإنشاء غرض بإستخدام الإجراء ACTION_SEND ..

ثم قم بإضافة إضافات تحدد المحتوى المطلوب مشاركته. عند إستدعاء ()startActivity بإستخدام هذا الغرض..

يمكن للمستخدم إختيار أحد التطبيقات الذي يمكن من خلاله مشاركة المحتوى.

 

تحذير: من المحتمل ألا يكون لدى المستخدم أي تطبيقات يمكنها التعامل مع الغرض الضمني الذي ترسله لـ ()startActivity .

أو قد يتعذر الوصول إلى التطبيق بسبب قيود أو إعدادات الملف الشخصي التي وضعها المدير. إذا حدث ذلك، فسوف يفشل الإستدعاء ويتعطل تطبيقك.

للتحقق من أن نشاطاً ما سيتلقى الغرض، قم بإستدعاء ()resolveActivity على كائن الغرض Intent.

إذا كانت النتيجة غير خالية، فهناك تطبيقٍ واحد على الأقل يمكنه التعامل مع الغرض ومن الآمن إستدعاء ()startActivity .

إذا كانت النتيجة خالية، فلا تستخدم الغرض، وإذا أمكن، يجب عليك تعطيل الميزة التي تنشر الغرض. يوضح المثال التالي كيفية التحقق من أن الغرض يصل إلى نشاط.

لا يستخدم هذا المثال URI، ولكن يتم الإعلان عن نوع بيانات الغرض لتحديد المحتوى الذي تحمله الإضافات.

KOTLIN
// Create the text message with a string
val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, textMessage)
    type = "text/plain"
}

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(packageManager) != null) {
    startActivity(sendIntent)
}
JAVA
// 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");

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

 

عندما يتم إستدعاء ()startActivity ، يقوم النظام بفحص كافة التطبيقات المثبتة، لتحديد أي منها يمكنه التعامل مع هذا النوع من الأغراض..

(غرض مع إجراء ACTION_SEND وتحمل بيانات “text/plain”). إذا كان هناك تطبيق واحد فقط يمكنه التعامل معه..

فسيتم فتح هذا التطبيق فوراً ويتم تسليم الغرض له. إذا قبلت عدة أنشطة الغرض، فسيعرض النظام مربع حوار مثل الذي يظهر في الشكل 2، بحيث يمكن للمستخدم إختيار التطبيق المراد إستخدامه.

يتم أيضاً توفير المزيد من المعلومات حول تشغيل التطبيقات الأخرى، في إرسال المستخدم إلى تطبيق آخر.

 

 

 

 

 

 

إجبار منتقي التطبيق

عندما يكون هناك أكثر من تطبيق واحد، يستجيب للأغراض الضمنية، يمكن للمستخدم تحديد التطبيق الذي يستخدمه، و يجعله هو الخيار الإفتراضي للإجراء.

تعتبر القدرة على تحديد التطبيق الإفتراضي، مفيدة عند تنفيذ إجراءٍ، عندما يرغب المستخدم في إستخدام نفس التطبيق في كل مرة..

مثل عند فتح صفحة ويب (غالباً ما يفضل المستخدمون متصفح ويب واحد فقط).

ومع ذلك، إذا كان بإمكان عدة تطبيقات الإستجابة للأغراض، و ربما كان المستخدم يرغب في إستخدام تطبيق مختلف في كل مرة..

فيجب عليك إظهار مربع حوار المنتقي بشكلٍ صريح. مربع حوار المنتقي، يطلب من المستخدم تحديد التطبيق المراد إستخدامه في الإجراء..

(لا يمكن للمستخدم تحديد تطبيق إفتراضي للإجراء). على سبيل المثال، عندما ينفذ تطبيقك “مشاركة” بإستخدام الإجراء ACTION_SEND ..

 

 

                            الشكل 2. مربع حوار المنتقي.

 

قد يرغب المستخدمون في المشاركة، بإستخدام تطبيق مختلف بناءً على وضعهم الحالي، لذلك يجب عليك دائماً إستخدام مربع حوار المنتقي، كما هو موضح في الشكل 2.

لإظهار المنتقي، قم بإنشاء غرض بإستخدام ()createChooser ثم قم بتمريره إلى ()startActivity ..

كما هو موضح في المثال التالي. يعرض هذا المثال مربع حوار يحتوي على قائمة بالتطبيقات التي تستجيب للغرض..

الذي تم تمريره إلى دالة ()createChooser ويستخدم النص الذي تم توفيره كعنوان لمربع الحوار.

KOTLIN
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)
}
JAVA
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);
}

 

 

 

 

 

تلقي غرض ضمني


للإعلان عن الأغراض الضمنية التي يمكن أن يتلقاها تطبيقك، قم بالإعلان عن مرشح غرض أو أكثر، لكل مكون من مكونات تطبيقك..

بإستخدام عنصر <intent-filter> في ملف الإيضاح الخاص بك. كل مرشح غرض intent ..

يحدد نوع الأغراض التي يقبلها، بناءً على إجراء الغرض، البيانات، التصنيف. يقوم النظام بتوصيل غرض ضمني لمكون التطبيق الخاص بك..

فقط إذا كان الغرض، يمكن تمريره من خلال إحدى مرشحات الغرض الخاصة بك.

 

ملاحظة: يتم دائماً إيصال الغرض الصريح إلى هدفه، بغض النظر عن أي مرشحات غرض يحددها المكون.

 

مكون التطبيق يجب أن يعلن عن مرشحات منفصلة، لكل مهمة فريدة، يمكنه القيام بها. على سبيل المثال..

قد يشتمل نشاط واحد، في تطبيق معرض الصور على مرشحين:

مرشح لعرض صورة، ومرشح آخر لتعديل الصورة. عندما يبدأ النشاط، فإنه يفحص الغرض ويقرر كيفية التصرف..

بناءً على المعلومات الموجودة في الغرض (مثل إظهار عناصر التحكم الخاصة بالمحرر، أم لا).

يتم تعريف كل مرشح غرض، بواسطة عنصر <intent-filter> في ملف إيضاح التطبيق، بشكلٍ متداخل في مكون التطبيق المتوافق (مثل عنصر <activity>).

داخل <intent-filter>، يمكنك تحديد نوع الأغراض التي يجب قبولها، بإستخدام واحد أو أكثر من هذه العناصر الثلاثة:

<action>

يعلن عن إجراء الغرض المقبول، في سمة الاسم. يجب أن تكون القيمة، قيمة سلسلة حرفية لإجراء ما، وليس ثوابت الفئة.

<data>

يعلن عن نوع البيانات المقبولة، بإستخدام سمة واحدة أو أكثر، تحدد جوانب مختلفة، من URI الخاص بالبيانات..

(نظام scheme ، مضيف host ، منفذ port ، مسار path) ونوع MIME.

 

<category>

يعلن عن تصنيف الغرض المقبول، في سمة الاسم. يجب أن تكون القيمة، قيمة سلسلة حرفية لإجراء ما، وليس ثوابت التصنيف.

ملاحظة: لتلقي الأغراض الضمنية، يجب عليك تضمين فئة CATEGORY_DEFAULT في مرشح الغرض.

تقوم دوال ()startActivity و ()startActivityForResult بمعاملة كافة الأغراض كما لو كانت تعلن عن التصنيف CATEGORY_DEFAULT.

إذا لم تقم بالإعلان عن هذا التصنيف في مرشح الغرض الخاص بك، فلن يتم إيصال أي أغراض ضمنية إلى نشاطك.

 

مثال، إليك إعلان عن نشاط، بإستخدام مرشح غرض، لتلقي غرض ACTION_SEND عندما يكون نوع البيانات نصي:

<activity android:name="ShareActivity">
    <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>.

إذا قمت بذلك، يجب أن تكون على يقين، من أن المكون يمكنه التعامل مع أي من وكافة، مجموعات عناصر المرشح هذه.

عندما ترغب في التعامل مع عدة أنواع من الأغراض، ولكن فقط في تراكيب محددة من الإجراءات ،البيانات، و نوع التصنيف، فأنت بحاجة إلى إنشاء عدة مرشحات غرض.

يتم إختبار الغرض الضمني ضد المرشح، من خلال مقارنة الغرض بكل عنصر من العناصر الثلاثة.

ليتم تسليمه إلى المكون، يجب أن يكون الغرض قد إجتاز الإختبارات الثلاثة. إذا فشل في مطابقة عنصر واحد منهم، فلن يقدم نظام الأندرويد الغرض إلى المكون.

ومع ذلك، نظراً لأن أحد المكونات قد يحتوي على عدة مرشحات غرض، فإن الغرض الذي لا يمر عبر أحد المرشحات الخاصة بالمكون..

قد يمر عبر مرشح آخر. يتم توفير مزيد من المعلومات، حول كيفية إيصال النظام للأغراض في القسم أدناه حول Intent Resolution.

تحذير: إن إستخدام مرشح غرض ليس طريقة آمنة، لمنع التطبيقات الأخرى، من بدء تشغيل مكوناتك. على الرغم من أن مرشحات الغرض..

تقوم بتقييد أحد المكونات، لكي يستجيب لأنواع معينة فقط من الأغراض الضمنيه، يمكن لتطبيق آخر، أن يبدأ مكون تطبيقك، بإستخدام غرض صريح..

إذا حدد المطور أسماء المكونات الخاصة بك. إذا كان من المهم أن يكون تطبيقك فقط هو القادر على بدء أحد مكوناتك..

فلا تعلن عن مرشحات غرض في ملف الإيضاح. بدلاً من ذلك، قم بتعيين سمة التصدير على القيمة “خطأ” لهذا المكون.

وبالمثل، لتجنب تشغيل خدمة تطبيق مختلف عن غير قصد، إستخدم دائماً غرض صريح لبدء الخدمة الخاصة بك.

ملاحظة: بالنسبة إلى جميع الأنشطة، يجب عليك الإعلان عن مرشحات الغرض في ملف الإيضاح. ومع ذلك، يمكن تسجيل مرشحات مستقبلات البث..

بشكلٍ حيوي عن طريق إستدعاء ()registerReceiver . يمكنك بعد ذلك، إلغاء تسجيل المستقبل، بإستخدام ()unregisterReceiver .

يسمح إجراء ذلك لتطبيقك، بالإستماع إلى عمليات بث محددة خلال فترة زمنية محددة، فقط أثناء تشغيل تطبيقك.

 

 

 

 

 

أمثله على المرشحات

لإثبات بعض سلوكيات مرشح الغرض، إليك مثال من ملف الإيضاح لتطبيق مشاركة إجتماعية:

<activity android:name="MainActivity">
    <!-- 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">
    <!-- 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 ، هو نقطة الدخول الرئيسية للتطبيق – النشاط الذي يتم فتحه عندما يقوم المستخدم في البداية بتشغيل التطبيق، بإستخدام أيقونة المشغل launcher:

– يشير الإجراء ACTION_MAIN إلى أن هذه هي نقطة الدخول الرئيسية، ولا يتوقع أي بيانات غرض.

– يشير التصنيف CATEGORY_LAUNCHER إلى أن أيقونة هذا النشاط يجب أن توضع في مشغل تطبيقات النظام.

إذا لم يحدد عنصر النشاط <activity> أيقونة بإستخدام أيقونة، فسيستخدم النظام أيقونة من عنصر التطبيق <application>.

 

يجب دمج هذين الإثنين معاً، لكي يظهر النشاط في مشغل التطبيقات.

يهدف النشاط الثاني، ShareActivity، إلى تسهيل مشاركة النص، ومحتوى الوسائط.

على الرغم من أن المستخدمين، قد يدخلون هذا النشاط، من خلال الإنتقال إليه من النشاط الرئيسي MainActivity..

يمكنهم أيضاً الدخول إلى ShareActivity مباشرةً من تطبيق آخر، يصدر غرض ضمني يطابق واحد من مرشحي الغرض الإثنان.

ملاحظة: نوع MIME ، application/vnd.google.panorama360 + jpg ، هو نوع خاص من البيانات، يحدد الصور البانورامية، والتي يمكنك التعامل معها، بإستخدام واجهات برمجة تطبيقات البانوراما من قوقل.

 

 

 

 

 

إستخدام الأغراض المعلقه


كائن PendingIntent عبارة عن كائن ملتف حول كائن الغرض Intent. الهدف الأساسي من PendingIntent هو..

منح الإذن لتطبيق خارجي، لإستخدام الغرض الموجود، كما لو تم تنفيذه من عملية التطبيق الخاصة بك.

تشمل حالات الإستخدام الرئيسية لغرضٍ معلق ما يلي:

  • الإعلان عن غرض، ليتم تنفيذه عندما ينفذ المستخدم إجراءً، بإستخدام الإشعار الخاص بك (نظام مدير إشعارات الأندرويد NotificationManager يقوم بتنفيذ الغرض).

 

  • الإعلان عن غرض ليتم تنفيذه، عند قيام المستخدم بتنفيذ إجراء بإستخدام ودجت التطبيق (تطبيق الشاشة الرئيسية يقوم بتنفيذ الغرض).

 

  • الإعلان عن غرض ليتم تنفيذه، في وقتٍ محدد في المستقبل (يقوم مدير المنبه للأندرويد بتنفيذ الغرض).

تماماً كما تم تصميم كل كائن غرض Intent ، ليتم التعامل معه بواسطة نوع معين من مكونات التطبيق (إما النشاط أو الخدمة أو مستقبل البث)..

يجب أيضاً إنشاء غرض معلق PendingIntent بنفس الإعتبار. عند إستخدام غرض معلق، لا يقوم تطبيقك بتنفيذ الغرض بواسطة إستدعاء مثل ()startActivity .

بدلاً من ذلك، يجب عليك تعريف نوع المكون المطلوب، عند إنشائك للغرض المعلق PendingIntent عن طريق إستدعاء دالة الإنشاء الخاصة به:

  • ()PendingIntent.getActivity دالة للغرض الذي يبدأ النشاط.
  • ()PendingIntent.getService  دالة للغرض الذي يبدأ الخدمة.
  • ()PendingIntent.getBroadcast  دالة للغرض الذي يبدأ مستقبل البث.

 

ما لم يكن تطبيقك يتلقى أغراضاً معلقة من تطبيقات أخرى، فإن الدوال المذكورة أعلاه، لإنشاء الغرض المعلق PendingIntent..

على الأرجح هي دوال الغرض المعلق PendingIntent الوحيدة التي ستحتاج إليها.

كل دالة تأخذ سياق التطبيق الحالي، الغرض الذي تريد لفه، وعلم واحد أو أكثر، والتي تحدد كيفية إستخدام الغرض (مثل ما إذا كان الغرض يمكن إستخدامه أكثر من مرة).

لمزيد من المعلومات حول إستخدام الأغراض المعلقة، راجع الوثائق الخاصة بكل من حالات الإستخدام ذات الصلة، كما هو مبين في أدلة الإشعارات و واجهة برمجة تطبيقات الودجت.

 

 

 

 

إيصال الغرض


عندما يتلقى النظام غرض ضمني لبدء نشاطٍ ما، فإنه يبحث عن أفضل نشاط للغرض، من خلال مقارنته مع مرشحات الغرض بناءً على ثلاثة جوانب:

  • الإجراء
  • بيانات (لكلٍ من URI ونوع البيانات).
  • التصنيف

تصف الأقسام التالية كيفية مطابقة الأغراض للمكونات المناسبة، وفقاً لإعلان مرشح الغرض في ملف إيضاح التطبيق.

 

 

 

 

إختبار الإجراء

لتحديد إجراءات الغرض المقبولة، يمكن لمرشح الغرض أن يعلن عن صفر أو أكثر من عناصر الإجراء <action>، كما هو موضح في المثال التالي:

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

 

لتمرير هذا المرشح، يجب أن يتطابق الإجراء المحدد في الغرض، مع أحد الإجراءات المدرجة في المرشح.

إذا لم يقم المرشح بإدراج أية إجراءات، فلن يكون هناك أي شيء لمطابقة الغرض، لذلك تفشل جميع الأغراض في الإختبار.

ومع ذلك، إذا لم يحدد الغرض، إجراءٍ ما ، فسوف يجتاز الإختبار، طالما يحتوي المرشح على إجراء واحد على الأقل.

 

 

 

 

إختبار التصنيف

لتحديد تصنيفات الغرض المقبولة، يمكن لمرشح الغرض intent أن يعلن عن صفر أو أكثر من عناصر التصنيف <category>، كما هو موضح في المثال التالي:

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>

 

لكي يجتاز الغرض إختبار التصنيف، يجب أن يتطابق كل تصنيف في الغرض، مع التصنيف في المرشح.

العكس ليس ضرورياً – قد يعلن مرشح الغرض عن تصنيفات أكثر مما تم تحديده في الغرض، وبالتالي لا يزال بإمكان الغرض المرور.

لذلك، فإن غرضاً بلا تصنيفات، يمكنه تجاوز هذا الإختبار دائماً، بغض النظر عن التصنيفات التي يتم الإعلان عنها في المرشح.

 

ملاحظة: يقوم الأندرويد تلقائياً بتطبيق التصنيف 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

في عنوان URL هذا، يكون النظام عبارة عن content، والمضيف هو com.example.project، والمنفذ 200 ، والمسار هو folder/subfolder/etc.

 

كل واحدة من هذه السمات إختيارية في عنصر البيانات <data>، ولكن هناك إعتمادات خطية:

  • إذا لم يتم تحديد المخطط، فسيتم تجاهل المضيف.
  • إذا لم يتم تحديد المضيف، فسيتم تجاهل المنفذ.
  • إذا لم يتم تحديد كلٍ من المخطط والمضيف، فسيتم تجاهل المسار.

 

عندما تتم مقارنة URI في غرض، بمواصفات URI في مرشح، تتم مقارنته فقط بأجزاء URI المضمنة في المرشح. فمثلاً:

 

  • إذا حدد المرشح مخططاً فقط، فستتم مطابقة جميع عناوين URI في هذا المخطط مع المرشح.
  • إذا حدد المرشح مخططاً ومصادقه authority، ولكن دون مسار، فإن كافة URI التي لها نفس المخطط والمصادقه سوف تجتاز المرشح، بصرف النظر عن مساراتهم.
  • إذا حدد المرشح مخططاً ومصادقة ومسار، فإنه فقط URI التي لها نفس المخطط والمصادقه والمسار تجتاز المرشح.
ملاحظة: يمكن أن تحتوي مواصفات المسار على الرمز (*) للمطالبة فقط، بمطابقة جزئية لأسم المسار.

 

يقوم إختبار البيانات بمطابقة كلٍ من URI ونوع MIME في الغرض، بـ URI ونوع MIME المحددان في المرشح. القواعد على النحو التالي:

1- الغرض الذي يحتوي على، إما URI أو نوع MIME ، يقوم بتمرير الإختبار فقط إذا لم يحدد المرشح أي أنواع لـ URI أو MIME.

2- الغرض الذي يحتوي على URI ولكن لا يوجد نوع MIME (لا صريحة ولا مستعصيه من URI)..

يجتاز الإختبار، إلا إذا كان URI الخاص به، يتطابق مع تنسيق URI للمرشح، ولا يقوم المرشح كذلك بتحديد نوع MIME.

3- الغرض الذي يحتوي على نوع MIME ولكنه ليس URI يقوم بإجتياز الإختبار، فقط إذا كان المرشح يقوم بإدراج نفس نوع MIME ولا يحدد تنسيق URI.

4- غرض يحتوي على كلٍ من URI ونوع MIME (إما صريح أو مستعصي من URI) يقوم بتمرير جزئية MIME من الإختبار..

فقط إذا كان هذا النوع، يطابق نوعاً مدرجاً في المرشح. يقوم بتمرير جزء URI من الإختبار، إما إذا كان URI الخاص به، يتطابق مع URI في المرشح..

أو إذا كان يحتوي على محتوى: أو ملف: URI ولا يقوم المرشح بتحديد عنوان URI.

بمعنى آخر، يفترض أن أحد المكونات، يدعم المحتوى: والملف: والبيانات إذا كان المرشح الخاص به يقوم بإدراج نوع MIME فقط.

 

ملاحظة: إذا قام الغرض بتحديد نوع URI أو MIME ، فسوف يفشل إختبار البيانات، إذا لم تكن هناك عناصر بيانات <data> في مرشح الغرض <intent-filter>.

هذه القاعدة الأخيره، القاعدة (d)، تقوم بعكس توقعات المكونات، القادرة على الحصول على البيانات المحلية من ملف أو من موفر محتوى.

لذا، يمكن للمرشحات الخاصة بها، أن تقوم بإدراج نوع البيانات فقط، ولا تحتاج إلى تسمية المحتوى: والملف: والمخططات صراحة.

يوضح المثال التالي حالة نموذجية، يخبر فيها عنصر البيانات <data> نظام الأندرويد، أن المكون يمكنه الحصول على بيانات الصورة، من موفر المحتوى، ويقوم بعرضها:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

 

قد تكون المرشحات التي تحدد نوع البيانات، ولا تحدد URI هي الأكثر شيوعاً، نظراً لأن معظم البيانات المتاحة، يتم الإستغناء عنها من قبل موفري المحتوى.

هناك تكوين شائع آخر، وهو مرشح يحتوي على مخطط ونوع بيانات.

مثال، عنصر بيانات <data> كالتالي، يخبر نظام الأندرويد، أن المكون يمكنه إسترداد بيانات فيديو من الشبكة من أجل تنفيذ الإجراء:

<intent-filter>
    <data android:scheme="http" android:mimeType="video/*" />
    ...
</intent-filter>

 

 

 

 

مطابقة الأغراض

تتم مطابقة الأغراض مع مرشحات الغرض، ليس فقط من أجل إكتشاف المكون المستهدف لتنشيطه..

ولكن أيضاً لإكتشاف شيء حول، مجموعة المكونات على الجهاز. مثال، تطبيق Home يقوم بملء مشغّل التطبيقات..

من خلال البحث عن جميع الأنشطة، التي تحتوي على مرشحات الغرض التي تحدد الإجراء ACTION_MAIN والتصنيف CATEGORY_LAUNCHER.

تكون المطابقة ناجحة، فقط إذا كانت الإجراءات والتصنيفات في الغرض، متطابقة مع المرشح، كما هو موضح في وثائق فئة مرشح الغرض IntentFilter.

يمكن لتطبيقك إستخدام مطابقة الغرض، بطريقة مشابهة لما يفعله التطبيق الرئيسي Home. يحتوي PackageManager على مجموعة من..

دوال الإستعلام ()...query التي تقوم بإرجاع كافة المكونات، التي يمكنها أن تقبل غرض معين وسلسلة مماثلة من دوال ()...resolve التي تحدد أفضل مكون للإستجابة للغرض.

على سبيل المثال، تقوم ()queryIntentActivities بإرجاع قائمة بجميع الأنشطة التي يمكن أن تقوم بتمرير الغرض كمعطى..

و تقوم ()queryIntentServices بإرجاع قائمة مماثلة بالخدمات. ولا واحدة من الدوال تقوم بتنشيط المكونات..

هي فقط تقوم بإدراج المكونات التي يمكن أن تستجيب. هناك دالة مشابهة، و هي دالة()queryBroadcastReceivers ، لمستقبلات البث.

 


للإطلاع على المقال باللغة الإنجليزية أضغط هنا.

الإعلانات