目录
问题
实现
排查思路
知识拓展
包可见性
scheme
targetsdkVersion
App A的Activity A通过scheme跳转至App B的Activity B,跳转失败。
1. App A和App B约定scheme。App A跳转代码如下:
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("appb://targetactivity/web?url=XXX"));
//发出 Intent 之前必须通过 resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_
ONLY) != null) {
mContext.startActivityForResult(intent, 0);
}else {
// 找不到指定的 Activity
}
2. 在App B承接的Activity中注册intent-filter。App B承接代码如下:
<activity android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="targetactivity"
android:scheme="appb" />
</intent-filter>
</activity>
上述代码在相关机型上未跳转成功,测试数款机型,发现只有android11及以上机型存在问题,故而怀疑是android11的隐私权和安全性更严格导致的。
查阅官网Android 11 中的软件包可见性和管理软件包可见性,我们发现:如果您的应用以 Android 11(API 级别 30)或更高版本为目标平台,并且需要与应用(自动可见的应用除外)交互,请在您应用的清单文件中添加 <queries> 元素。
换而言之,当你不加<queries> 元素 ,targetSDKVersion为30及以上且手机是android11及以上是无法跳转的。
App A中注册以下代码即可解决。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.XXX.myapp">
<uses-permission android:name="android.permission.INTERNET" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW"/>
<data
android:host = "targetactivity"
android:scheme = "appb"/>
</intent>
</queries>
<application
<!--XXXX-->
</application>
</manifest>
Android 11 更改了应用查询用户已在设备上安装的其他应用以及与之交互的方式。使用<queries> 元素,应用可以定义一组自身可访问的其他软件包。通过告知系统应向您的应用显示哪些其他软件包,此元素有助于鼓励最小权限原则。参考:Android 11 中的软件包可见性和管理软件包可见性。
一个完整的完整的URL Scheme协议格式由scheme、host、port、path和query组成,其结构如下所示:
<scheme>://<host>:<port>/<path>?<query>
scheme可以是常见的协议名 (http、file等)也可以是自定义的协议名(自定义一个字符串即可),一般打开一个APP,大多使用自定义的协议名。参考:Android URL Scheme。
Android 会随新版本的推出而逐渐发展,在此过程中,某些行为乃至外观可能会发生变化。不过,如果平台的 API 级别高于应用 targetSdkVersion 所声明的版本,系统便可通过启用兼容性行为,确保应用继续以您所期望的方式工作。您可以将 targetSdkVersion 指定为符合应用所运行平台的 API 级别,从而停用此类兼容性行为。参考:<uses-sdk>。
|