[英]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:
时间表示例:
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:因此,要将所有这些放在一起,您需要执行以下操作:
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.