从深度链接中排除几个 URL
Posted
技术标签:
【中文标题】从深度链接中排除几个 URL【英文标题】:Exclude few Urls from deeplinking 【发布时间】:2015-01-26 20:55:56 【问题描述】:我可以在 Manifest 的意图过滤器中使用以下过滤器成功实现应用的深度链接:
<data android:host="myhost.com"
android:pathPrefix="/v"
android:scheme="http" />
例如。我的网址是:
http://myhost.com/v/login1.php?id=123&name=abc&type=a
http://myhost.com/v/login1.php?id=123&name=abc&type=b
我要排除
http://myhost.com/v/login1.php?id=123&name=abc&type=c
现在我想排除一些具有相同前缀的 URL。有可能还是我需要用 android:path
明确指定所有网址?如果是,如何处理查询参数的值?
【问题讨论】:
【参考方案1】:很遗憾,我们无法排除任何特定的网址,因为 Android 不提供该选项。
最佳做法是提供尽可能精确的 pathPrefix。
只要应用程序执行的所有操作都有意义,只指定没有任何路径前缀的主机是可以的。但是,如果有任何链接在应用程序无法处理时应该做一些特定的事情,那么它应该让 Web 服务正确处理它。在这种情况下,如果您的 Web 服务可以做的不仅仅是您的应用程序,那么将所有内容都列入白名单并不是一个好主意。
有些人喜欢只匹配清单中的主机,然后在代码中处理不同的情况。如果通过“else”条件处理它真的有意义,你永远不知道可以捕获什么意外的 url。更好的是,仔细做,只列出我们确定的pathPrefix。
回到你的例子,大多数时候,我相信如果只是查询参数不同,应用程序能够处理 url。因为它属于同一个动作(通过 API 的路由处理程序),只是结果不同。只有当整个路由不同时,才应该区别对待,给予正确的pathPrefix。
所以有效的例子可能是:
// To handle:
http://myhost.com/v/login1?id=123&name=abc&type=a
// To exclude:
http://myhost.com/v/login2?id=123&name=abc&type=a
然后在AndroidManifest.xml中:
<data android:scheme="http"
android:host="myhost.com"
android:pathPrefix="/v/login1" />
注意: 万一你偶然发现noindex.xml,那是用于应用索引,而不是用于深度链接排除。
【讨论】:
我尝试使用 android:pathPrefix="/v/" 处理 url myhost.com/v,但它不起作用。 用“/v”替换“/v/”怎么样? Nop :( 我要创建一个关于这个问题的新问题...【参考方案2】:您可以让应用决定是否让浏览器处理 URL
@Override
protected void onNewIntent(Intent intent)
if (intent.getData().getQueryParameter("type").equals("c"))
forwardToBrowser(intent);
else
handleIntent(intent);
;
// from https://***.com/a/23268821/3221253
private void forwardToBrowser(Intent i)
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(i.getData(), i.getType());
List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, 0);
ArrayList<Intent> targetIntents = new ArrayList<Intent>();
String thisPackageName = getApplicationContext().getPackageName();
for (ResolveInfo currentInfo : activities)
String packageName = currentInfo.activityInfo.packageName;
if (!thisPackageName.equals(packageName))
Intent targetIntent = new Intent(android.content.Intent.ACTION_VIEW);
targetIntent.setDataAndType(intent.getData(),intent.getType());
targetIntent.setPackage(intent.getPackage());
targetIntent.setComponent(new ComponentName(packageName, currentInfo.activityInfo.name));
targetIntents.add(targetIntent);
if(targetIntents.size() > 0)
Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), "Open with");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[] ));
startActivity(chooserIntent);
finish();
forwardToBrowser
(来自https://***.com/a/23268821/3221253)的这种实现允许用户选择一个浏览器(如果他们有多个浏览器)。如果您愿意,您可以简单地打开 Chrome。
【讨论】:
这不适用于 android 6。queryIntentActivities() 仅返回 1 个活动(我的应用)【参考方案3】:这对我有用
if(Build.VERSION.SDK_INT < 23)
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(i.getData(), i.getType());
List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, 0);
ArrayList<Intent> targetIntents = new ArrayList<Intent>();
String thisPackageName = getApplicationContext().getPackageName();
for (ResolveInfo currentInfo : activities)
String packageName = currentInfo.activityInfo.packageName;
if (!thisPackageName.equals(packageName))
Intent targetIntent = new Intent(android.content.Intent.ACTION_VIEW);
targetIntent.setDataAndType(intent.getData(), intent.getType());
targetIntent.setPackage(intent.getPackage());
targetIntent.setComponent(new ComponentName(packageName, currentInfo.activityInfo.name));
targetIntents.add(targetIntent);
if (targetIntents.size() > 0)
Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), "Open with");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]));
startActivity(chooserIntent);
finish();
// from SDK 23, queryIntentActivities only return your activity, so you need to disable you activity before forward to browser and enable it later.
else
final PackageManager pm = getPackageManager();
final ComponentName component = new ComponentName(this, HandleDeepLinkActivity.class);
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Intent webIntent = new Intent(Intent.ACTION_VIEW);
webIntent.setData(i.getData());
startActivity(webIntent);
Handler handler = new Handler();
handler.postDelayed(new Runnable()
@Override
public void run()
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
, 500);
【讨论】:
Android 默认不支持排除深层链接,因此您必须在活动中处理这些排除的 URL(转发到浏览器)【参考方案4】:我通过在第二个意图中禁用深度链接解决了这个问题
清单
<activity android:name=".Deeplinking">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:host="*.example.com" />
</intent-filter>
</activity>
在代码中,我可以理解是否希望浏览器/应用处理它,并在需要时触发新意图。
private void openInBrowser(String url)
setDeepLinkingState(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
setDeepLinkingState(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
private void setDeepLinkingState(int state)
ComponentName compName = new ComponentName(getPackageName(), getPackageName() + ".Deeplinking");
getApplicationContext().getPackageManager().setComponentEnabledSetting(
compName,
state,
PackageManager.DONT_KILL_APP);
【讨论】:
以上是关于从深度链接中排除几个 URL的主要内容,如果未能解决你的问题,请参考以下文章
无法在 IOS 应用程序的 detox 中使用深度链接 url 启动应用程序