【问题标题】:Exclude few Urls from deeplinking从深度链接中排除几个 URL
【发布时间】: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 明确指定所有网址?如果是,如何处理查询参数的值?

【问题讨论】:

    标签: android deep-linking


    【解决方案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://stackoverflow.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://stackoverflow.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);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-16
      • 1970-01-01
      相关资源
      最近更新 更多