从深度链接中排除几个 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的主要内容,如果未能解决你的问题,请参考以下文章

如何简单快速地实现深度链接?

从 nivo 灯箱中排除链接

无法在 IOS 应用程序的 detox 中使用深度链接 url 启动应用程序

Android 中的深度链接和向上导航

Xcode 9.3 使用 URL 方案(深度链接)调用时构建崩溃 [重复]

需要使用 grok 从日志中排除几个词