Javascript 覆盖重定向无法在 Android WebView 上正确显示

问题描述 投票:0回答:1

我正在尝试基于

WebView
实现自定义浏览器。它在大多数网站上运行良好,但在 https://smittenkitchen.com/ 上我可能遗漏了一些关键的东西:

它可以很好地加载和显示主页,但是当输入搜索词(例如“carrot”)时,它首先登陆一个丑陋的“搜索表单”页面,然后显示一个空白覆盖! (在 Logcat 中没有覆盖显示/重定向的痕迹!

在任何标准的网络浏览器上,它首先登陆那个丑陋的“搜索表单”页面,然后在 0.5-2 秒后显示一个覆盖层,搜索结果逐渐被填充。

我试图了解我在实施中遗漏了什么:

在 MyWebViewClient 中,我覆盖:

  • onPageStarted
  • 页面完成
  • shouldOverrideUrlLoading
  • onPageCommitVisible

但是,前 3 种方法(

onPageStarted
onPageFinished
shouldOverrideUrlLoading
)仅在调用时记录 Logcat 消息,它们不会执行任何自定义操作。

做一些自定义的唯一重写方法 (

onPageCommitVisible
) 只调用 WebView 的
loadUrl()

javascript:window.HTMLOUT.processHTML(document.getElementsByTagName('html')[0].innerHTML)

促成:

webView.addJavascriptInterface(new MyJavascriptInterface(this, webView), "HTMLOUT");

请注意,

shouldOverrideUrlLoading
永远不会被 Android WebView 框架调用,尽管有明显的重定向(可能是因为它是客户端重定向,而不是更改 URL?)

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
    Log.d("", "url: " + url + ", view: " + view.getUrl());
}
@Override
public void onPageFinished(WebView view, String url) {
    Log.d("", "url: " + url + ", view: " + view.getUrl());
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest webResourceRequest) {
    Log.d("", "webResourceRequest: " + webResourceRequest.getUrl() + ", view: " + view.getUrl());
    return false;
}
@Override
public void onPageCommitVisible(WebView view, String url) {
    super.onPageCommitVisible(view, url);
    view.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByTagName('html')[0].innerHTML)"); // convert all javascript to HTML
    Log.v("", "url (passed): " + url + " < view.getUrl(): " + view.getUrl());
}

Javascript当然是启用的:

webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
webSettings.setBlockNetworkLoads(false);
webSettings.setDomStorageEnabled(true);

webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(false);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);

相关的Logcat代码片段如下:

11:12:03.716                           D   url: https://smittenkitchen.com/, view: https://smittenkitchen.com/ (called from: MyWebViewClient.onPageFinished) 
11:12:03.988                           D   url: https://smittenkitchen.com/, view: https://smittenkitchen.com/ (called from: MyWebViewClient.onPageStarted)
11:12:05.646                           E   net::ERR_CONNECTION_REFUSED(-6) on request: https://ssc.33across.com/api/v1/hb?guid=cYCh20L9Or64olaKj0P0Le, https://smittenkitchen.com/ (called from: MyWebViewClient.onReceivedError)
11:12:05.787  MyWebView                V   javascript:window.HTMLOUT.processHTML(document.getElementsByTagName('html')[0].innerHTML); (called from: MyWebView.loadUrl < MyWebViewClient.onPageCommitVisible)
11:12:05.790  MyWebViewClient          V   url (passed): https://smittenkitchen.com/ < view.getUrl(): https://smittenkitchen.com/ (called from: MyWebViewClient.onPageCommitVisible)
11:12:08.097                           D   url: https://smittenkitchen.com/, view: https://smittenkitchen.com/ (called from: MyWebViewClient.onPageFinished)
11:12:23.824                           D   url: https://smittenkitchen.com/?s=carrot, view: https://smittenkitchen.com/?s=carrot (called from: MyWebViewClient.onPageStarted)
11:12:24.083  MyWebView                V   javascript:window.HTMLOUT.processHTML(document.getElementsByTagName('html')[0].innerHTML); (called from: MyWebView.loadUrl < MyWebViewClient.onPageCommitVisible)
11:12:24.085  MyWebViewClient          V   url (passed): https://smittenkitchen.com/?s=carrot < view.getUrl(): https://smittenkitchen.com/?s=carrot (called from: MyWebViewClient.onPageCommitVisible)
11:12:25.176                           E   net::ERR_CONNECTION_REFUSED(-6) on request: https://ssc.33across.com/api/v1/hb?guid=cYCh20L9Or64olaKj0P0Le, https://smittenkitchen.com/?s=carrot (called from: MyWebViewClient.onReceivedError)
11:12:26.583                           D   url: https://smittenkitchen.com/?s=carrot, view: https://smittenkitchen.com/?s=carrot (called from: MyWebViewClient.onPageFinished)

知道我在实现中可能会遗漏什么,以便我的基于 WebView 的浏览器像 Chrome 一样显示覆盖吗?

javascript android html webview android-webview
1个回答
0
投票

我认为这个问题可能与页面加载时间和 JavaScript 执行有关。

在您的

MyWebViewClient
实施中,您仅捕获初始页面加载,而不捕获搜索结果的后续动态加载。要正确捕获此类动态负载,您可以选择在您的
shouldInterceptRequest
中实施
WebViewClient
方法。

这样你就可以拦截 WebView 发出的请求并在加载之前修改它们。

还有

onPageCommitVisible
方法被用来执行JavaScript代码,但它可能在页面完全加载之前被调用。这可能会导致 JavaScript 代码在不完整或不正确的页面状态下执行,从而导致意外行为。

为确保您的代码仅在页面完全加载时执行,您可以将 JavaScript 执行移至

onPageFinished
方法。页面加载完成后将调用该方法。

这是包含新修改的

MyWebViewClient
类的示例:

public class MyWebViewClient extends WebViewClient {
    private Context context;
    private WebView webView;

    public MyWebViewClient(Context context, WebView webView) {
        this.context = context;
        this.webView = webView;
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        Log.d("", "url: " + url + ", view: " + view.getUrl());
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        Log.d("", "url: " + url + ", view: " + view.getUrl());
        view.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByTagName('html')[0].innerHTML)");
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest webResourceRequest) {
        Log.d("", "webResourceRequest: " + webResourceRequest.getUrl() + ", view: " + view.getUrl());
        return false;
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        Log.e("", error.toString() + " on request: " + request.getUrl() + ", " + view.getUrl());
    }
}

请注意,

onReceivedError
方法也已更新为包括
super
调用,这是正确处理错误所必需的。

试试这个更新后的实现,看看它是否解决了叠加层未正确显示的问题。

© www.soinside.com 2019 - 2024. All rights reserved.