Mam aplikację, która w szerokim zakresie wykorzystuje WebView. Kiedy użytkownik tej aplikacji nie ma połączenia z Internetem, pojawia się strona z napisem „strona internetowa niedostępna” i inny tekst. Czy istnieje sposób, aby nie wyświetlać tego ogólnego tekstu w moim WebView? Chciałbym zapewnić własną obsługę błędów.
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();
}
}
Dowiedziałem się, że WebView-> clearView w rzeczywistości nie czyści widoku.
Odpowiedzi:
Najpierw utwórz własną stronę błędu w formacie HTML i umieść ją w folderze zasobów, nazwijmy ją myerrorpage.html Następnie za pomocą onReceivedError:
mWebView.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { mWebView.loadUrl("file:///android_asset/myerrorpage.html"); } });
źródło
view.loadUrl("about:blank");
przed loadUrl, aby zapobiec wyświetlaniu strony błędu przez ułamek sekundy.Najlepszym rozwiązaniem, jakie znalazłem, jest załadowanie pustej strony w zdarzeniu OnReceivedError w następujący sposób:
@Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); view.loadUrl("about:blank"); }
źródło
view.loadUrl(noConnectionUrl);
dwukrotnie (gdzie noConnectionUrl to lokalny plik z komunikatem o błędzie). Pomogło to również nie „widzieć” wbudowanej strony błędu przez ułamek sekundy.webView.goBack()
upewnij się, że obsługujesz warunek dla tej pustej strony. W przeciwnym razie wczytana zostanie poprzednia strona i jeśli ponownie się nie powiedzie, ponownie zobaczysz tę pustą stronę.Wreszcie rozwiązałem to. (Działa do teraz ..)
Moje rozwiązanie jest takie ...
Przygotuj układ tak, aby zamiast strony internetowej pokazywał, kiedy wystąpił błąd (komunikat „nie znaleziono strony”) Układ ma jeden przycisk „RELOAD” z kilkoma komunikatami przewodnika.
Jeśli wystąpił błąd, pamiętaj o użyciu wartości logicznych i pokaż przygotowany przez nas układ.
Oto moje pełne źródło. Sprawdź to.
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); } }; } }
Dodatek: Oto układ ...
<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>
źródło
Kiedy webview jest osadzony w jakimś niestandardowym widoku, tak że użytkownik prawie wierzy, że widzi widok natywny, a nie widok internetowy, w takim przypadku błąd „nie można załadować strony” jest niedorzeczny. Zwykle w takiej sytuacji ładuję pustą stronę i pokazuję toastową wiadomość jak poniżej
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); } });
źródło
Sprawdź dyskusję w Android WebView onReceivedError () . Jest dość długi, ale wydaje się, że a) nie możesz zatrzymać wyświetlania strony „strona internetowa niedostępna”, ale b) zawsze możesz załadować pustą stronę po otrzymaniu onReceivedError
źródło
onReceivedError
tym, żeby w ogóle nie uruchamiać. Uruchamia się poprawnie w moim kodzie, gdy nie ma połączenia z Internetem.Możesz użyć
GET
żądania, aby pobrać zawartość strony, a następnie wyświetlić te dane za pomocąWebview
, w ten sposób nie używasz wielu wywołań serwera. Alternatywnie możesz użyćJavascript
do sprawdzeniaDOM
poprawności obiektu.źródło
Być może źle zrozumiałem pytanie, ale wygląda na to, że mówisz, że otrzymałeś komunikat zwrotny o błędzie i po prostu pytasz, jaki jest najlepszy sposób, aby nie pokazać błędu? Dlaczego po prostu nie usuniesz widoku internetowego z ekranu i / lub nie pokażesz na nim innego widoku?
źródło
Tutaj znalazłem najłatwiejsze rozwiązanie. Sprawdź to..
@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); }
A oto metoda 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; }
źródło
Przypuszczam, że jeśli nalegasz na zrobienie tego, możesz po prostu sprawdzić, czy zasób istnieje, przed wywołaniem funkcji loadURL. Po prostu nadpisuj funkcje i sprawdź przed wywołaniem super ()
UWAGA (może nie na temat): W http znajduje się metoda o nazwie HEAD, opisana w następujący sposób:
Ta metoda może być przydatna. Tak czy inaczej, jak kiedykolwiek to zaimplementujesz ... sprawdź ten kod:
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 } }
Możesz spróbować tego sprawdzenia za pomocą
if(url.openConnection().getContentLength() > 0)
źródło
Po prostu zmieniłbym stronę internetową na tę, której używasz do obsługi błędów:
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/");
to wszystko można znaleźć na http://developer.android.com/reference/android/webkit/WebView.html
źródło
Pracowałem dzisiaj nad tym problemem porzucenia tych irytujących stron błędów Google. Jest to możliwe dzięki przykładowemu kodowi Androida widocznemu powyżej i na wielu innych forach (zapytaj, skąd wiem):
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(); } } });
JEŚLI umieścisz go w shouldOverrideUrlLoading () jako jeszcze jednego klienta WWW. Przynajmniej to działa dla mnie na moim urządzeniu 2.3.6. Gdzie jeszcze to działa, zobaczymy później. Jestem pewien, że to by mnie teraz tylko przygnębiło. Kawałek goBack jest mój. Możesz tego nie chcieć.
źródło
Spróbuj tego
@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()); } }
źródło
Możemy ustawić widoczność webView na 0 (view.INVISIBLE) i pokazać jakąś wiadomość. Ten kod działa dla mojej aplikacji działającej na Lolipopie.
@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()); }
źródło
Musiałem zmierzyć się z tym problemem, a także próbowałem go rozwiązać z różnych perspektyw. Wreszcie znalazłem rozwiązanie, używając jednej flagi, aby sprawdzić, czy wystąpił błąd.
... 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()); } }
W ten sposób ukrywam stronę za każdym razem, gdy pojawia się błąd i pokazuję ją po ponownym załadowaniu strony.
Dodano również małe opóźnienie w przypadku.
Uniknąłem rozwiązania polegającego na wczytywaniu pustej strony, ponieważ nie pozwala na późniejsze wykonanie webview.reload (), ponieważ dodaje tę nową stronę do historii nawigacji.
źródło
spróbuj tego shouldOverrideUrlLoading , przed przekierowaniem do innego adresu URL sprawdź, czy połączenie internetowe oparte na tej stronie powinno zostać załadowane, czy nie.
źródło
zastąpić metodę WebViewClient
@Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { view.clearView(); }
view.loadUrl('about:blank')
ma efekty uboczne, ponieważ anuluje ładowanie oryginalnego adresu URL.źródło