Web Görünümü'nün "web sayfası kullanılamıyor" göstermesini önleyin


88

Bir Web Görünümü'nü kapsamlı şekilde kullanan bir uygulamam var. Bu uygulamanın kullanıcısı İnternet bağlantısına sahip olmadığında, "web sayfası kullanılamıyor" yazan bir sayfa ve çeşitli başka metinler belirir. Bu genel metni Web Görünümümde göstermemenin bir yolu var mı? Kendi hata işlememi sağlamak istiyorum.

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();
 }
}

Öğrendiğim WebView-> Clearview aslında görünümü temizlemez.


3
Neden web Görünümü'nü göstermeden önce internet bağlantısını kontrol etmiyorsunuz ve kullanılabilir internet olanağı yoksa Web Görünümü'nü göstermeyi atlayabilir ve bunun yerine internet mesajı olmadan bir uyarı veya tost gösterebilirsiniz?
Andro Selva

@JoJo bir yanıtı doğru olarak işaretleyebilir misiniz? muhtemelen benim: P
Sherif elKhatib

Yanıtlar:


102

Öncelikle HTML'de kendi hata sayfanızı oluşturun ve varlıklar klasörünüze koyun, Hadi ona myerrorpage.html diyelim Sonra onReceivedError ile:

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

    }
});

27
Eski "Web sayfası yüklenmedi" hata sayfası, varlıkların özel hata sayfasıyla değiştirilmeden önce bir saniyeden daha kısa bir süre
boyunca görünüyor

1
Cheenu ile aynı fikirde. Daha iyi bir çözüm olmalı.
Jozua

3
1. Web Görünümü görünmez durumdayken web içeriğini yükleyebilir (ve belki de üzerinde kötü bir ilerleme gösterebilir) ve sayfa başarıyla yüklendiyse bunu gösterebilir / hata durumunda "hatam.html" dosyasını yükleyebilirsiniz. 2. Sayfa yüklendikten sonra çalışan JS'de OR problemini yüklemede sorunlar varsa onReceiveError'ın tetikleneceğini bilmelisiniz (document.ready () olayında çalışan jQuery işlevleri gibi). Masaüstü tarayıcısı - mobil tarayıcıların yaptığı gibi, kullanıcıyı bu konuda bilgilendirmeden JS hatasına izin verir.
FunkSoulBrother

6
view.loadUrl("about:blank");Bir saniyeden kısa bir süre için hata sayfası göstermesini önlemek için loadUrl'den önce ekleyin .
Aashish

2
Bu myerrorpage.html dosyasını nereye koymalıyım? Bu android varlıklar klasörü nerede bulunur?
Nived Kannada

34

Bulduğum en iyi çözüm, OnReceivedError olayına şunun gibi boş bir sayfa yüklemektir:

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

    view.loadUrl("about:blank");
}

İyi bir fikir! Benim durumumda view.loadUrl(noConnectionUrl);iki kez ekledim (burada noConnectionUrl hata mesajı içeren yerel dosyadır). Bu aynı zamanda bir saniyeden daha kısa bir süre boyunca yerleşik hata sayfasını "görmemeye" yardımcı oldu.
hQuse

4
Lütfen dikkat edin, eğer işlem yapıyorsanız, webView.goBack()bu boş sayfa için koşulu işlediğinizden emin olun. Aksi takdirde önceki sayfanız yüklenecek ve tekrar başarısız olursa bu boş sayfayı tekrar göreceksiniz.
Chintan Shah

Peki bunun üstesinden gelmenin en iyi yolu nedir?
Mostafa Soliman

@MoSoli Her şey ihtiyaçlarınıza bağlıdır. Boş bir sayfayı görüntülemeye bir alternatif, bazı özel kullanıcı arayüzleri veya önbelleğe alınmış bir web sayfası göstermektir.
7heViking

10

Sonunda bunu çözdüm. (Şimdiye kadar çalışıyor ..)

Benim çözümüm şöyle ...

  1. Düzeni, Web Sayfası yerine bir hata oluştuğunda gösterecek şekilde hazırlayın (kirli bir 'sayfa bulunamadı mesajı') Düzende bazı kılavuz mesajlar içeren "YENİDEN YÜKLE" adlı bir düğme vardır.

  2. Bir hata oluşursa, boole kullanmayı hatırlayın ve hazırladığımız düzeni gösterin.

  3. Kullanıcı "YENİDEN YÜKLE" düğmesini tıklarsa, mbErrorOccured öğesini false olarak ayarlayın. Ve mbReloadPressed öğesini true olarak ayarlayın.
  4. mbErrorOccured yanlışsa ve mbReloadPressed doğruysa bu, web görünümünün sayfanın başarıyla yüklendiği anlamına gelir. Hata tekrar oluşursa, mbErrorOccured onReceivedError'da true olarak ayarlanacaktır (...)

İşte tam kaynağım. Şuna bak.

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);
            }
        };
    }
}

Ekleme: İşte düzen ...

<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>


Lütfen kaynak dosyanızı paylaşır mısınız? Acemiyim
Rajan Rawal

@RajanRawal Düzen örneğini düzenledim ve ekledim. :)
cmcromance

Herhangi bir ilerleme çubuğu göremiyorum ama kodu orada görebiliyorum. :-(
Rajan Rawal

8

Web görünümü, kullanıcının bir web görünümü değil de yerel bir görünüm gördüğüne neredeyse inanacağı şekilde bazı özel görünümlere gömüldüğünde, böyle bir senaryoda "sayfa yüklenemedi" hatasını gösteren mantıksız bir durumdur. Böyle bir durumda genellikle yaptığım şey, boş bir sayfa yükleyip aşağıdaki gibi bir tost mesajı göstermemdir.

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);
            }
        });

7

Android WebView onReceivedError () adresindeki tartışmaya göz atın . Oldukça uzun, ancak fikir birliği, a) "web sayfası kullanılamıyor" sayfasının görünmesini durduramazsınız, ancak b) bir onReceivedError aldıktan sonra her zaman boş bir sayfa yükleyebilirsiniz.


Bu adamlar onReceivedErrorhiç tetiklememekten bahsediyorlar . İnternet bağlantısı olmadığında kodumda doğru şekilde tetikleniyor.
JoJo

2

GETSayfa içeriğini almak için bir istek kullanabilir ve ardından bu verileri kullanarak bu verileri görüntüleyebilirsiniz Webview, bu şekilde birden fazla sunucu çağrısı kullanmazsınız. Alternatif olarak Javascript, DOMnesnenin geçerliliğini kontrol etmek için kullanabilirsiniz .


bu iyi bir fikir, ancak böyle bir şey yapmamız gerçekten talihsiz bir durum ...
Jeffrey Blattman

2

Belki soruyu yanlış anladım, ancak geri aramayı aldığınızı söylüyorsunuz ve hatayı göstermemek için en iyi yolun ne olduğunu soruyorsunuz? Neden web görünümünü ekrandan kaldırmıyorsunuz ve / veya bunun üzerinde başka bir görünüm göstermiyorsunuz?


2

Burada en kolay çözümü buldum. bunu kontrol et..

   @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);
        }

Ve işteInterentConnection () yöntemi ...

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;
}

1

Sanırım bunu yapmakta ısrar ediyorsanız, loadURL işlevini çağırmadan önce kaynağın orada olup olmadığını kontrol edebilirsiniz. Sadece işlevleri geçersiz kılın ve super () 'i çağırmadan önce kontrolü yapın.

HATIRLATMA (konu dışı olabilir): http'de, aşağıdaki gibi açıklanan HEAD adlı bir yöntem vardır:

HEAD yöntemi, sunucunun yanıtta bir ileti gövdesi döndürmemesi ZORUNLU olması dışında GET ile aynıdır.

Bu yöntem kullanışlı olabilir. Her neyse, nasıl uygularsanız ... şu kodu kontrol edin:

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
}
}

Bu kontrolü kullanarak deneyebilirsiniz

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

6
Kaynağın gerçekten gitmeden önce orada olup olmadığını kontrol etmek, 1 sanal istek başına 2 fiziksel istek olacağı için sunucudaki yükü ikiye katlar. Bu biraz abartılı görünüyor.
JoJo

1
Her neyse, yine de aşırı yükleyebilir ve html içeriğini alabilirsiniz, bir hata olup olmadığını kontrol edin. Değilse ayrıştırmak ve görüntülemek
Sherif elKhatib

bunu gerçekte nasıl uygularsınız?
JoJo

@JoJo, aslında bu yöntem geçersiz bir url durumunda sunucudaki yükü azaltır, çünkü HEAD yanıtı döndürmek, 304 veya 500 yanıtı döndürmeye kıyasla çok daha küçük bir ek yüke sahiptir.
Justin Shield

Bu, sayfayı indirirken bağlantı koparsa sorunu
çözmez

0

Hata işleme için kullandığınız web sayfasını değiştiririm:

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/");

bunların tümü http://developer.android.com/reference/android/webkit/WebView.html adresinde bulunabilir.


0

Bugün bu sinir bozucu Google hata sayfalarından kurtulma sorunu üzerinde çalışıyorum. Yukarıda ve diğer birçok forumda görülen Android örnek koduyla mümkündür (nasıl bildiğimi sorun):

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();
       }
    }
});

EĞER onu bir web istemcisi olarak shouldOverrideUrlLoading () içine koyarsanız. En azından bu benim için 2.3.6 cihazımda çalışıyor. Başka nerede çalıştığını daha sonra göreceğiz. Bu sadece şimdi beni üzer, eminim. GoBack bit benim. İstemeyebilirsin.


0

Bunu dene

 @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());
      }
 }

0

WebView görünürlüğünü 0 (view.INVISIBLE) olarak ayarlayabilir ve bir mesaj gösterebiliriz. Bu kod, lolipop üzerinde çalışan uygulamam için çalışıyor.

@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());
    }

0

Bu sorunla yüzleşmek zorunda kaldım ve farklı açılardan da çözmeye çalıştım. Sonunda, bir hata olup olmadığını kontrol etmek için tek bir bayrak kullanarak bir çözüm buldum.

... 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());
    }
 }

Bu şekilde, her hata olduğunda sayfayı gizlerim ve sayfa yeniden düzgün yüklendiğinde gösteririm.

Ayrıca durumda küçük bir gecikme eklendi.

Gezinti geçmişine o yeni sayfayı eklediğinden daha sonra webview.reload () yapmanıza izin vermediği için boş bir sayfa yükleme çözümünden kaçındım.



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.