简体   繁体   English

Android WebView WebChromeClient:onProgressChanged() 中的进度值不准确

[英]Android WebView WebChromeClient : inaccurate progress value in onProgressChanged()

I need to access the progress value in WebView -> WebChromeClient -> onProgressChanged().我需要访问 WebView -> WebChromeClient -> onProgressChanged() 中的进度值。 The progress integer value doesn't increment from 0 to 100 but rather jumps around.进度整数值不会从 0 增加到 100,而是四处跳跃。 Here is a sample log-output from loading one page and the associated progress numbers:这是加载页面和相关进度数字的示例日志输出:

DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 37
DEBUG:  progress : 45
DEBUG:  progress : 48
DEBUG:  progress : 49
DEBUG:  progress : 50
DEBUG:  progress : 52
DEBUG:  progress : 54
DEBUG:  progress : 56
DEBUG:  progress : 59
DEBUG:  progress : 61
DEBUG:  progress : 63
DEBUG:  progress : 66
DEBUG:  progress : 68
DEBUG:  progress : 70
DEBUG:  progress : 73
DEBUG:  progress : 75
DEBUG:  progress : 77
DEBUG:  progress : 79
DEBUG:  progress : 82
DEBUG:  progress : 84
DEBUG:  progress : 86
DEBUG:  progress : 87
DEBUG:  progress : 88
DEBUG:  progress : 89
DEBUG:  progress : 100

What am I doing wrong?我究竟做错了什么?

Code:代码:

webView.setWebChromeClient(new WebChromeClient() {
    public void onProgressChanged(WebView view, int progress) {
        Log.i(LOG_TAG, "DEBUG: progress : " + progress);
    }
});

From my own experiments, I found that onProgressChanged can get called multiple times for the same url for the same progress value (Ex: google.com progress = 100 calls twice).从我自己的实验中,我发现 onProgressChanged 可以为相同的 url 被多次调用以获得相同的进度值(例如:google.com progress = 100 调用两次)。

I also found that onProgressChanged will be called late for a url while you are loading another one.我还发现当您加载另一个 url 时,onProgressChanged 将被延迟调用。 Timetable example:时间表示例:

  1. Load google.com加载 google.com
  2. ProgressChanged = 100, webView.geturl(): google.com ProgressChanged = 100, webView.geturl(): google.com
  3. Load amazon.com加载 amazon.com
  4. ProgressChanged = 40, webView.getUrl(): amazon.com ProgressChanged = 40, webView.getUrl(): amazon.com
  5. ProgressChanged = 100, webView.getUrl(): google.com ProgressChanged = 100, webView.getUrl(): google.com

At this point, I should mention that in my experiments I override shouldOverrideUrlLoading() to see redirects and even when I don't see redirects the above still happens.在这一点上,我应该提到,在我的实验中,我覆盖了 shouldOverrideUrlLoading() 以查看重定向,即使我没有看到重定向,上述情况仍然会发生。 So why does this happen?那么为什么会发生这种情况呢?

According to this answer( Why is there a noticeable delay between WebChromeClient.onProgressChanged and jquery's $(document).ready() callbacks? ): because a page is loaded before the script are triggered, document ready looks for all html elements to be loaded first except images and things like that, so your script does not fire until everything has been loaded, by that time your onprogresschanged has received 100% first as it may be have a higher priority than your javascript after all devices do ask to check if js should be allowed or not so it has to go through some checks before this method is called.根据这个答案( 为什么 WebChromeClient.onProgressChanged 和 jquery 的 $(document).ready() 回调之间有明显的延迟? ):因为在触发脚本之前加载了页面,文档就绪会查找要加载的所有 html 元素首先除了图像和类似的东西,所以你的脚本在所有东西都被加载之前不会触发,到那个时候你的 onprogresschanged 已经首先收到 100% 因为它可能比你的 javascript 具有更高的优先级,因为它可能比你的 javascript 有更高的优先级,因为所有设备都要求检查 js应该允许与否,因此在调用此方法之前必须经过一些检查。

So to put it all together this is what you need to do:因此,要将所有这些放在一起,您需要执行以下操作:

  1. Don't trust onProgressChanged().不要相信 onProgressChanged()。
  2. onPageStarted() check that the current url you are trying to load matches webView.getUrl(). onPageStarted() 检查您尝试加载的当前 url 是否与 webView.getUrl() 匹配。 This is your starting point.这是你的起点。 Set a boolean finishedLoading to false.将布尔值finishedLoading 设置为false。
  3. Assume your page is loaded when onPageFinished is called and webView.getUrl() matches the url you are trying to load.假设您的页面在调用 onPageFinished 时加载,并且 webView.getUrl() 与您尝试加载的 url 匹配。 If no redirects, then set finishedLoading flag to true.如果没有重定向,则将finishedLoading 标志设置为true。 However, for redirects, you will need to follow step 3.但是,对于重定向,您需要执行第 3 步。
  4. override shouldOverrideurlLoading().覆盖 shouldOverrideurlLoading()。 Load the new url if it doesn't match the one that was originally loaded (webView.loadUrl(new redirect url)) and set finishedLoading to false.如果新 url 与最初加载的 url 不匹配,则加载新 url (webView.loadUrl(new redirect url)) 并将 finishedLoading 设置为 false。

Code代码

    private boolean isCurrentUrl(String url){
        return url.toLowerCase().contains(currentUrl.toLowerCase());
    }

   public void onPageStarted(WebView webView, String url,     
       android.graphics.Bitmap bitmap){

                if (isCurrentUrl(url)){
                    pageLoaded = false;
                }
   }

   public void onPageFinished(WebView webview, String url){
       if (isCurrentUrl(url)){
           pageLoaded = true;
       }
   }

   public boolean shouldOverrideUrlLoading(WebView view, String 
       url){
       if (!currentUrl.equalsIgnoreCase(url)){
           currentUrl = url;
           view.loadUrl(currentUrl);
           return true;
       }
       return false;
   }

正如@ksasq 在上述评论中指出的那样,初始 URL 导致了多次重定向,因此 onProgressChanged() 被多次调用。

Best solution is to use the progress of webview and not progress(integer value from method onProgressChanged(WebView view, int progress))最好的解决方案是使用 webview 的进度而不是进度(来自方法 onProgressChanged(WebView view, int progress) 的整数值)

psuedo code,伪代码,

@Override
public void onProgressChanged(WebView view, int progress) {
       progressBar.setProgress(yourWebView.getProgress());
}

This solution works fine in all cases!此解决方案适用于所有情况!

There are two progress of webView. webView有两个进度。 webView.getProgress() gives more accurate progress including progress of media files. webView.getProgress()提供更准确的进度,包括媒体文件的进度。 onProgressChanged() progress gives relative progress according to visibility of the page. onProgressChanged()进度根据页面的可见性给出相对进度。 Below code works fine for me.下面的代码对我来说很好用。 Here I am using my custom webView.在这里我使用我的自定义 webView。

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import com.xyz.interfaces.WebViewLoadingProgressListener


class MyWebView : WebView {

    private var webViewLoadingProgressListener: WebViewLoadingProgressListener? = null

    /**
     * to avoid webView progress inconsistency
     * and to get progress in incremental order
     */
    private var loadProgressCounter: Int? = null

    constructor(context: Context) : super(context) {
        initView(context)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        initView(context)
    }

    fun setWebViewLoadingProgressListener(webViewLoadingProgressListener: WebViewLoadingProgressListener) {
        this.webViewLoadingProgressListener = webViewLoadingProgressListener
    }

    var totalContentHeight = 0

    private fun initView(context: Context) {
        this.settings.javaScriptEnabled = true
        this.settings.domStorageEnabled = true
        this.settings.setAppCacheEnabled(true)
        this.settings.loadsImagesAutomatically = true
        this.settings.loadWithOverviewMode = true
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }


        this.webViewClient = object : WebViewClient() {
            /**
             * to restrict use of external browsing
             */
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                view?.loadUrl(url)
                /**
                 * resetting on page change
                 */
                loadProgressCounter = null
                return true
            }
        }

        this.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                /**
                 * use webView.getProgress() for more precise progress
                 */

                /**
                 * allowing incremental progress only
                 */
                if (loadProgressCounter == null || loadProgressCounter!! <= newProgress) {
                    loadProgressCounter = newProgress
                }
                /**
                 * sends progress to required class
                 */
                webViewLoadingProgressListener?.onProgressChange(loadProgressCounter!!)
            }
        }
    }


} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WebChromeClient onProgressChanged事件发生错误 - error at WebChromeClient onProgressChanged event WebChromeClient的onShowFileChooser无法与android studio中的webview一起使用 - WebChromeClient's onShowFileChooser not working with webview in android studio 从未触发Android WebChromeClient WebView onGeolocationPermissionsShowPrompt - Android WebChromeClient WebView onGeolocationPermissionsShowPrompt never fired Android WebView WebChromeClient 示例应用程序问题 - Android WebView WebChromeClient example app issue Cordova WebView比Android WebChromeClient慢 - Cordova WebView slower than Android WebChromeClient Android seekbar触发onProgressChanged时显示进度的简便方法 - Android seekbar easy way to display the progress when onProgressChanged is triggered WebView onProgressChanged()未调用 - WebView onProgressChanged() not called Android webview:未定义类型new WebChromeClient(){}的方法setProgress(int) - Android webview: The method setProgress(int) is undefined for the type new WebChromeClient(){} 无法使用WebChromeClient在WebView Android 4.4.2中打开文件选择器 - can't open file chooser in WebView Android 4.4.2 using WebChromeClient Android webview SKIPS javascript甚至包含setJavascriptEnabled(true)和WebChromeClient - Android webview SKIPS javascript even with setJavascriptEnabled(true) and WebChromeClient
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM