根据用例配置软件包可见性

本文档举例说明了应用与其他应用进行交互的一些常见用例。每个部分都会介绍如何针对其他已安装应用管理软件包可见性,如果您的应用以 Android 11(API 级别 30)或更高版本为目标平台,则需要考虑这个问题。

当您的应用以 Android 11 或更高版本为目标平台并使用 intent 在其他应用中启动 activity 时,最简单的方式是调用 intent,并在没有可用的应用时处理 ActivityNotFoundException 异常。

如果应用的部分功能需要知道对 startActivity() 的调用是否可以成功(例如显示界面),请向应用清单的 <queries> 元素添加一个元素。通常,此新元素是一个 <intent> 元素。

打开网址

本部分介绍如何在以 Android 11 或更高版本为目标平台的应用中打开网址。根据应用打开网址的方式,按照以下各子部分中的对应示例进行操作。

在浏览器或其他应用中打开网址

如需打开网址,请使用包含 ACTION_VIEW intent 操作的 intent,操作说明请参阅有关如何加载网址部分。使用此 intent 调用 startActivity() 后,会发生以下一种情况:

  • 网址在网络浏览器应用中打开。
  • 网址在支持该网址作为深层链接的应用中打开。
  • 系统显示一个消除歧义对话框,供用户选择使用哪个应用打开网址。
  • 因为设备上未安装任何可打开网址的应用而发生 ActivityNotFoundException。(这种情况不常见。)

    建议让应用在发生 ActivityNotFoundException 时捕获并处理此异常。

由于 startActivity() 方法不受系统软件包可见性行为的影响,因此您无需将 <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() 并将网络 intent 作为参数传递时,在某些情况下,返回的列表就会包含可用的浏览器应用。如果用户将网址配置为默认在非浏览器应用中打开,此列表将不包含浏览器应用。

在自定义标签页中打开网址

使用自定义标签页,应用就可以自定义浏览器的外观和风格。您可以在自定义标签页中打开网址,而无需在应用清单中添加或更改 <queries> 元素。

不过,您可能需要检查设备是否有支持自定义标签页的浏览器,或者使用 CustomTabsClient.getPackageName() 选择要通过自定义标签页启动的特定浏览器。在此类情况下,请在清单中将以下 <intent> 元素添加为 <queries> 元素的一部分:

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

注意:如果清单中已经包含有关如何检查是否有可用浏览器部分中所示的 <intent> 元素,那么上述代码段中所示的 <intent> 元素就并非必不可少了。

让非浏览器应用处理网址

即使您的应用可以使用自定义标签页打开网址,我们仍建议您尽可能允许一款非浏览器应用打开给定网址。如需在您的应用中提供此功能,请尝试使用一个用于设置 FLAG_ACTIVITY_REQUIRE_NON_BROWSER intent 标记的 intent 来调用 startActivity()。如果系统抛出 ActivityNotFoundException,您的应用就可以在自定义标签页中打开网址。

如果 intent 包含此标记,在发生以下任一种情况时,调用 startActivity() 都会导致抛出 ActivityNotFoundException

  • 此调用会直接启动一款浏览器应用。
  • 此调用会向用户显示一个消除歧义对话框,其中只提供了浏览器应用作为选项。

以下代码段展示了如何更新逻辑来使用 FLAG_ACTIVITY_REQUIRE_NON_BROWSER intent 标记:

KotlinJava

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 intent 标记的 intent。

如果 intent 包含此标记,调用 startActivity() 会导致在该调用本应向用户显示消除歧义对话框时系统抛出 ActivityNotFoundException

如果 intent 同时包含此标记和 FLAG_ACTIVITY_REQUIRE_NON_BROWSER intent 标记,在发生以下任一种情况时,调用 startActivity() 都会导致抛出 ActivityNotFoundException

  • 此调用会直接启动浏览器应用。
  • 此调用会向用户显示消除歧义对话框。

以下代码段展示了如何将 FLAG_ACTIVITY_REQUIRE_NON_BROWSER 和 FLAG_ACTIVITY_REQUIRE_DEFAULT 标记配合使用:

KotlinJava

String url = URL_TO_LOAD;
try {
    // In order 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);
}

打开文件

如果应用需要处理文件或附件,例如需要检查设备能否打开给定文件,通常最简单的办法是尝试启动可以处理该文件的 Activity。为此,请使用包含 ACTION_VIEW intent 操作和代表特定文件的 URI 的 intent。如果设备上没有可用的应用,您的应用可捕获 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>

然后,您可以使用 intent 调用 resolveActivity() 来检查是否有可用应用。

授予对 URI 的访问权限

注意:此建议适用于所有应用,而不考虑以下因素:

  • 您应用的目标 SDK 版本。
  • 您的应用是否导出其 Content Provider。

为了使以 Android 11 或更高版本为目标平台的应用能够访问内容 URI,您应用的 intent 必须至少设置以下 intent 标记中的一个来声明 URI 访问权限FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION

在 Android 11 及更高版本中,接收 intent 的应用拥有 URI 访问权限后将具有以下功能:

  • 根据给定的 URI 权限针对内容 URI 代表的数据执行读取或写入操作。
  • 看到所含 Content Provider 与 URI 授权相匹配的应用。包含 Content Provider 的应用可能与发送 intent 的应用不同。

以下代码段演示了如何添加 URI 权限 intent 标记,以便另一个以 Android 11 或更高版本为目标平台的应用可以查看内容 URI 中的数据:

KotlinJava

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

创建自定义共享表单

请尽可能使用系统提供的共享表单。或者,您也可以在清单中将以下 <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>

与之前的 Android 版本相比,在应用的逻辑中构建共享表单的过程(例如调用 queryIntentActivities())在其他方面保持不变。

显示自定义文字选择操作

当用户在您的应用中选择文字时,文字选择工具栏会显示一组可对选定文字执行的操作。如果此工具栏应显示来自其他应用的自定义操作,请在清单中将以下 <intent> 元素添加为 <queries> 元素的一部分:

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

连接到文字转语音引擎

如果应用需要与文字转语音 (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>

显示联系人的自定义数据行

应用可以向联系人提供程序添加自定义数据行。为了让“通讯录”应用显示此自定义数据,它需要能够执行以下操作:

  1. 从其他应用读取 contacts.xml 文件。
  2. 加载与自定义 MIME 类型相对应的图标。

如果您的应用是“通讯录”应用,请在清单中将以下 <intent> 元素添加为 <queries> 元素的一部分:

<!-- Place inside the <queries> element. -->
<!-- Allows the app to read the "contacts.xml" file from the other apps. -->
<intent>
  <action android:name="android.accounts.AccountAuthenticator" />
</intent>
<!-- Allows the app to 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>

在库中声明软件包可见性需求

如果您要开发 Android 库,您可以通过在 AAR 清单文件中添加 <queries> 元素来声明软件包可见性需求。此 <queries> 元素与应用可在自己的清单中声明的元素功能相同。

如果您的库涉及与“托管”应用通信(例如使用绑定服务),请添加用于指定托管应用的软件包名称的 <package> 元素:

<!-- Place inside the <queries> element. -->
<package android:name=PACKAGE_NAME />

通过添加此声明,您可以检查是否已安装托管应用并与之交互,例如通过调用 bindService() 来完成。此交互的结果是,使用您的库的调用方应用会自动对托管应用可见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值