WebViewClient.onPageStarted () llamó dos veces al especificar URL no existente a través de WebView.loadURL ()

Aquí está mi código

public class Main extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); WebView webView = (WebView)findViewById(R.id.webView); // Assign webclient. webView.setWebViewClient(new WebViewClient( ) { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Log.d("TAG", url); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Log.d("TAG", "failed: " + failingUrl + ", error code: " + errorCode + " [" + description + "]"); } }); webView.loadUrl("http://m.vooglemoogle.com" ); } } 

Resultados en el siguiente registro:

 03-29 13:40:27.005: DEBUG/TAG(10948): http://m.vooglemoogle.com/ 03-29 13:40:27.599: DEBUG/TAG(10948): failed: http://m.vooglemoogle.com/, error code: -2[The URL could not be found.] 03-29 13:40:27.607: DEBUG/TAG(10948): http://m.vooglemoogle.com/ 

Nota otra llamada a onPageStarted () … ¿Alguien sabe la razón detrás de esto? ¡aclamaciones!

Me encontré con el mismo problema al probar mi aplicación en un AVD con API 7 (no estoy seguro si esto es relevante, pero en cualquier caso).

Me di cuenta de que la secuencia exacta de callbacks es la siguiente:

 onPageStarted() // url = non-existing url onLoadResource() // url = non-existing url onReceivedError() // url = non-existing url onPageStarted() // url = non-existing url onLoadResource() // url = file://android_assed/webkit/android-weberror.png onPageFinished() // url = non-existing url 

Así que supongo que la carga de la página de Android "página web no disponible" está desencadenando la segunda llamada onPageStarted.

Yo luché con esto también, pero creo que he trabajado en torno a ello. Básicamente establezco una bandera en el error para guardar el cliente de procesar más callbacks. La bandera se restablece cuando llamo a un método en la actividad para probar la carga de nuevo. Aquí hay algunos ejemplos de código de una lista de conceptos que creé https://gist.github.com/museofwater/6373048

 public class AsyncMultiplayerSetupActivity extends Activity { private static final String TAG = AsyncMultiplayerSetupActivity.class.getName(); public static final String UTF_8 = "UTF-8"; private WebView wvSignin; private String url = "http://localhost:9000/signin"; private ProgressDialog progressLoadUrl; private SigninWebViewClient webViewClient; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); registerUser(url); } private void registerUser(String url) { webViewClient = new SigninWebViewClient(getResources().getInteger(R.integer.timeout)); setContentView(R.layout.setup); wvSignin = (WebView)findViewById(R.id.wvSignin); wvSignin.getSettings().setJavaScriptEnabled(true); wvSignin.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); wvSignin.setWebViewClient(webViewClient); loadUrl(url); } private void loadUrl(String url) { if (!NetworkUtil.checkNetwork(this)) { setSigninFailureResult(); } // Show progress progressLoadUrl = ProgressDialog.show(this, getString(R.string.CONNECTING_TITLE), getString(R.string.CONNECTING_MSG)); webViewClient.prepareToLoadUrl(); wvSignin.loadUrl(url); } private void setSigninFailureResult() { setResult(getResources().getInteger(R.integer.RESPONSE_FAILED_CODE)); finish(); } private void setSigninResult() { setResult(getResources().getInteger(R.integer.RESPONSE_OK_CODE)); } private class SigninWebViewClient extends WebViewClient { /** * Timeout for page load in seconds */ private int timeout; private String urlLoading; boolean pageLoaded = false; // Flag to instruct the client to ignore callbacks after an error boolean hasError = false; private Handler timeoutHandler; private AlertDialog alertDialog; private SigninWebViewClient(int timeout) { this.timeout = timeout; timeoutHandler = new Handler(); } // Called by activity before requesting load of a url private void prepareToLoadUrl() { this.hasError = false; this.pageLoaded = true; this.urlLoading = null; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (hasError) { return; } urlLoading = url; // timeout has expired if this flag is still set when the message is handled pageLoaded = false; Runnable run = new Runnable() { public void run() { // Do nothing if we already have an error if (hasError) { return; } // Dismiss any current alerts and progress dismissProgress(); dismissErrorAlert(); if (!pageLoaded) { showTimeoutAlert(); } } }; timeoutHandler.postDelayed(run, this.timeout*1000); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // Ignore future callbacks because the page load has failed hasError = true; dismissProgress(); showServerErrorAlert(); } @Override public void onPageFinished(WebView view, String url) { if (hasError) { return; } pageLoaded = true; dismissProgress(); dismissErrorAlert(); urlLoading = null; // Do whatever processing you need to on page load here } private void showTimeoutAlert() { showErrorAlert(R.string.TIMEOUT_TITLE, R.string.TIMEOUT_MSG); } private void showServerErrorAlert() { showErrorAlert(R.string.SERVER_ERROR_TITLE,R.string.SERVER_ERROR_MSG); } private void showErrorAlert(int titleResource, int messageResource) { AlertDialog.Builder builder = new AlertDialog.Builder(AsyncMultiplayerSetupActivity.this); // Add the buttons builder.setTitle(titleResource) .setMessage(messageResource) .setPositiveButton(R.string.RETRY, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Try to load url again loadUrl(urlLoading); dialog.dismiss(); } }); builder.setNegativeButton(R.string.CANCEL, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog setSigninFailureResult(); dialog.cancel(); } }); // Create the AlertDialog alertDialog = builder.create(); alertDialog.show(); } private void dismissProgress() { if (progressLoadUrl != null && progressLoadUrl.isShowing()) { progressLoadUrl.dismiss(); } } private void dismissErrorAlert() { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); } } } } 

En la API de Android, puede encontrar la nota:

Notificar a la aplicación host que una página ha iniciado la carga. Este método se llama una vez para cada carga del marco principal, por lo que una página con iframes o framesets llamará onPageStarted una vez para el frame principal. Esto también significa que onPageStarted no se llamará cuando cambia el contenido de un marco incrustado, es decir, haciendo clic en un vínculo cuyo destino es un iframe.

Lo que sugiere que podría ser causado por "iframes" en la página web.

  • OnPageStart se llama muchas veces y onPageFinished no se llama para una sola página
  • ¿Qué se considera onPageFinished en el WebViewClient para Android?
  • Android JS en WebView.loadUrl ()
  • Android WebView para Facebook como botón
  • Habilitación de JavaScript general en WebViewClient
  • Android WebViewClient onReceivedError no se llama para un error 404
  • Android: abra los vínculos _blank de destino en WebView con un navegador externo
  • El controlador onScaleChanged de WebView se llama varias veces
  • Interceptar y anular las solicitudes HTTP de WebView
  • Vista Web de Android
  • Android: cómo interceptar un formulario POST en android WebViewClient en el nivel 4 de API
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.