17

I have created a WebView layout, which is used to access a specific website, however it would be useful to edit or create a custom "Web page not available" resource when a handset doesn't have a network connection or the page times out. I know it's possible because if you open the app "Wikidroid" while a handset is in Airplane mode you receive "Article not available" error page instead of the standard Android "Web page not available" error page.

I have search high and low on the internet and haven't come up with any online resources which address this request. Any and all help is much appreciated. Thanks in advance.

Gopal Singh Sirvi
  • 4,539
  • 5
  • 33
  • 55
Sid 6x
  • 173
  • 1
  • 1
  • 5

3 Answers3

20

To determine when the device has a network connection, request the permission <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> and then you can check with the following code. First define these variables as class variables.

private Context c;
private boolean isConnected = true;

In your onCreate() method initialize c = this;

Then check for connectivity.

ConnectivityManager connectivityManager = (ConnectivityManager)
    c.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
    NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
    if (ni.getState() != NetworkInfo.State.CONNECTED) {
        // record the fact that there is not connection
        isConnected = false;
    }
}

Then to intercept the WebView requets, you could do something like the following. If you use this, you will probably want to customize the error messages to include some of the information that is available in the onReceivedError method.

final String offlineMessageHtml = "DEFINE THIS";
final String timeoutMessageHtml = "DEFINE THIS";

WebView browser = (WebView) findViewById(R.id.webview);
browser.setNetworkAvailable(isConnected);
browser.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (isConnected) {
            // return false to let the WebView handle the URL
            return false;
        } else {
            // show the proper "not connected" message
            view.loadData(offlineMessageHtml, "text/html", "utf-8");
            // return true if the host application wants to leave the current 
            // WebView and handle the url itself
            return true;
        }
    }
    @Override
    public void onReceivedError (WebView view, int errorCode, 
        String description, String failingUrl) {
        if (errorCode == ERROR_TIMEOUT) {
            view.stopLoading();  // may not be needed
            view.loadData(timeoutMessageHtml, "text/html", "utf-8");
        }
    }
});
Brian
  • 16,196
  • 3
  • 27
  • 28
  • I took a look at the errors you mentioned and updated my answer to address them. You may want to become more familiar with Java before going too far with an Android project. A good Java foundation will help immensely when debugging these small errors and trying to spot problems. Let me know if you encounter any other issues with this. – Brian Nov 19 '10 at 07:35
  • 2
    Brian, thank you for taking a look at the code I GREATLY appreciate your assistance. I ended up using the "onReceivedError" code and instead of loading a "timeoutMessageHtml" string, I have the app "setContentView()" to a new linear layout that I created which has a custom error message. Also, you are 100% correct regarding having a good Java foundation. I've read a couple Java books and I'm currently taking a Java class, however I learn best by doing, so I figured what better way to learn Java than creating an app. Thx again. – Sid 6x Nov 23 '10 at 01:45
  • I found that this code would crash if the device had wifi and 3G turned off, the example here worked for me: http://www.androidsnippets.com/check-if-the-network-is-available – Jag Apr 11 '12 at 17:57
  • 1
    Why such a complex solution if you can just override `WebViewClient`'s built-in `onReceivedError()`? – caw Jun 18 '13 at 20:27
  • When just using `onReceivedError()`, you cannot detect if there is any connectivity. Simply reacting to an error is less desirable than anticipating it and having more information to be able to suggest a solution. – Brian Jun 20 '13 at 23:01
  • Comment by [Sharats.com](https://stackoverflow.com/users/7495214/sharats-com), incorrectly posted in [answer](https://stackoverflow.com/a/46403489/5292302) *"@Brian, provided URL has been updated to http://www.androidsnippets.com/check-if-the-network-is-available.html* – Petter Friberg Sep 25 '17 at 11:16
10

Marco W. is correct.

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

    }
});
andrewsi
  • 10,807
  • 132
  • 35
  • 51
Cain
  • 109
  • 1
  • 2
  • 19
    This will not look good on most devices. The standard error page is rendered before the call to onReceivedError(). As a result, the standard error page is visible for a couple of milliseconds until the custom page has loaded. – Robert Sep 10 '14 at 15:18
0

I have tried using all the above solutions but none of them are working. Twisted my code a little bit and have got the solution:

package com.samnjor.tipsmaster;

import android.content.Context; import android.graphics.Bitmap;
import android.net.ConnectivityManager; import
android.net.NetworkInfo; import
android.support.v7.app.AppCompatActivity; import android.os.Bundle;
import android.view.View; import android.webkit.WebSettings; import
android.webkit.WebView; import android.webkit.WebViewClient; import
android.widget.ProgressBar; import android.widget.TextView;

import com.google.android.gms.ads.AdListener; import
com.google.android.gms.ads.AdRequest; import
com.google.android.gms.ads.InterstitialAd;

public class TodayTips extends AppCompatActivity {
    String ShowOrHideWebViewInitialUse = "show";
    private WebView webview ;
    private ProgressBar spinner;
    private String TAG = TodayTips.class.getSimpleName();
    InterstitialAd mInterstitialAd;
    final String noconnectionHtml = "Failed to connect ot the internet";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_today_tips);
        mInterstitialAd = new InterstitialAd(this);

        // set the ad unit ID
        mInterstitialAd.setAdUnitId(getString(R.string.adbig));

        AdRequest adRequest = new AdRequest.Builder()
                .build();

        // Load ads into Interstitial Ads
        mInterstitialAd.loadAd(adRequest);

        mInterstitialAd.setAdListener(new AdListener() {
            public void onAdLoaded() {
                showInterstitial();
            }
        });
    }

    private void showInterstitial() {
        if (mInterstitialAd.isLoaded()) {
            mInterstitialAd.show();
        }

        webview =(WebView)findViewById(R.id.webView);
        spinner = (ProgressBar)findViewById(R.id.progressBar1);
        webview.setWebViewClient(new CustomWebViewClient());

        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings().setDomStorageEnabled(true);
        webview.setOverScrollMode(WebView.OVER_SCROLL_NEVER);

        if(haveNetworkConnection()){
            webview.loadUrl("http://you domain here");
        } else {


            webview.loadData(noconnectionHtml, "text/html", "utf-8"); //
        }
    }
    private boolean haveNetworkConnection() {
        boolean haveConnectedWifi = false;
        boolean haveConnectedMobile = false;

        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if (ni.getTypeName().equalsIgnoreCase("WIFI"))
                if (ni.isConnected())
                    haveConnectedWifi = true;
            if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
                if (ni.isConnected())
                    haveConnectedMobile = true;
        }
        return haveConnectedWifi || haveConnectedMobile;

    }

    // This allows for a splash screen
    // (and hide elements once the page loads)
    private class CustomWebViewClient extends WebViewClient {

        @Override
        public void onPageStarted(WebView webview, String url, Bitmap favicon) {

            // only make it invisible the FIRST time the app is run
            if (ShowOrHideWebViewInitialUse.equals("show")) {
                webview.setVisibility(webview.INVISIBLE);
            }
        }

        @Override
        public void onPageFinished(WebView view, String url) {

            ShowOrHideWebViewInitialUse = "hide";
            spinner.setVisibility(View.GONE);

            view.setVisibility(webview.VISIBLE);
            super.onPageFinished(view, url);

        }
    }`` }
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Samnjor
  • 1
  • 1