Intereting Posts
Ошибка раздувания класса com.facebook.widget.LoginButton с Facebook SDK 4.0.1 База данных SQLite, многопоточность, блокировка и синхронизация учетной записи на android Использование сервисов игр Google Play в эмуляторе Ожидание открытия ящика навигации перед инициализацией Фрагменты с пустым циклом while Проблемы с подключением USB 6 Nexus 5 USB Как получить активность, запрошенную намерением Невозможно подключить отладчик к Jelly Bean Galaxy Nexus Создание базы данных веб-сервера для использования с Android-приложением События TextWatcher запускаются несколько раз Удаление левого дополнения на Android EditText Объект refrence не установлен в экземпляр объекта Когда я создаю новое приложение для Android (Visual Studio) Можете ли вы запустить событие, когда Android Dialog будет уволен? Как передать объект из одной активности в другую на Android? Изменение фона popupMenu в Android Попробуйте получить ответ USSD в android

Как прослушать завершение загрузки WebView URL?

У меня есть WebView который загружает страницу из Интернета. Я хочу показать ProgressBar пока загрузка не будет завершена.

Как прослушать завершение загрузки страницы WebView ?

Solutions Collecting From Web of "Как прослушать завершение загрузки WebView URL?"

Внедрение WebViewClient и расширение onPageFinished () следующим образом:

 mWebView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView view, String url) { // do your stuff here } }); 

@ian это не на 100% точно. Если на странице есть несколько фреймов, у вас будет несколько onPageFinished (и onPageStarted). И если у вас есть несколько перенаправлений, это может также потерпеть неудачу. Этот подход решает (почти) все проблемы:

 boolean loadingFinished = true; boolean redirect = false; mWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) { if (!loadingFinished) { redirect = true; } loadingFinished = false; webView.loadUrl(urlNewString); return true; } @Override public void onPageStarted(WebView view, String url) { loadingFinished = false; //SHOW LOADING IF IT ISNT ALREADY VISIBLE } @Override public void onPageFinished(WebView view, String url) { if(!redirect){ loadingFinished = true; } if(loadingFinished && !redirect){ //HIDE LOADING IT HAS FINISHED } else{ redirect = false; } } }); 

ОБНОВИТЬ:

Согласно документации: onPageStarted НЕ будет вызываться, когда изменяется содержимое встроенного фрейма, то есть нажатие ссылки, целью которой является iframe.

Я нашел конкретный случай, подобный этому в Твиттере, где вызывалась только страничная ссылка и немного путала логику. Чтобы решить эту проблему, я добавил запланированную задачу, чтобы удалить загрузку через X секунд. Это не требуется во всех других случаях.

ОБНОВЛЕНИЕ 2 :

Теперь с текущей реализацией Android WebView:

 boolean loadingFinished = true; boolean redirect = false; mWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading( WebView view, WebResourceRequest request) { if (!loadingFinished) { redirect = true; } loadingFinished = false; webView.loadUrl(request.getUrl().toString()); return true; } @Override public void onPageStarted( WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); loadingFinished = false; //SHOW LOADING IF IT ISNT ALREADY VISIBLE } @Override public void onPageFinished(WebView view, String url) { if(!redirect){ loadingFinished = true; } if(loadingFinished && !redirect){ //HIDE LOADING IT HAS FINISHED } else{ redirect = false; } } }); 

Я довольно частичен решению @NeTeInStEiN (и @polen), но реализовал бы его с помощью счетчика вместо нескольких булевых или государственных наблюдателей (просто еще один вкус, но я думал, что может поделиться). У него есть нюанс JS об этом, но я чувствую, что логику немного легче понять.

 private void setupWebViewClient() { webView.setWebViewClient(new WebViewClient() { private int running = 0; // Could be public if you want a timer to check. @Override public boolean shouldOverrideUrlLoading(WebView webView, String urlNewString) { running++; webView.loadUrl(urlNewString); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { running = Math.max(running, 1); // First request move it to 1. } @Override public void onPageFinished(WebView view, String url) { if(--running == 0) { // just "running--;" if you add a timer. // TODO: finished... if you want to fire a method. } } }); } 

Я упростил код NeTeInStEiN таким образом:

 mWebView.setWebViewClient(new WebViewClient() { private int webViewPreviousState; private final int PAGE_STARTED = 0x1; private final int PAGE_REDIRECTED = 0x2; @Override public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) { webViewPreviousState = PAGE_REDIRECTED; mWebView.loadUrl(urlNewString); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); webViewPreviousState = PAGE_STARTED; if (dialog == null || !dialog.isShowing()) dialog = ProgressDialog.show(WebViewActivity.this, "", getString(R.string.loadingMessege), true, true, new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // do something } }); } @Override public void onPageFinished(WebView view, String url) { if (webViewPreviousState == PAGE_STARTED) { dialog.dismiss(); dialog = null; } } }); 

Легко понять, OnPageFinished, если предыдущий обратный вызов включен onPageStarted, поэтому страница полностью загружена.

Если вы хотите показать индикатор выполнения, вам необходимо прослушать событие изменения прогресса, а не только для завершения страницы:

 mWebView.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { //change your progress bar } }); 

BTW, если вы хотите отображать только неопределенный прогрессBar, переопределяющий метод onPageFinished, достаточно

Используйте setWebViewClient () и переопределите onPageFinished ()

Я нашел одно элегантное решение, не испытал его строго:

 public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); if (m_webView.getProgress() == 100) { progressBar.setVisibility(View.GONE); m_webView.setVisibility(View.VISIBLE); } } 

Вы можете проследить Progress Staus методом getProgress в классе webview .

Инициализировать статус выполнения

 private int mProgressStatus = 0; 

Затем AsyncTask для загрузки следующим образом:

 private class Task_News_ArticleView extends AsyncTask<Void, Void, Void> { private final ProgressDialog dialog = new ProgressDialog( your_class.this); // can use UI thread here protected void onPreExecute() { this.dialog.setMessage("Loading..."); this.dialog.setCancelable(false); this.dialog.show(); } @Override protected Void doInBackground(Void... params) { try { while (mProgressStatus < 100) { mProgressStatus = webview.getProgress(); } } catch (Exception e) { } return null; } protected void onPostExecute(Void result) { if (this.dialog.isShowing()) { this.dialog.dismiss(); } } } 

Спасибо за ответы. Это помогло мне, но мне пришлось немного улучшить его для моих нужд. У меня было несколько pagestarts и финиширов, поэтому я добавил таймер, который проверяет, будет ли atfer на странице заканчивается новый pagestart. Хорошо, плохое объяснение. См. Код 🙂

 myWebView.setWebViewClient(new WebViewClient() { boolean loadingFinished = true; boolean redirect = false; long last_page_start; long now; // Load the url public boolean shouldOverrideUrlLoading(WebView view, String url) { if (!loadingFinished) { redirect = true; } loadingFinished = false; view.loadUrl(url); return false; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Log.i("p","pagestart"); loadingFinished = false; last_page_start = System.nanoTime(); show_splash(); } // When finish loading page public void onPageFinished(WebView view, String url) { Log.i("p","pagefinish"); if(!redirect){ loadingFinished = true; } //call remove_splash in 500 miSec if(loadingFinished && !redirect){ now = System.nanoTime(); new android.os.Handler().postDelayed( new Runnable() { public void run() { remove_splash(); } }, 500); } else{ redirect = false; } } private void show_splash() { if(myWebView.getVisibility() == View.VISIBLE) { myWebView.setVisibility(View.GONE); myWebView_splash.setVisibility(View.VISIBLE); } } //if a new "page start" was fired dont remove splash screen private void remove_splash() { if (last_page_start < now) { myWebView.setVisibility(View.VISIBLE); myWebView_splash.setVisibility(View.GONE); } } }); 

Загрузка URL с SwipeRefreshLayout и ProgressBar :

UrlPageActivity.java:

  WebView webView; SwipeRefreshLayout _swipe_procesbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_url_page); String url = "http://stackoverflow.com/"; _swipe_procesbar = (SwipeRefreshLayout)findViewById(R.id.url_path_swipe_procesbar); _swipe_procesbar.post(new Runnable() { @Override public void run() { _swipe_procesbar.setRefreshing(true); } } ); webView = (WebView) findViewById(R.id.url_page_web_view); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView view, String url) { _swipe_procesbar.setRefreshing(false); _swipe_procesbar.setEnabled(false); } }); webView.loadUrl(url); } 

activity_url_page.xml:

 <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/url_path_swipe_procesbar" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.test.test1.UrlPageActivity"> <WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/url_page_web_view" /> </RelativeLayout> </android.support.v4.widget.SwipeRefreshLayout> 

Вот метод, который позволяет зарегистрировать Runnable для выполнения после того, как определенный веб-адрес завершит загрузку. Мы связываем каждый Runnable с соответствующей String URL на Map , и мы используем WebView getOriginalUrl() для выбора соответствующего обратного вызова.

 package io.github.cawfree.webviewcallback; /** * Created by Alex Thomas (@Cawfree), 30/03/2017. **/ import android.net.http.SslError; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.SslErrorHandler; import android.webkit.WebView; import android.webkit.WebViewClient; import java.util.HashMap; import java.util.Map; /** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */ public class MainActivity extends AppCompatActivity { /* Member Variables. */ private WebView mWebView; private Map<String, Runnable> mCallbackMap; /** Create the Activity. */ @Override protected final void onCreate(final Bundle pSavedInstanceState) { // Initialize the parent definition. super.onCreate(pSavedInstanceState); // Set the Content View. this.setContentView(R.layout.activity_main); // Fetch the WebView. this.mWebView = (WebView)this.findViewById(R.id.webView); this.mCallbackMap = new HashMap<>(); // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.) this.getWebView().setWebViewClient(new WebViewClient() { /** Handle when a request has been launched. */ @Override public final void onPageFinished(final WebView pWebView, final String pUrl) { // Determine whether we're allowed to process the Runnable; if the page hadn't been redirected, or if we've finished redirection. if(pUrl.equals(pWebView.getOriginalUrl())) { // Fetch the Runnable for the OriginalUrl. final Runnable lRunnable = getCallbackMap().get(pWebView.getOriginalUrl()); // Is it valid? if(lRunnable != null) { lRunnable.run(); } } // Handle as usual. super.onPageFinished(pWebView, pUrl); } /** Ensure we handle SSL state properly. */ @Override public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); } }); // Assert that we wish to visit Zonal's website. this.getWebView().loadUrl("http://www.zonal.co.uk/"); // Align a Callback for Zonal; this will be serviced once the page has loaded. this.getCallbackMap().put("http://www.zonal.co.uk/", new Runnable() { @Override public void run() { /* Do something. */ } }); } /* Getters. */ public final WebView getWebView() { return this.mWebView; } private final Map<String, Runnable> getCallbackMap() { return this.mCallbackMap; } } 

Вот новый метод обнаружения, когда URL загружен, используя возможности Android для JavaScript-перехватчиков . Используя этот шаблон, мы используем знание JavaScript о состоянии документа для генерации вызова метода native в среде выполнения Android. Эти вызовы, доступные для JavaScript, могут быть сделаны с @JavaScriptInterface аннотации @JavaScriptInterface .

Эта реализация требует, чтобы мы вызывали setJavaScriptEnabled(true) в WebView , поэтому она может не подходить в зависимости от требований вашего приложения, например, от соображений безопасности.

Src / io / github / cawfree / webviewcallback / MainActivity.java (Jelly Bean, API-уровень 16)

 package io.github.cawfree.webviewcallback; /** * Created by Alex Thomas (@Cawfree), 30/03/2017. **/ import android.net.http.SslError; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.webkit.JavascriptInterface; import android.webkit.SslErrorHandler; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; /** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */ public class MainActivity extends AppCompatActivity { /* Static Declarations. */ private static final String HOOK_JS = "Android"; private static final String URL_TEST = "http://www.zonal.co.uk/"; private static final String URL_PREPARE_WEBVIEW = ""; /* Member Variables. */ private WebView mWebView = null; /** Create the Activity. */ @Override protected final void onCreate(final Bundle pSavedInstanceState) { // Initialize the parent definition. super.onCreate(pSavedInstanceState); // Set the Content View. this.setContentView(R.layout.activity_main); // Fetch the WebView. this.mWebView = (WebView)this.findViewById(R.id.webView); // Enable JavaScript. this.getWebView().getSettings().setJavaScriptEnabled(true); // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.) this.getWebView().setWebViewClient(new WebViewClient() { @Override public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); } }); // Define the WebView JavaScript hook. this.getWebView().addJavascriptInterface(this, MainActivity.HOOK_JS); // Make this initial call to prepare JavaScript execution. this.getWebView().loadUrl(MainActivity.URL_PREPARE_WEBVIEW); } /** When the Activity is Resumed. */ @Override protected final void onPostResume() { // Handle as usual. super.onPostResume(); // Load the URL as usual. this.getWebView().loadUrl(MainActivity.URL_TEST); // Use JavaScript to embed a hook to Android's MainActivity. (The onExportPageLoaded() function implements the callback, whilst we add some tests for the state of the WebPage so as to infer when to export the event.) this.getWebView().loadUrl("javascript:" + "function onExportPageLoaded() { " + MainActivity.HOOK_JS + ".onPageLoaded(); }" + "if(document.readyState === 'complete') { onExportPageLoaded(); } else { window.addEventListener('onload', function () { onExportPageLoaded(); }, false); }"); } /** Javascript-accessible callback for declaring when a page has loaded. */ @JavascriptInterface @SuppressWarnings("unused") public final void onPageLoaded() { // Display the Message. Toast.makeText(this, "Page has loaded!", Toast.LENGTH_SHORT).show(); } /* Getters. */ public final WebView getWebView() { return this.mWebView; } } 

разреш / макет / activity_main.xml

 <?xml version="1.0" encoding="utf-8"?> <WebView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/webView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

По сути, мы добавляем дополнительную функцию JavaScript, которая используется для проверки состояния документа. Если он загружен, мы запускаем пользовательское onPageLoaded() в MainActivity Android; В противном случае мы регистрируем прослушиватель событий, который обновляет Android после того, как страница будет готова, используя window.addEventListener('onload', ...); ,

Поскольку мы добавляем этот скрипт после вызова this.getWebView().loadURL("") было сделано, вероятно, нам не нужно «слушать» события вообще, так как мы получаем только шанс Чтобы добавить JavaScript-крючок, выполнив последовательный вызов loadURL , как только страница уже загружена.