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

Android WebView ceding rel=活动管理器的外部链接,android,webview,android-webview,rel,webviewclient,Android,Webview,Android Webview,Rel,Webviewclient,我有一个WebView,其中我希望在Android浏览器中打开带有rel=external的锚定标签,但所有其他链接保留在WebView中 因此,如果用户点击标记如下所示的链接,内容将加载到WebView: <a href="http://example.com/">Whatever</a> <a href="http://example.com/" rel="external">Whatever</a> @Override public bo

我有一个
WebView
,其中我希望在Android浏览器中打开带有
rel=external
的锚定标签,但所有其他链接保留在
WebView

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

<a href="http://example.com/">Whatever</a>
<a href="http://example.com/" rel="external">Whatever</a>
@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;
}
public class JavaScriptInterface {
    public void viewExternalUrl(String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent);
        return true;
    }
}
确定是否存在
rel=external
属性/值的最佳方法是以某种方式使用
addJavascriptInterface()
,并让JavaScript通知Java是否存在
rel
属性以及值是什么

还是有更好的办法


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

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

myappname://external?url=encoded_real_page_url


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

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

myappname://external?url=encoded_real_page_url


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

如果您可以控制服务器端内容,那么一定要按照Theo提出的建议去做。由于您指示页面也应在标准浏览器中加载,因此不要使用自定义方案,而是使
rel=external
成为您链接/重定向到的实际url的一部分

通过这样做,您可以轻松解析
shouldOverrideUrlLoading(WebView视图,字符串url)
中的
url
参数,并检查上述键/值对。我建议您将其解析为,并使用检查值是否匹配
rel
。如果是
外部的
,则触发一个意图

它看起来像这样:

<a href="http://example.com/">Whatever</a>
<a href="http://example.com/" rel="external">Whatever</a>
@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;
}
public class JavaScriptInterface {
    public void viewExternalUrl(String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent);
        return true;
    }
}
另请注意:无需声明'else',因为您已经从'if'中的方法返回


如果用户可以使用您的WebView访问任何站点,如果您对其他站点应用相同的密钥/值对的目的心存疑虑,您可以轻松地添加另一项检查,以确定url是否位于“您的”域中。

如果您可以控制服务器端内容,那么一定要采纳Theo提出的建议。由于您指示页面也应在标准浏览器中加载,因此不要使用自定义方案,而是使
rel=external
成为您链接/重定向到的实际url的一部分

通过这样做,您可以轻松解析
shouldOverrideUrlLoading(WebView视图,字符串url)
中的
url
参数,并检查上述键/值对。我建议您将其解析为,并使用检查值是否匹配
rel
。如果是
外部的
,则触发一个意图

它看起来像这样:

<a href="http://example.com/">Whatever</a>
<a href="http://example.com/" rel="external">Whatever</a>
@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;
}
public class JavaScriptInterface {
    public void viewExternalUrl(String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent);
        return true;
    }
}
另请注意:无需声明'else',因为您已经从'if'中的方法返回


如果用户可以使用您的WebView访问任何站点,并且您对其他站点应用相同的密钥/值对的目的心存疑虑,那么您可以轻松添加另一项检查,以确定url是否位于“您的”域中。

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

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

<a href="http://example.com/">Whatever</a>
<a href="http://example.com/" rel="external">Whatever</a>
@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;
}
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)。您可以通过创建自定义和重写来检测页面加载完成

我还没有测试过这些代码,但它应该可以工作,假设您在页面中加载了JQuery。如果没有,您可能会想出一些JavaScript来操作DOM而不使用它,或者您可以在加载JavaScript之前先使用loadUrl手动加载JQuery


请注意,这种方法完全放弃了任何使用
shouldOverrideUrlLoading

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

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

<a href="http://example.com/">Whatever</a>
<a href="http://example.com/" rel="external">Whatever</a>
@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;
}
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)。您可以通过创建自定义和重写来检测页面加载完成

我还没有测试过这些代码,但它应该可以工作,假设您在页面中加载了JQuery。如果没有,您可能会想出一些JavaScript来操作DOM而不使用它,或者您可以在加载JavaScript之前先使用loadUrl手动加载JQuery


请注意,这种方法完全放弃了使用
shouldOverrideUrlLoading

我在WebView中查看的页面也需要通过标准浏览器查看,因此如果我这样做,我需要解决这个问题。也许我可以让我的应用程序在加载页面时将JavaScript注入每个页面,然后用自定义方案重写URL。如果没有,那么也许我可以尝试处理