Android: как проверить успешную загрузку url при использовании webview.loadUrl

В webview android я пытаюсь загрузить URL-адрес и проверить, успешно ли загружен этот URL-адрес (подключение к Интернету было доступно, сервер был включен и т.д.). У меня создалось впечатление, что webview.loadUrl будет бросать исключения, но неправильно! так как это явно указано в здесь "исключение НЕ будет выбрано".

Итак, как я могу проверить, не потерял ли webview.loadUrl?

Ответ 1

К сожалению, в настоящее время в WebView нет простого способа убедиться, что все на странице было успешно загружено. Мы надеемся, что лучший API появится в будущей версии. Позвольте мне объяснить, что вы можете сделать сейчас.

Прежде всего, чтобы обнаружить любые проблемы, которые препятствуют веб-интерфейсу для подключения к серверу для загрузки вашей главной страницы (например, неправильное имя домена, ошибка ввода-вывода и т.д.), вы должны использовать обратный вызов WebViewClient.onReceivedError как правильно указывают другие люди:

public class MyWebViewClient extends WebViewClient {
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        // Make a note about the failed load.
    }
}
myWebView.setWebViewClient(new MyWebViewClient());

Если соединение с сервером прошло успешно, а основная страница была восстановлена ​​и проанализирована, вы получите обратный вызов WebView.onPageFinished, поэтому вам также необходимо иметь это в своем подклассе WebViewClient:

public class MyWebViewClient extends WebViewClient {
    ...
    @Override
    public void onPageFinished(WebView view, String url) {
        // Make a note that the page has finished loading.
    }
    ...
}

Здесь следует указать, что если вы получили сообщение об ошибке HTTP с сервера (например, ошибка 404 или 500), этот обратный вызов будет вызван в любом случае, это просто контент, который вы получите в своем WebView, будет сервером страница ошибки. Люди предлагают разные способы справиться с этим, см. Ответы здесь: Как я могу проверить из Android WebView, если страница "404 страница не найдена" ? В принципе, это действительно зависит от того, что вы ожидаете стать "хорошей" страницей и "ошибкой". К сожалению, в настоящее время у приложения нет способа получить код ответа HTTP из WebView.

Обратные вызовы WebViewClient.onPageStarted и WebViewClient.onProgressChanged полезны, если вы хотите нарисовать индикатор выполнения при загрузке страницы.

Также обратите внимание, что способ переопределения WebViewClient.shouldOverrideUrlLoading, который обычно предлагают люди, неверен:

public class MyWebViewClient extends WebViewClient {
    ...
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)         {  
        // !!! DO NOT DO THIS UNCONDITIONALLY !!!
        view.loadUrl(url);
        return true;
    }
    ...
}

Мало кто понимает, что обратный вызов также вызывается для подкадров с не-https-схемами. Если вы столкнетесь с чем-то вроде <iframe src='tel:1234'>, вы закончите выполнение view.loadUrl('tel:1234'), и ваше приложение покажет страницу с ошибкой, так как WebView не знает, как загрузить URL tel:. Рекомендуется просто вернуть false из метода, если вы хотите, чтобы WebView выполнял загрузку:

public class MyWebViewClient extends WebViewClient {
    ...

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)         {
        // Returning 'false' unconditionally is fine.
        return false;
    }
    ...
}

Это не означает, что вы не должны называть WebView.loadUrl от shouldOverrideUrlLoading вообще. Конкретный шаблон, который следует избегать, делает это безоговорочно для всех URL-адресов.

Ответ 2

public class AppWebViewClient extends WebViewClient {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            // TODO Auto-generated method stub
            super.onPageStarted(view, url, favicon);
            setProgressBar(true);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            //Page load finished
            super.onPageFinished(view, url);
            setProgressBar(false);
        }
}

а затем вы можете сделать

webView.setWebViewClient(new AppWebViewClient());

Для части ошибки вы можете переопределить метод onReceivedError

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        // TODO Auto-generated method stub
        super.onReceivedError(view, errorCode, description, failingUrl);
}

Ответ 3

Вот то, что я придумал, работает как шарм

    Boolean failedLoading = false;
    WebView webView = view.findViewById(R.id.webView);
    webView.loadUrl("www.example.com");
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (!failedLoading) {
                webView.setVisibility(View.VISIBLE);
                webView.setAlpha(0f);
                ObjectAnimator anim  = ObjectAnimator.ofFloat(webView, "alpha",1f);
                anim.setDuration(500);
                anim.start();
            }
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            failedLoading = true;
        }
    });

Работает также отлично, если у вас есть какая-то кнопка обновления, чем вы можете вызвать приведенный выше код внутри функции, чтобы повторить попытку :)

Ответ 4

Вы можете проверить, успешно ли загружен URL, используя onProgressChanged()

mWebView.setWebChromeClient(new WebChromeClient() {

         public void onProgressChanged(WebView view, int progress) {
                progressBar.setProgress(progress);
                if (progress == 100) {
                    //your url is loaded successfully 
                }
            }
    });