WebViewに「利用できないWebページ」が表示されないようにする


88

WebViewを多用するアプリがあります。このアプリのユーザーがインターネットに接続していない場合は、「ウェブページにアクセスできません」などのテキストが表示されます。この汎用テキストをWebViewに表示しない方法はありますか?独自のエラー処理を提供したいと思います。

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

私が見つけたWebView->クリアビューは、実際にビューをクリアしません。


3
webViewを表示する前にインターネット接続を確認し、インターネット機能が利用できない場合は、WebViewの表示をスキップして、代わりにインターネットメッセージなしでアラートまたはトーストを表示できますか?
Andro Selva

@JoJo正解は?おそらく私:P
Sherif elKhatib

回答:


102

まず、独自のエラーページをHTMLで作成し、アセットフォルダに配置します。myerrorpage.htmlと呼びましょう。次に、onReceivedErrorを使用します。

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

    }
});

27
古い「Webページが読み込まれていません」エラーページは、アセットのカスタムエラーページに置き換えられる前に、
ほんの一瞬

1
Cheenuに同意します。より良い解決策が必要です。
Jozua

3
1. WebViewが表示されていないときにWebコンテンツをロードし(おそらく、進行状況が悪い場合はそれを表示し)、ページが正常にロードされたかどうかを表示するか、エラー時に「myerrorpage.html」をロードします。2.ページのロード後に実行されるJSのOR問題のロードに問題がある場合(document.ready()イベントで実行されるjQuery関数など)、onReceiveErrorがトリガーされることに注意してください。デスクトップブラウザ-モバイルブラウザの場合と同様に、ユーザーに通知せずにJSエラーを許可します。
FunkSoulBrother 2015

5
view.loadUrl("about:blank");loadUrlの前に追加して、ほんの一瞬エラーページが表示されないようにします。
アーシッシュ2018

2
myerrorpage.htmlファイルをどこに配置しますか?そのandroidアセットフォルダーはどこにありますか?
Nived Kannada

34

私が見つけた最良の解決策は、次のようなOnReceivedErrorイベントで空のページをロードすることです:

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

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

良いアイデア!私の場合、view.loadUrl(noConnectionUrl);2回追加しました(ここで、noConnectionUrlはエラーメッセージのあるローカルファイルです)。また、組み込みのエラーページがほんの一瞬で "表示"されないことにも役立ちました。
hQuse 2017年

4
あなたが扱っている場合は、ご注意くださいwebView.goBack()。この空白のページ用のハンドル状態にしてください、その後。それ以外の場合は、前のページが読み込まれ、失敗した場合は、この空白のページが再び表示されます。
Chintan Shah

それで、それを処理する最良の方法は何ですか?
MoSoli

@MoSoliそれはすべてあなたのニーズに依存します。空のページを表示する代わりに、いくつかのカスタムUIまたはキャッシュされたWebページを表示することもできます。
7heViking

10

最後に、私はこれを解決しました。(これまでは動作します。)

私の解決策はこのようなものです...

  1. Webページの代わりにエラーが発生したときに表示するレイアウトを準備します(ダーティな「ページが見つかりません」というメッセージ)レイアウトには、「RELOAD」という1つのボタンといくつかのガイドメッセージがあります。

  2. エラーが発生した場合は、ブール値を使用して、準備したレイアウトを表示してください。

  3. ユーザーが[RELOAD]ボタンをクリックする場合は、mbErrorOccuredをfalseに設定します。そして、mbReloadPressedをtrueに設定します。
  4. mbErrorOccuredがfalseでmbReloadPressedがtrueの場合、webviewがページを正常にロードしたことを意味します。'エラーが再び発生した場合、onReceivedError(...)でmbErrorOccuredがtrueに設定されます

これが私の完全なソースです。これをチェックしてください。

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

追加:ここにレイアウトがあります...

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


リソースファイルを共有していただけますか?私は初心者です。
Rajan Rawal 2015

@RajanRawalレイアウトの例を編集して追加しました。:)
cmcromance 2015

プログレスバーは表示されませんが、コードは表示されます。:-(
Rajan Rawal

7

Android WebView onReceivedError()のディスカッションをチェックしてください。かなり長いですが、コンセンサスはa)「利用できないWebページ」ページの表示を停止できないことですが、b)onReceivedErrorが発生した後は常に空のページをロードできます。


これらの人たちはonReceivedErrorまったくトリガーしないことについて話している。インターネット接続がない場合、コードで正しくトリガーされます。
ジョジョ

7

Webviewが一部のカスタムビューに埋め込まれているため、ユーザーがWebviewではなくネイティブビューを表示しているとほとんど信じている場合、そのようなシナリオで「ページを読み込めませんでした」というエラーが表示されます。そのような状況で私が通常行うことは、以下のように空白のページをロードしてトーストメッセージを表示することです

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

2

GETリクエストを使用してページコンテンツを取得し、を使用してそのデータを表示Webviewできます。これにより、複数のサーバー呼び出しを使用しなくなります。オブジェクトの有効性Javascriptをチェックするために使用できる代替手段DOM


それは良い考えですが、このようなことをする必要があるのは本当に残念です...
Jeffrey Blattman

2

多分私は質問を誤解しているかもしれませんが、あなたはあなたがエラーを受け取ったコールバックを受け取ると言っているように聞こえます、そしてあなたはただエラーを表示しないための最良の方法は何を求めているのですか?画面からWebビューを削除したり、その上に別のビューを表示したりしてみませんか?


2

ここで私は最も簡単な解決策を見つけました。これをチェック

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

そして、これが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;
}

1

これを主張する場合は、loadURL関数を呼び出す前にリソースが存在するかどうかを確認するだけでよいと思います。単に関数をオーバーライドし、super()を呼び出す前にチェックを行います

備考(おそらくトピック外):httpには、HEADというメソッドがあり、次のように説明されています。

HEADメソッドは、サーバーが応答でメッセージ本文を返してはならないことを除いて、GETと同じです。

この方法は便利かもしれません。とにかく、それをどのように実装するか...このコードを確認してください:

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

あなたは使用してこのチェックを試すことができます

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

6
実際にアクセスする前にリソースが存在するかどうかを確認すると、1つの仮想リクエストに対して2つの物理リクエストがあるため、サーバーの負荷が2倍になります。これは少しやり過ぎのようです。
ジョジョ

絶望的な対策!
Sherif elKhatib 2011

1
とにかく、まだオーバーロードしてhtmlコンテンツを取得できます。エラーがあるかどうかを確認してください。解析および表示しない場合
Sherif elKhatib '10 / 07/11

実際にこれをどのように実装しますか?
ジョジョ

@JoJo、実際にはこのメソッドは、HEAD応答を返すオーバーヘッドが304または500応答を返すよりもはるかに小さいため、無効なURLが発生した場合のサーバーの負荷を軽減します。
ジャスティンシールド

0

エラー処理に使用しているものにWebページを変更します。

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

これはすべてhttp://developer.android.com/reference/android/webkit/WebView.htmlにあります


0

私は今日、これらの苛立たしいGoogleエラーページを破棄するというこの問題に取り組んできました。上記および他の多くのフォーラムで見られるAndroidのサンプルコードで可能です(私が知っている方法を尋ねてください)。

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

もう1つのWebクライアントとしてshouldOverrideUrlLoading()に配置した場合。少なくとも、これは私の2.3.6デバイスで動作します。他のどこで機能するかは後で確認します。それは今私を落ち込ませるだけだろう、私は確信している。goBackビットは私のものです。あなたはそれを望まないかもしれません。


0

これを試して

 @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の可視性を0(view.INVISIBLE)に設定して、メッセージを表示できます。このコードは、ロリポップで実行する私のアプリで機能します。

@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

私はこの問題に直面しなければならず、さまざまな視点からそれを解決しようとしました。最後に、単一のフラグを使用してエラーが発生したかどうかを確認することで解決策を見つけました。

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

このようにして、エラーが発生するたびにページを非表示にし、ページが適切に再度読み込まれたときにページを表示します。

また、ケースに小さな遅延が追加されました。

ナビゲーション履歴に新しいページを追加するため、後でwebview.reload()を実行できないため、空のページをロードするソリューションは避けました。



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.