تلبية حالات الاستخدام الشائعة مع توفُّر إمكانية رؤية محدودة للحزمة

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

عندما يستخدِم أحد التطبيقات التي تستهدف الإصدار 11 من نظام التشغيل Android أو الإصدارات الأحدث نيةً لإجراء ما يلي: وبدء نشاط في تطبيق آخر، فإن النهج الأكثر سهولة هو استدعاء النية والتعامل مع ActivityNotFoundException باستثناء في حالة عدم توفر أي تطبيق.

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

عناوين URL المفتوحة

يوضّح هذا القسم طرقًا مختلفة لفتح عناوين URL في تطبيق يستهدف الإصدار 11 من نظام التشغيل Android أو إصدار أحدث

فتح عناوين URL في متصفّح أو تطبيق آخر

لفتح عنوان URL، استخدِم هدفًا يحتوي على ACTION_VIEW الإجراء المطلوب، مثل كما هو موضح في دليل تحميل موقع ويب عنوان URL. بعد الاتصال بـ startActivity() باستخدام هذا الغرض، يحدث أحد ما يلي:

  • يفتح عنوان URL في تطبيق متصفّح الويب.
  • يتم فتح عنوان URL في تطبيق يتوافق مع عنوان URL كصفحة لصفحة في التطبيق. .
  • يظهر مربّع حوار توضيحي يتيح للمستخدم اختيار التطبيق. لفتح عنوان URL.
  • يحدث ActivityNotFoundException بسبب عدم وجود تطبيق مثبَّت على الجهاز الذي يمكنه فتح عنوان URL. (هذا أمر غير عادي).

    ننصح بأن يلتقط تطبيقك ActivityNotFoundException في حال حدوثها.

لأنّ الطريقة startActivity() لا تتطلّب إذن الوصول إلى الحزمة بدء نشاط تطبيق آخر، فلست بحاجة إلى إضافة <queries> إلى بيان التطبيق أو إجراء أي تغييرات على <queries> حالية العنصر. وينطبق ذلك على كلّ من الأهداف الضمنية والصريحة التي تفتح عنوان URL.

التحقُّق من توفُّر متصفِّح

في بعض الحالات، قد يحتاج تطبيقك إلى التأكّد من توفُّر متصفّح واحد على الأقل. متاحة على الجهاز، أو أن متصفحًا معينًا هو المتصفح الافتراضي، قبل محاولة فتح عنوان URL. في هذه الحالات، قم بتضمين ما يلي العنصر <intent> كجزء من العنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" />
</intent>

عند استدعاء queryIntentActivities() وتمرير هدف الويب كوسيطة، تتضمّن القائمة المعروضة تطبيقات المتصفّح المتاحة في بعض الحالات. القائمة لا تتضمّن تطبيقات المتصفّح إذا ضبط المستخدم عنوان URL ليفتح في تطبيق بدون متصفح افتراضيًا.

فتح عناوين URL في علامات تبويب مخصَّصة

تتيح علامات التبويب المخصصة على تخصيص شكل المتصفح وأسلوبه. يمكنك فتح عنوان URL في علامة تبويب مخصَّصة بدون الحاجة إلى إضافة العنصر <queries> أو تغييره في بيان التطبيق

ومع ذلك، ننصحك بالتحقّق مما إذا كان الجهاز مزوّدًا بمتصفّح متوافق. علامات التبويب المخصَّصة أو اختيار متصفّح محدّد لتشغيله باستخدام "علامات التبويب المخصّصة" (Custom Tabs) باستخدام CustomTabsClient.getPackageName() في تلك الحالات، يجب تضمين العنصر <intent> التالي كجزء من عنصر <queries> في ملف البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>

السماح للتطبيقات التي لا تستخدم متصفّحًا بالتعامل مع عناوين URL

حتى إذا كان بإمكان تطبيقك فتح عناوين URL باستخدام علامات التبويب المخصَّصة، ننصحك السماح لتطبيق لا يعمل بمتصفح يفتح عنوان URL إن أمكن. لتوفير هذه المعلومات، في تطبيقك، يُرجى محاولة الاتصال بالرقم startActivity() باستخدام إجراء. التي تحدد FLAG_ACTIVITY_REQUIRE_NON_BROWSER علامة intent. وإذا عرض النظام رمز الاستجابة ActivityNotFoundException، يمكن لتطبيقك تنفيذ ما يلي: ثم افتح عنوان URL في علامة تبويب مخصصة.

إذا تضمّن الغرض هذه العلامة، يؤدّي استدعاء startActivity() إلى حدوث يتم طرح ActivityNotFoundException في إحدى الحالتَين التاليتَين الحالات التالية:

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

يوضح مقتطف الرمز التالي كيفية تعديل منطقك لاستخدام علامة هدف واحدة (FLAG_ACTIVITY_REQUIRE_NON_BROWSER):

Kotlin

try {
    val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply {
        // The URL should either launch directly in a non-browser app (if it's
        // the default) or in the disambiguation dialog.
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url)
}

Java

try {
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    // The URL should either launch directly in a non-browser app (if it's the
    // default) or in the disambiguation dialog.
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url);
}

تجنب مربّع حوار توضيحي

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

إذا تضمّن الغرض هذه العلامة، يؤدّي استدعاء startActivity() إلى حدوث سيتم طرح ActivityNotFoundException عندما تظهر المكالمة مربع حوار توضيحي للمستخدم.

إذا تضمنت النية كلاً من هذه العلامة FLAG_ACTIVITY_REQUIRE_NON_BROWSER علامة intent، تسبب الطلب startActivity() في حدوث ActivityNotFoundException يجب طرحها عند حدوث أحد الشروط التالية:

  • كان من الممكن أن تؤدي المكالمة إلى تشغيل تطبيق المتصفح مباشرةً.
  • ستظهر المكالمة للمستخدم مربّع حوار توضيحي.

يعرض مقتطف الرمز التالي طريقة استخدام FLAG_ACTIVITY_REQUIRE_NON_BROWSER وFLAG_ACTIVITY_REQUIRE_DEFAULT علامة معًا:

Kotlin

val url = URL_TO_LOAD
try {
    // For this intent to be invoked, the system must directly launch a
    // non-browser app.
    val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply {
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER or
                FLAG_ACTIVITY_REQUIRE_DEFAULT
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url)
}

Java

String url = URL_TO_LOAD;
try {
    // For this intent to be invoked, the system must directly launch a
    // non-browser app.
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER |
            FLAG_ACTIVITY_REQUIRE_DEFAULT);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url);
}

فتح ملف

إذا كان تطبيقك يعالج الملفات أو المرفقات، مثلاً التحقّق مما إذا كان بإمكان الجهاز فتح ملف معين، فمن الأسهل عادةً محاولة بدء نشاط يمكن التعامل مع الملف. لإجراء ذلك، استخدِم هدفًا يتضمّن نية ACTION_VIEW. ومعرّف الموارد المنتظم (URI) الذي يمثل الملف المحدد. في حال عدم توفُّر أي تطبيق على الجهاز، سيتمكّن تطبيقك من رصد ActivityNotFoundException. في للتعامل مع الاستثناءات، يمكنك إما إظهار خطأ أو محاولة معالجة الملف نفسك.

إذا كان على تطبيقك أن يعرف مقدمًا ما إذا كان بإمكان تطبيق آخر فتح ملف معيّن أم لا، تضمين العنصر <intent> في مقتطف الرمز التالي كجزء من العنصر <queries> في ملف البيان. قم بتضمين نوع الملف إذا كنت تعرف ذلك بالفعل وما هو عليه في وقت التجميع.

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". -->
  <data android:mimeType="application/pdf" />
</intent>

يمكنك بعد ذلك التحقّق ممّا إذا كان التطبيق متاحًا من خلال الاتصال على الرقم resolveActivity(). في تحقيق هدفك.

منح إمكانية الدخول إلى معرف الموارد المنتظم (URI)

ملاحظة: تعريف أذونات الوصول إلى عنوان URI كما هو موضّح في هذا القسم مطلوبة للتطبيقات التي تستهدف Android 11 (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث ننصح به لجميع التطبيقات، بغض النظر عن إصدار حزمة تطوير البرامج (SDK) المستهدَف وما إذا كان يتم تصدير موفّري المحتوى التابعين لهم.

بالنسبة إلى التطبيقات التي تستهدف الإصدار 11 من نظام التشغيل Android أو الإصدارات الأحدث الوصول إلى معرّف الموارد المنتظم (URI) للمحتوى، يجب أن يفصح هدف التطبيق عن الوصول إلى معرّف الموارد المنتظم (URI) الأذونات من خلال ضبط إحدى علامتيّ الأهداف التاليتَين أو كلتيهما: FLAG_GRANT_READ_URI_PERMISSION أو FLAG_GRANT_WRITE_URI_PERMISSION

في نظام التشغيل Android 11 والإصدارات الأحدث، تمنح أذونات الوصول إلى معرّف الموارد المنتظم (URI) الإمكانات التالية للتطبيق الذي يتلقّى الغرض:

  • اقرأ من البيانات التي يمثلها معرف الموارد المنتظم (URI) للمحتوى أو اكتب إليها، اعتمادًا على أذونات معرف الموارد المنتظم (URI) المحددة.
  • الحصول على إذن الوصول إلى التطبيق الذي يتضمن موفِّر المحتوى الذي يتطابق مع مرجع معرّف الموارد المنتظم (URI). قد يكون التطبيق الذي يتضمّن موفِّر المحتوى مختلفًا من التطبيق الذي يرسل intent.

يوضح مقتطف الرمز التالي كيفية إضافة علامة intent لأذونات معرّف الموارد المنتظم (URI). لكي يتمكّن تطبيق آخر يستهدف الإصدار 11 من نظام التشغيل Android أو الإصدارات الأحدث من عرض البيانات في معرف الموارد المنتظم للمحتوى:

Kotlin

val shareIntent = Intent(Intent.ACTION_VIEW).apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    data = CONTENT_URI_TO_SHARE_WITH_OTHER_APP
}

Java

Intent shareIntent = new Intent(Intent.ACTION_VIEW);
shareIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setData(CONTENT_URI_TO_SHARE_WITH_OTHER_APP);

الربط بالخدمات

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

الربط بمحرك لتحويل النص إلى كلام

إذا كان تطبيقك يتفاعل مع محرك لتحويل النص إلى كلام، يجب تضمين ما يلي: العنصر <intent> كجزء من العنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.TTS_SERVICE" />
</intent>

الاتصال بخدمة التعرّف على الكلام

إذا تفاعَل تطبيقك مع إحدى خدمات التعرّف على الكلام، عليك تضمين ما يلي: العنصر <intent> كجزء من العنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.speech.RecognitionService" />
</intent>

الاتصال بخدمات متصفِّح الوسائط

إذا كان التطبيق يستخدم أحد متصفّحات الوسائط العميلة التطبيق، تتضمن العنصر <intent> التالي كجزء من العنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.media.browse.MediaBrowserService" />
</intent>

توفير وظائف مخصصة

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

طلب تطبيقات الرسائل القصيرة SMS

إذا كان تطبيقك يحتاج إلى معلومات حول مجموعة تطبيقات الرسائل القصيرة SMS المثبَّتة على الجهاز، على سبيل المثال للتحقّق من التطبيق الذي يُعد معالِج الرسائل القصيرة SMS التلقائي على الجهاز، تضمين العنصر <intent> التالي كجزء من العنصر <queries> في في بيان التطبيق:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.SENDTO"/>
  <data android:scheme="smsto" android:host="*" />
</intent>

إنشاء ورقة مشاركة مخصّصة

استخدِم القيمة التي يقدّمها النظام قائمة مشاركة البيانات. بدلاً من ذلك، تضمين العنصر <intent> التالي كجزء من العنصر <queries> في في بيان التطبيق:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.SEND" />
  <!-- Replace with the MIME type that your app works with, if needed. -->
  <data android:mimeType="image/jpeg" />
</intent>

يشير هذا المصطلح إلى عملية إنشاء قائمة مشاركة البيانات وفقًا لمنطق تطبيقك، مثل استدعاء queryIntentActivities()، بخلاف ذلك سيظل بدون تغيير مقارنةً بـ التي تعمل بالإصدارات الأقدم من نظام التشغيل Android 11.

إظهار إجراءات تحديد النص المخصّص

عندما يحدّد المستخدمون نصًا في تطبيقك، ستظهر عبارة اختيار نص. شريط الأدوات تعرض مجموعة العمليات المحتملة التي يمكن إجراؤها على النص المحدد. إذا كان هذا يعرض شريط الأدوات الإجراءات المخصصة من التطبيقات الأخرى، قم بتضمين ما يلي العنصر <intent> كجزء من العنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.PROCESS_TEXT" />
  <data android:mimeType="text/plain" />
</intent>

إظهار صفوف البيانات المخصّصة لجهة اتصال

إمكانية إضافة التطبيقات بيانات مخصَّصة الصفوف إلى جهات الاتصال مزوِّد الخدمة لكي يعرض تطبيق جهات الاتصال هذه البيانات المخصصة، يجب أن يكون من إجراء ما يلي:

  1. اقرأ الملف contacts.xml من التطبيقات الأخرى.
  2. حمِّل رمزًا يتوافق مع نوع MIME المخصّص.

إذا كان تطبيقك مخصّصًا لجهات الاتصال، عليك تضمين عناصر <intent> التالية كجزء من التطبيق للعنصر <queries> في البيان:

<!-- Place inside the <queries> element. -->
<!-- Lets the app read the contacts.xml file from other apps. -->
<intent>
  <action android:name="android.accounts.AccountAuthenticator" />
</intent>
<!-- Lets the app load an icon corresponding to the custom MIME type. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <data android:scheme="content" android:host="com.android.contacts"
        android:mimeType="vnd.android.cursor.item/*" />
</intent>