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

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

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

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

فتح عناوين URL

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

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

لفتح عنوان URL، استخدِم هدفًا يتضمّن إجراء intent 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);
}

فتح ملف

إذا كان تطبيقك يعالج الملفات أو المرفقات، مثل التحقّق مما إذا كان بإمكان جهاز ما فتح ملف معيّن، من الأسهل عادةً محاولة بدء نشاط يمكنه معالجة الملف. لإجراء ذلك، استخدِم هدفًا يتضمّن إجراء intent 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() مع تضمين النية.

منح إذن الوصول إلى عنوان URL

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

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

في الإصدار Android 11 والإصدارات الأحدث، تمنح أذونات الوصول إلى عناوين URL التطبيقات التي تتلقّى الطلب القدرات التالية:

  • قراءة البيانات التي يمثّلها معرّف الموارد المنتظم للمحتوى أو الكتابة فيها، استنادًا إلى أذونات معرّف الموارد المنتظم الممنوحة
  • الاطّلاع على التطبيق الذي يتضمّن مقدّم المحتوى الذي يتطابق مع هيئة عنوان URL قد يكون التطبيق الذي يحتوي على مقدّم المحتوى مختلفًا عن التطبيق الذي يُرسِل النية.

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

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> في بيانك. تقدّم الأقسام التالية إرشادات تفصيلية حول العديد من السيناريوهات الشائعة.

طلب البحث عن تطبيقات الرسائل القصيرة

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