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

يعرض هذا المستند العديد من حالات الاستخدام الشائعة التي يتفاعل فيها التطبيق مع التطبيقات الأخرى. يقدِّم كل قسم إرشادات حول كيفية إنجاز وظائف التطبيق من خلال إذن الوصول المحدود إلى الحِزم، وهي إرشادات يجب مراعاتها إذا كان تطبيقك يستهدف الإصدار 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> أو تغييره في بيان التطبيق.

مع ذلك، يمكنك التحقّق مما إذا كان الجهاز يحتوي على متصفّح متوافق مع علامات التبويب المخصَّصة أو اختيار متصفّح معيّن لتشغيله مع "علامات التبويب المخصَّصة" باستخدام 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. إذا عرض النظام علامة 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.

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

إذا تضمّن الغرض كلاً من هذه العلامة وعلامة FLAG_ACTIVITY_REQUIRE_NON_BROWSER النية، ستؤدي طلب الرمز 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) من خلال ضبط إحدى علامتَي الغرض التاليتَين أو كليهما: FLAG_GRANT_READ_URI_PERMISSION وFLAG_GRANT_WRITE_URI_PERMISSION.

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

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

يوضِّح مقتطف الرمز التالي كيفية إضافة علامة الغرض من أذونات معرّف الموارد المنتظم (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 التي تم تثبيتها على الجهاز، للتحقق مثلاً من التطبيق الذي يكون المعالج التلقائي للرسائل القصيرة على الجهاز، يمكنك تضمين عنصر <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 الأقدم من 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>