因为项目需要实装了applinks,在代码中使用Intent打开符合applinks规则的链接时,会自动回到app,而不是使用浏览器打开。这是因为在AndroidMainifest.xml文件中声明了data符合该链接的intent-filter,所以使用Intent方式打开该uri时会自动回到app。
那该怎么避免呢?我们可以找到手机上可以打开"https://…"的某应用A。然后intent.setPackage(A)来指定用A应用打开该uri。
直接上代码:
public static void openUrlOnlyInBrowser(String uri, Context context) {
try {
// 随便指定一个https链接
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"));
PackageManager packageManager = context.getPackageManager();
final ResolveInfo resolveInfo;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 请注意:在安卓13及以上需要使用该方法来找到可处理该intent的应用,因为resolveActivity(@NonNull Intent intent, int flags)方法在安卓13sdk中已被标为@Deprecated,需要使用resolveActivity(@NonNull Intent intent, @NonNull ResolveInfoFlags flags)来代替。flag设为MATCH_DEFAULT_ONLY,代表只有支持 Intent.CATEGORY_DEFAULT 的过滤器才会被考虑进行匹配。
resolveInfo = packageManager.resolveActivity(browserIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
} else {
// 安卓12及以下仍用resolveActivity(@NonNull Intent intent, int flags)来找到可处理该intent的应用。
resolveInfo = packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
}
// 请注意: 因为resolveActivity方法的返回值是@Nullable的,所以这里进行一下判空处理
if (resolveInfo != null) {
final String defaultPackageName = resolveInfo.activityInfo.packageName;
final Intent defaultBrowserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
// 指定处理该intent的应用
defaultBrowserIntent.setPackage(defaultPackageName);
try {
// 这里就实现了使用默认浏览器来打开该uri了
context.startActivity(defaultBrowserIntent);
return;
} catch (Exception e) {
e.printStackTrace();
}
}
// 一般来说MATCH_DEFAULT_ONLY应该就可以找到默认应用来打开intent了,但万一呢,于是使用MATCH_ALL(慎重使用)来找到可以处理该intent的所有应用们,然后遍历直到成功使用某应用打开该intent。
final List<ResolveInfo> resolveInfos;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
resolveInfos = packageManager.queryIntentActivities(browserIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_ALL));
} else {
resolveInfos = packageManager.queryIntentActivities(browserIntent, PackageManager.MATCH_ALL);
}
for(ResolveInfo info: resolveInfos) {
final String targetPackageName = info.activityInfo.packageName;
final Intent targetBrowserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
targetBrowserIntent.setPackage(targetPackageName);
try {
context.startActivity(targetBrowserIntent);
break;
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
最后,也是最最重要的是,在安卓11上新增了软件包可见性,所以我们直接使用上述代码可能访问不到处理该intent的应用。这个时候我们需要在AndroidManifest.xml中声明软件包可见性。
上代码:
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
这样就可以访问到可以处理scheme为https且action为android.intent.action.VIEW的其他应用啦。
如果能帮到为此烦恼的小伙伴们,就很nice了。 也欢迎大家指出该文章中的不足或不对之处~~。
Best Wishes!
参考:
https://blog.csdn.net/qq_41904106/article/details/127107271?spm=1001.2014.3001.5501
https://developer.android.google.cn/guide/topics/manifest/queries-element?hl=en#package