WebView ceding rel =活动管理器的外部链接

时间:2012-01-08 20:38:11

标签: android webview android-webview rel webviewclient

我有一个WebView我希望锚点标记rel=external在Android浏览器中打开,但所有其他链接都留在WebView

因此,如果用户点击标记如下所示的链接,内容将在WebView内加载:

<a href="http://example.com/">Whatever</a>

但是,如果用户点击标记如下所示的链接,则内容将在Android浏览器中加载:

<a href="http://example.com/" rel="external">Whatever</a>

这是WebViewClient代码中的相关代码(带有注释的一位伪代码):

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (! rel=external) {   //  <-- That condition...how do I do that?
        view.loadUrl(url);
        return false;
    } else {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent);
        return true;
    }

确定是否存在rel=external属性/值的最佳方法是以某种方式使用addJavascriptInterface()并让JavaScript通知Java是否存在rel属性以及价值是?

还是有更好的方法吗?

(我正在寻找一种不涉及检查URL域名的解决方案,因为有任意数量的域需要被视为内部域,我无法提前知道或在运行中轻松确定。)

3 个答案:

答案 0 :(得分:2)

如果您不想修改现有网址,我认为原始建议的变体可能是最好的。

使用addJavaScriptInterface添加一个类来处理外部网址加载。内部类可能如下所示:

public class JavaScriptInterface {
    public void viewExternalUrl(String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent);
        return true;
    }
}

当然要加上它:

webView.addJavascriptInterface(new JavaScriptInterface(), "Android");

通过loadUrl注入JavaScript以添加点击处理程序以在加载页面后调用JavaScript界面​​(为简单起见使用JQuery)。您可以通过创建自定义WebViewClient并覆盖onPageFinished来检测网页加载完成情况。

webView.setWebViewClient(new WebViewClient() {
    private static final String sJs = "javascript:" +
        Uri.encode("$('a[@rel$='external']').click(function(){ Android.viewExternalUrl($(this).attr('href')); });");

    @Override
    public void onPageFinished(WebView view, String url) {
        webView.loadUrl(sJs);
    }
}

我没有测试过这些代码,但它应该可以工作,假设你在页面中加载了JQuery。如果没有,您可以在没有它的情况下提出一些JavaScript来操作DOM,或者您可以在加载JavaScript之前使用loadUrl手动加载JQuery。

请注意,此方法完全放弃使用shouldOverrideUrlLoading

答案 1 :(得分:1)

我的建议是使用一种不同的方式来指定外部URL ...一种将该信息嵌入到URL中,因此与shouldOverrideUrlLoading函数兼容。具体来说,创建自定义方案URL并将实际页面作为参数传递:

myappname://外部URL = encoded_real_page_url

然后在shouldOverrideUrlLoading函数中检查它是否是自定义方案URL,提取url参数,解码然后重定向。

答案 2 :(得分:1)

如果您可以控制服务器端内容,那么请务必遵循Theo的建议。由于您指示页面也应加载标准浏览器,因此请不要使用自定义方案,而是将rel=external部分用于链接/重定向到的实际网址。

通过这样做,您可以轻松解析url中的shouldOverrideUrlLoading(WebView view, String url)参数,并检查上面的键/值对。我建议您将其解析为Uri并使用getQueryParameter(key)检查匹配rel的值。如果它是external,则触发意图。

它看起来像这样:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    Uri uri = Uri.parse(url);
    String relValue = uri.getQueryParameter("rel");    
    if (relValue != null && !relValue.equals("external")) {
        view.loadUrl(url);
        return false;
    }
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(uri);
    startActivity(intent);
    return true;
}

旁注:不需要声明'else',因为你已经从'if'中的方法返回。

如果用户可以使用您的WebView访问任何网站,并且如果您对其他应用相同键/值对的网站感到偏执,则可以轻松添加其他检查以确定该网址是否位于“您的”域中