موارد استفاده رایج را با رؤیت‌پذیری محدود بسته برآورده کنید

این سند چندین مورد استفاده رایج را ارائه می‌دهد که در آن‌ها یک برنامه با برنامه‌های دیگر تعامل دارد. هر بخش راهنمایی‌هایی درباره نحوه انجام عملکرد برنامه با رؤیت‌پذیری محدود بسته ارائه می‌دهد که اگر برنامه‌تان Android 11 (میانای برنامه‌سازی کاربردی سطح ۳۰) یا بالاتر را هدف قرار می‌دهد، باید آن را درنظر بگیرید.

وقتی برنامه‌ای که Android نسخه ۱۱ یا بالاتر را هدف قرار می‌دهد از قصدی برای شروع فعالیتی در برنامه دیگری استفاده می‌کند، ساده‌ترین رویکرد این است که قصد را فراخوانی کنید و درصورت دردسترس نبودن برنامه، استثنای ActivityNotFoundException را مدیریت کنید.

اگر بخشی از برنامه‌تان به دانستن اینکه آیا فراخوانی به startActivity() می‌تواند موفق شود یا نه بستگی دارد، مثلاً نمایش یک میانای کاربر، عنصری را به عنصر <queries> مانیفست برنامه‌تان اضافه کنید. معمولاً این عنصر <intent> است.

باز کردن نشانی‌های وب

این بخش روش‌های مختلف باز کردن نشانی‌های وب را در برنامه‌ای که Android 11 یا بالاتر را هدف قرار می‌دهد شرح می‌دهد.

باز کردن نشانی‌های وب در مرورگر یا برنامه‌ای دیگر

برای باز کردن نشانی وب، از هدفی استفاده کنید که حاوی کنش هدف ACTION_VIEW باشد، همان‌طور که در راهنمای بار کردن نشانی وب شرح داده شده است. پس‌از اینکه startActivity() را بااستفاده از این هدف فراخوانی کردید، یکی از موارد زیر اتفاق می‌افتد:

  • نشانی وب در برنامه مرورگر وب باز می‌شود.
  • نشانی وب در برنامه‌ای باز می‌شود که از نشانی وب به‌عنوان پیوند عمیق پشتیبانی می‌کند.
  • کادر گفتگوی ابهام‌زدایی ظاهر می‌شود که به کاربر اجازه می‌دهد انتخاب کند کدام برنامه نشانی وب را باز کند.
  • ActivityNotFoundException زمانی رخ می‌دهد که برنامه‌ای در دستگاه نصب نشده باشد که بتواند نشانی وب را باز کند. (این غیرعادی است.)

    توصیه می‌شود که برنامه‌تان ActivityNotFoundException را درصورت وقوع، دریافت و مدیریت کند.

چون روش startActivity() برای شروع فعالیت برنامه دیگر به رؤیت‌پذیری بسته نیاز ندارد، لازم نیست عنصر <queries> را به مانیفست برنامه‌تان اضافه کنید یا تغییری در عنصر <queries> موجود ایجاد کنید. این موضوع برای هر دو هدف ضمنی و صریح که نشانی وب را باز می‌کنند صادق است.

بررسی کنید آیا مرورگری دردسترس است یا نه

در برخی موارد، ممکن است برنامه‌تان بخواهد قبل‌از تلاش برای باز کردن نشانی وب، درستی‌سنجی کند که حداقل یک مرورگر در دستگاه دردسترس است یا مرورگر خاصی مرورگر پیش‌فرض است. در این موارد، عنصر <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() را فراخوانی می‌کنید و یک هدف وب را به‌عنوان آرگومان ارسال می‌کنید، فهرست برگردانده‌شده در برخی موارد شامل برنامه‌های مرورگر دردسترس است. اگر کاربر نشانی وب را به‌گونه‌ای پیکربندی کرده باشد که به‌طور پیش‌فرض در برنامه‌ای غیرمرورگر باز شود، این فهرست شامل برنامه‌های مرورگر نمی‌شود.

باز کردن نشانی‌های وب در «برگه‌های سفارشی»

برگه‌های سفارشی به برنامه اجازه می‌دهد ظاهر و کاربرد مرورگر را سفارشی‌سازی کند. می‌توانید نشانی وب را در «برگه سفارشی» باز کنید بدون اینکه لازم باشد عنصر <queries> را در مانیفست برنامه‌تان اضافه یا تغییر دهید.

بااین‌حال، شاید بخواهید بررسی کنید که آیا دستگاه مرورگری دارد که از «برگه‌های سفارشی» پشتیبانی کند یا مرورگر خاصی را برای راه‌اندازی با «برگه‌های سفارشی» بااستفاده از CustomTabsClient.getPackageName() انتخاب کنید. در این موارد، عنصر <intent> زیر را به‌عنوان بخشی از عنصر <queries> در مانیفست خود اضافه کنید:

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

اجازه دادن به برنامه‌های غیرمرورگر برای مدیریت نشانی‌های وب

حتی اگر برنامه‌تان بتواند نشانی‌های وب را بااستفاده از «برگه‌های سفارشی» باز کند، توصیه می‌شود درصورت امکان اجازه دهید برنامه‌ای غیرمرورگر نشانی وب را باز کند. برای ارائه این قابلیت در برنامه‌تان، بااستفاده از قصدی که پرچم قصد FLAG_ACTIVITY_REQUIRE_NON_BROWSER را تنظیم می‌کند، startActivity() را فراخوانی کنید. اگر سیستم ActivityNotFoundException را برگرداند، برنامه‌تان می‌تواند نشانی وب را در «برگه سفارشی» باز کند.

اگر قصدی شامل این پرچم باشد، تماس با startActivity() باعث می‌شود که درصورت وقوع هریک از شرایط زیر، ActivityNotFoundException ایجاد شود:

  • این تماس مستقیماً برنامه مرورگر را راه‌اندازی می‌کرد.
  • این فراخوانی کادر گفتگوی ابهام‌زدایی را به کاربر نشان می‌دهد که تنها گزینه‌های آن برنامه‌های مرورگر است.

تکه‌کد زیر نشان می‌دهد که چگونه منطق خود را برای استفاده از پرچم قصد FLAG_ACTIVITY_REQUIRE_NON_BROWSER به‌روز کنید:

کاتلین

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)
}

جاوا

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

اجتناب از کادر گفتگوی ابهام‌زدایی

اگر می‌خواهید از نمایش کادر گفتگوی ابهام‌زدایی که ممکن است کاربران هنگام باز کردن نشانی وب ببینند جلوگیری کنید و درعوض ترجیح می‌دهید خودتان نشانی وب را در این شرایط مدیریت کنید، می‌توانید از قصدی استفاده کنید که پرچم قصد FLAG_ACTIVITY_REQUIRE_DEFAULT را تنظیم می‌کند.

اگر قصدی شامل این پرچم باشد، تماس با startActivity() باعث می‌شود ActivityNotFoundException زمانی که تماس می‌توانست کادر گفتگوی ابهام‌زدایی را به کاربر نشان دهد، پرتاب شود.

اگر قصدی هم این پرچم و هم پرچم قصد FLAG_ACTIVITY_REQUIRE_NON_BROWSER را داشته باشد، تماس با startActivity() باعث می‌شود که درصورت وقوع هریک از شرایط زیر، ActivityNotFoundException پرتاب شود:

  • این تماس مستقیماً برنامه مرورگر را راه‌اندازی می‌کرد.
  • تماس می‌توانست کادر گفتگوی ابهام‌زدایی را به کاربر نشان دهد.

تکه‌کد زیر نحوه استفاده از پرچم‌های FLAG_ACTIVITY_REQUIRE_NON_BROWSER و FLAG_ACTIVITY_REQUIRE_DEFAULT را باهم نشان می‌دهد:

کاتلین

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)
}

جاوا

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 و شناسه منبع یکسانی باشد که فایل خاص را نشان می‌دهد. اگر هیچ برنامه‌ای در دستگاه دردسترس نباشد، برنامه شما می‌تواند 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) یا بالاتر را هدف قرار می‌دهند الزامی است و برای همه برنامه‌ها، صرف‌نظر از نسخه کیت توسعه نرم‌افزار هدف آن‌ها و اینکه آیا ارائه‌دهندگان محتوای خود را صادر می‌کنند یا نه، توصیه می‌شود.

برای برنامه‌هایی که Android نسخه ۱۱ یا بالاتر را هدف قرار می‌دهند، برای دسترسی به شناسه منبع یکسان محتوا، هدف برنامه شما باید اجازه‌های دسترسی به شناسه منبع یکسان را با تنظیم یکی یا هر دو پرچم هدف زیر اعلام کند: FLAG_GRANT_READ_URI_PERMISSION و FLAG_GRANT_WRITE_URI_PERMISSION.

در Android نسخه ۱۱ و بالاتر، اجازه‌های دسترسی URI قابلیت‌های زیر را به برنامه‌ای که هدف را دریافت می‌کند می‌دهد:

  • بسته به اجازه‌های URI داده‌شده، از داده‌هایی که شناسه منبع یکسان محتوا نشان می‌دهد بخواند یا در آن‌ها بنویسد.
  • Gain visibility into the app containing the content provider that matches the URI authority. برنامه‌ای که حاوی ارائه‌دهنده محتوا است ممکن است با برنامه‌ای که هدف را ارسال می‌کند متفاوت باشد.

تکه‌کد زیر نشان می‌دهد که چگونه پرچم هدف اجازه‌های URI را اضافه کنید تا برنامه دیگری که Android نسخه ۱۱ یا بالاتر را هدف قرار می‌دهد بتواند داده‌ها را در URI محتوا مشاهده کند:

کاتلین

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

جاوا

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

متصل شدن به سرویس‌ها

اگر برنامه‌تان باید با سرویسی تعامل داشته باشد که به‌طور خودکار نمایان نیست، می‌توانید کنش هدف مناسب را در عنصر <queries> اعلام کنید. بخش‌های زیر نمونه‌هایی از سرویس‌هایی را که معمولاً به آن‌ها دسترسی پیدا می‌شود ارائه می‌دهند.

اتصال به موتور نوشتار به گفتار

اگر برنامه‌تان با موتور نوشتار به گفتار (TTS) تعامل دارد، عنصر <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>