从深层链接中排除少数网址

时间:2014-11-28 08:24:26

标签: android deep-linking

我可以在我的Manifest中的intent-filter中使用以下过滤器成功实现app的深层链接:

   <data  android:host="myhost.com"
    android:pathPrefix="/v"
    android:scheme="http" />

EG。我的网址是:

 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明确指定所有网址?如果是这样,如何处理查询参数的值?

4 个答案:

答案 0 :(得分:7)

很遗憾,我们无法排除任何特定网址,因为Android并未提供该选项。

最佳做法是尽可能作为精确路径前缀

只指定没有任何pathPrefix的主机,只要应用程序执行的所有操作都有意义。但是,如果有任何链接应该在应用程序无法处理时执行某些特定操作,那么它应该让Web服务正确处理它。在这种情况下,如果您的Web服务可以比您的应用程序做得更多,那么将所有内容列入白名单并不是一个好主意。

有些人喜欢只在清单中匹配主机,然后在代码中处理不同的情况。你永远不会知道可以捕获到什么意外的网址,如果它真的能让感官处理它,那么其他的就是&#34;条件。更好,仔细,只列出我们确定的pathPrefix。

回到你的情况,大多数时候,我相信应用程序能够处理url,如果它只在查询参数中有所不同。因为它属于同一个动作(通过API的路由处理程序),所以只有不同的结果。只有当整个路由不同时,您才应该通过给出正确的路径前缀来区别对待它。

所以有效的例子可能是:

// 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,那就是App Indexing,而不是深层链接排除。

答案 1 :(得分:4)

您可以让应用决定是否让浏览器处理网址

@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。

答案 2 :(得分:1)

我通过在第二个意图中禁用深层链接来解决它

清单

<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);
}

答案 3 :(得分:0)

这项工作对我来说

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);
}