Impedir que WebView muestre "página web no disponible"

Tengo una aplicación que hace uso extensivo de un WebView. Cuando el usuario de esta aplicación no tiene conexión a Internet, aparece una página que dice "página web no disponible" y varios otros textos. ¿Hay una manera de no mostrar este texto genérico en mi WebView? Me gustaría proporcionar mi propio manejo de errores.

private final Activity activity = this; private class MyWebViewClient extends WebViewClient public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // I need to do something like this: activity.webView.wipeOutThePage(); activity.myCustomErrorHandling(); Toast.makeText(activity, description, Toast.LENGTH_LONG).show(); } } 

Descubrí que WebView-> clearView no borra la vista.

En primer lugar, crear su propia página de error en HTML y ponerlo en su carpeta de activos, vamos a llamar myerrorpage.html Entonces con onReceivedError:

 mWebView.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { mWebView.loadUrl("file:///android_asset/myerrorpage.html"); } }); 

La mejor solución que he encontrado es cargar una página vacía en el evento OnReceivedError así:

 @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); view.loadUrl("about:blank"); } 

Finalmente, resolví esto. (Funciona hasta ahora ..)

Mi solución es así …

  1. Preparar el diseño para mostrar cuándo ocurrió un error en lugar de Página Web (un mensaje de "página no encontrada" sucia) El diseño tiene un botón, "RELOAD" con algunos mensajes guía.

  2. Si se produjo un error, recuerde usar booleanos y mostrar el diseño que preparamos.

  3. Si el usuario hace clic en el botón "RELOAD", defina mbErrorOccured como false. Y fije mbReloadPressed en true.
  4. Si mbErrorOccured es falso y mbReloadPressed es true, significa que la página cargada Webview se ha ejecutado correctamente. Porque si el error ocurrió otra vez, mbErrorOccured será fijado verdadero en onReceivedError (…)

Aquí está mi fuente completa. Mira esto.

 public class MyWebViewActivity extends ActionBarActivity implements OnClickListener { private final String TAG = MyWebViewActivity.class.getSimpleName(); private WebView mWebView = null; private final String URL = "http://www.google.com"; private LinearLayout mlLayoutRequestError = null; private Handler mhErrorLayoutHide = null; private boolean mbErrorOccured = false; private boolean mbReloadPressed = false; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_webview); ((Button) findViewById(R.id.btnRetry)).setOnClickListener(this); mlLayoutRequestError = (LinearLayout) findViewById(R.id.lLayoutRequestError); mhErrorLayoutHide = getErrorLayoutHideHandler(); mWebView = (WebView) findViewById(R.id.webviewMain); mWebView.setWebViewClient(new MyWebViewClient()); WebSettings settings = mWebView.getSettings(); settings.setJavaScriptEnabled(true); mWebView.setWebChromeClient(getChromeClient()); mWebView.loadUrl(URL); } @Override public boolean onSupportNavigateUp() { return super.onSupportNavigateUp(); } @Override public void onClick(View v) { int id = v.getId(); if (id == R.id.btnRetry) { if (!mbErrorOccured) { return; } mbReloadPressed = true; mWebView.reload(); mbErrorOccured = false; } } @Override public void onBackPressed() { if (mWebView.canGoBack()) { mWebView.goBack(); return; } else { finish(); } super.onBackPressed(); } class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return super.shouldOverrideUrlLoading(view, url); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public void onLoadResource(WebView view, String url) { super.onLoadResource(view, url); } @Override public void onPageFinished(WebView view, String url) { if (mbErrorOccured == false && mbReloadPressed) { hideErrorLayout(); mbReloadPressed = false; } super.onPageFinished(view, url); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { mbErrorOccured = true; showErrorLayout(); super.onReceivedError(view, errorCode, description, failingUrl); } } private WebChromeClient getChromeClient() { final ProgressDialog progressDialog = new ProgressDialog(MyWebViewActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setCancelable(false); return new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } }; } private void showErrorLayout() { mlLayoutRequestError.setVisibility(View.VISIBLE); } private void hideErrorLayout() { mhErrorLayoutHide.sendEmptyMessageDelayed(10000, 200); } private Handler getErrorLayoutHideHandler() { return new Handler() { @Override public void handleMessage(Message msg) { mlLayoutRequestError.setVisibility(View.GONE); super.handleMessage(msg); } }; } } 

Adición: Aquí está la disposición ….

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rLayoutWithWebView" android:layout_width="match_parent" android:layout_height="match_parent" > <WebView android:id="@+id/webviewMain" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/lLayoutRequestError" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:background="@color/white" android:gravity="center" android:orientation="vertical" android:visibility="gone" > <Button android:id="@+id/btnRetry" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:minWidth="120dp" android:text="RELOAD" android:textSize="20dp" android:textStyle="bold" /> </LinearLayout> 

Echa un vistazo a la discusión en Android WebView onReceivedError () . Es bastante largo, pero el consenso parece ser que a) no se puede detener la "página web no disponible" la página que aparece, pero b) siempre se puede cargar una página vacía después de obtener un onReceivedError

Cuando la vista web está incrustada en algunas vistas personalizadas de tal manera que el usuario casi cree que está viendo una vista nativa y no una vista web. En ese escenario que muestra la página no se puede cargar el error es absurdo, lo que suelo hacer en tal situación es cargar la página en blanco y mostrar un mensaje de brindis como a continuación

 webView.setWebViewClient(new WebViewClient() { @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Log.e(TAG," Error occured while loading the web page at Url"+ failingUrl+"." +description); view.loadUrl("about:blank"); Toast.makeText(App.getContext(), "Error occured, please check newtwork connectivity", Toast.LENGTH_SHORT).show(); super.onReceivedError(view, errorCode, description, failingUrl); } }); 

Puede utilizar una solicitud GET para obtener el contenido de la página y, a continuación, mostrar esos datos utilizando la vista Webview , de esta manera no está utilizando varias llamadas al servidor. Alternativa puede utilizar Javascript para comprobar el objeto DOM para la validez.

Tal vez no entiendo la pregunta, pero suena como si estuviera diciendo que recibió el error recibido de devolución de llamada, y que sólo están preguntando cuál es la mejor manera de no mostrar el error? ¿Por qué no sólo quitar la vista web de la pantalla y / o mostrar otra vista en la parte superior de la misma?

Supongo que si insistes en hacer esto, podrías comprobar si el recurso está ahí antes de llamar a la función loadURL. Basta con anular las funciones y hacer la comprobación antes de llamar al super ()

REMARK (quizá fuera de tema): En http, hay un método llamado HEAD que se describe a continuación:

El método HEAD es idéntico a GET excepto que el servidor NO DEBE devolver un cuerpo de mensaje en la respuesta

Este método puede ser útil. De todos modos cómo alguna vez implementarlo … comprobar este código:

 import java.util.Map; import android.content.Context; import android.webkit.WebView; public class WebViewPreLoad extends WebView{ public WebViewPreLoad(Context context) { super(context); } public void loadUrl(String str){ if(//Check if exists) super.loadUrl(str); else //handle error } public void loadUrl(String url, Map<String,String> extraHeaders){ if(//Check if exists) super.loadUrl(url, extraHeaders); else //handle error } } 

Usted podría intentar esta comprobación usando

 if(url.openConnection().getContentLength() > 0) 

Yo sólo cambiaría la página web a lo que esté usando para el manejo de errores:

 getWindow().requestFeature(Window.FEATURE_PROGRESS); webview.getSettings().setJavaScriptEnabled(true); final Activity activity = this; webview.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { // Activities and WebViews measure progress with different scales. // The progress meter will automatically disappear when we reach 100% activity.setProgress(progress * 1000); } }); webview.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show(); } }); webview.loadUrl("http://slashdot.org/"); 

Esto se puede encontrar en http://developer.android.com/reference/android/webkit/WebView.html

He estado trabajando en este problema de abandonar esas irritables páginas de error de Google hoy. Es posible con el código de ejemplo de Android visto arriba y en muchos otros foros (pregunte cómo sé):

 wv.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { if (view.canGoBack()) { view.goBack(); } Toast.makeText(getBaseContext(), description, Toast.LENGTH_LONG).show(); } } }); 

SI usted lo pone en shouldOverrideUrlLoading () como un webclient más. Por lo menos, esto está funcionando para mí en mi dispositivo 2.3.6. Veremos dónde más funciona más tarde. Eso me deprime ahora, estoy seguro. El bit goBack es mío. Tal vez no lo quieras.

Prueba esto

  @SuppressWarnings("deprecation") @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // Your handling } @Override public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString()); } } 

Podemos establecer la visibilidad de webView a 0 (view.INVISIBLE) y mostrar algún mensaje. Este código funciona para mi aplicación que se ejecuta en lolipop.

 @SuppressWarnings("deprecation") @Override public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl) { // hide webView content and show custom msg webView.setVisibility(View.INVISIBLE); Toast.makeText(NrumWebViewActivity.this,getString(R.string.server_not_responding), Toast.LENGTH_SHORT).show(); } @TargetApi(android.os.Build.VERSION_CODES.M) @Override public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) { // Redirect to deprecated method, so you can use it in all SDK versions onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString()); } 

Aquí encontré la solución más fácil. mira esto..

  @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // view.loadUrl("about:blank"); mWebView.stopLoading(); if (!mUtils.isInterentConnection()) { Toast.makeText(ReportingActivity.this, "Please Check Internet Connection!", Toast.LENGTH_SHORT).show(); } super.onReceivedError(view, errorCode, description, failingUrl); } 

Y aquí está el método isInterentConnection () …

 public boolean isInterentConnection() { ConnectivityManager manager = (ConnectivityManager) mContext .getSystemService(Context.CONNECTIVITY_SERVICE); if (manager != null) { NetworkInfo info[] = manager.getAllNetworkInfo(); if (info != null) { for (int i = 0; i < info.length; i++) { if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } } return false; } 

Intente esto shouldOverrideUrlLoading , antes de redirigir a otra url comprobar para Internet conncetion basado en esa página debe ser cargado o no.

Reemplazar el método WebViewClient

 @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { view.clearView(); } 

view.loadUrl('about:blank') tiene efectos secundarios, ya que cancela la carga URL original.

  • Convertir matriz de int en Bitmap en Android
  • ¿Hay algún almacenamiento de certificados de sistema en Android?
  • Alternativa a Intent.FLAG_ACTIVITY_CLEAR_TASK
  • ¿El postDelayed hace que el mensaje salte al frente de la cola?
  • Android cursor cómo obtener valores nulos de columnas
  • ¿Es posible ejecutar pruebas de unidad de Android Espresso en métodos anotados @BeforeClass?
  • Android WebView - Fuga de memoria de JavaScript
  • Cómo agregar funcionalidad de flecha de botón Volver en barra de navegación
  • Android: GridView simple que muestra texto en las cuadrículas
  • ¿Qué es un apkLIB y cómo uso uno?
  • Prueba de estrés en una aplicación de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.