Tengo una aplicación que hace un uso extensivo de 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 alguna forma 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 en realidad no borra la vista.
Respuestas:
Primero cree su propia página de error en HTML y colóquela en su carpeta de activos, llamémosla myerrorpage.html Luego con onReceivedError:
mWebView.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { mWebView.loadUrl("file:///android_asset/myerrorpage.html"); } });
fuente
view.loadUrl("about:blank");
antes de loadUrl para evitar que muestre la página de error durante una fracción de segundo.La mejor solución que he encontrado es cargar una página vacía en el evento OnReceivedError como este:
@Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); view.loadUrl("about:blank"); }
fuente
view.loadUrl(noConnectionUrl);
dos veces (donde noConnectionUrl es un archivo local con un mensaje de error). Eso también ayudó a no "ver" la página de error incorporada durante una fracción de segundo.webView.goBack()
, asegúrese de gestionar la condición de esta página en blanco. De lo contrario, se cargará su página anterior y, si falla nuevamente, verá esta página en blanco nuevamente.Finalmente, resolví esto. (Funciona hasta ahora ..)
Mi solución es así ...
Prepare el diseño para mostrar cuando ocurrió un error en lugar de la página web (un 'mensaje de página no encontrada' sucio) El diseño tiene un botón, "RELOAD" con algunos mensajes de guía.
Si ocurrió un error, recuerde usar boolean y mostrar el diseño que preparamos.
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á el diseño ...
<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>
fuente
Cuando la vista web está incrustada en alguna vista personalizada de modo que el usuario casi cree que está viendo una vista nativa y no una vista web, en tal escenario, mostrar el error "la página no se pudo cargar" es absurdo. Lo que suelo hacer en tal situación es cargar una página en blanco y mostrar un mensaje de brindis como se muestra 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); } });
fuente
Consulte la discusión en Android WebView onReceivedError () . Es bastante largo, pero el consenso parece ser que a) no se puede evitar que aparezca la página "página web no disponible", pero b) siempre se puede cargar una página vacía después de recibir un error onReceivedError
fuente
onReceivedError
no disparar en absoluto. Se activa correctamente en mi código cuando no hay conexión a Internet.Puede usar una
GET
solicitud para obtener el contenido de la página y luego mostrar esos datos usando elWebview
, de esta manera no está usando múltiples llamadas al servidor. Alternativa que puede utilizarJavascript
para comprobar laDOM
validez del objeto.fuente
Tal vez no entiendo la pregunta, pero parece que está diciendo que recibe la devolución de llamada del error recibido, y solo pregunta cuál es la mejor manera de no mostrar el error. ¿Por qué no elimina la vista web de la pantalla y / o muestra otra vista encima?
fuente
Aquí encontré la solución más sencilla. 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; }
fuente
Supongo que si insiste en hacer esto, puede verificar si el recurso está allí antes de llamar a la función loadURL. Simplemente anule las funciones y haga la verificación antes de llamar al super ()
OBSERVACIÓN (quizás fuera del tema): En http, hay un método llamado HEAD que se describe a continuación:
Este método puede resultar útil. De todos modos, como sea que lo implemente ... verifique 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 } }
Podrías probar esta verificación usando
if(url.openConnection().getContentLength() > 0)
fuente
Simplemente 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/");
todo esto se puede encontrar en http://developer.android.com/reference/android/webkit/WebView.html
fuente
Hoy he estado trabajando en este problema de deshacerme de esas irritables páginas de error de Google. Es posible con el código de ejemplo de Android que se ve arriba y en muchos otros foros (pregunte cómo lo 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 lo coloca en shouldOverrideUrlLoading () como un cliente web más. Al menos, esto me funciona en mi dispositivo 2.3.6. Veremos dónde más funciona más tarde. Eso solo me deprimiría ahora, estoy seguro. El bit goBack es mío. Puede que no lo desee.
fuente
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()); } }
fuente
Podemos establecer la visibilidad de webView en 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()); }
fuente
He tenido que afrontar este problema y también he tratado de solucionarlo desde diferentes perspectivas. Finalmente encontré una solución usando una sola bandera para verificar si ocurrió un error.
... extends WebViewClient { boolean error; @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { showLoading(true); super.onPageStarted(view, url, favicon); error = false; // IMPORTANT } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); if(!error) { Observable.timer(100, TimeUnit.MICROSECONDS, AndroidSchedulers.mainThread()) .subscribe((data) -> view.setVisibility(View.VISIBLE) ); } showLoading(false); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { view.stopLoading(); view.setVisibility(View.INVISIBLE) error = true; // Handle the error } @Override @TargetApi(android.os.Build.VERSION_CODES.M) public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { this.onReceivedError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); } }
De esta forma, oculto la página cada vez que hay un error y lo muestro cuando la página se ha cargado de nuevo correctamente.
También se agregó un pequeño retraso por si acaso.
Evité la solución de cargar una página vacía ya que no le permite hacer webview.reload () más adelante debido a que agrega esa nueva página en el historial de navegación.
fuente
intente esto shouldOverrideUrlLoading , antes de redirigir a otra URL, verifique si la conexión a Internet basada en esa página debe cargarse o no.
fuente
anular su 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 de la URL original.fuente