9

I've been working on this for a couple of days now. I just started working with Android. I have a 2 part question. i want to check if internet is available. If it is launch the webView if not give an alert and prevent webView from loading. I have tried this but it force closes if there is not internet connection(e.g. airplane mode). How do I get it to give a message and stop loading the webview. Also is there a way to continuously check for connection so that the webpage 404 is not shown when it loses connection?

Here is my code.

    public class MainActivity extends Activity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        android.net.NetworkInfo wifi = cm
                .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        android.net.NetworkInfo datac = cm
                .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        if ((wifi != null & datac != null)
                && (wifi.isConnected() | datac.isConnected())) {
            setContentView(R.layout.activity_main);
                 }else{
                //no connection
                  Toast toast = Toast.makeText(MainActivity.this, "No Internet Connection", Toast.LENGTH_LONG);
                  toast.show();  
        }

        CookieManager cookieManager = CookieManager.getInstance(); 
        cookieManager.setAcceptCookie(true); 

        webView = (WebView) findViewById(R.id.webview);
        webView.setWebViewClient(new MyWebViewClient());
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("http://mysite.com/?ma=1");
    }   
        private class MyWebViewClient extends WebViewClient {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (Uri.parse(url).getHost().equals("mysite.com")) {
                    return false;
                }
                // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(intent);
                return true;
            }
        }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // Check if the key event was the Back button and if there's history
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        // If it wasn't the Back key or there's no web page history, bubble up to the default
        // system behavior (probably exit the activity)
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch (item.getItemId()) 
        {
            case R.id.logout:
                finish();
                return true;
        }
      return false;
    }


}

Edit: Added Errors To be specific, I get these errors when pressing back after it shows the Toast saying there is no internet connect. It crashes if I use the back button after the toast message and the errors are below.

04-07 14:40:38.664: E/AndroidRuntime(15173): FATAL EXCEPTION: main
04-07 14:40:38.664: E/AndroidRuntime(15173): java.lang.NullPointerException
04-07 14:40:38.664: E/AndroidRuntime(15173):    at com.mysite.testapp.MainActivity.onKeyDown(MainActivity.java:67)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.view.KeyEvent.dispatch(KeyEvent.java:2705)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.app.Activity.dispatchKeyEvent(Activity.java:2401)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2007)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3813)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3761)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2926)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.os.Looper.loop(Looper.java:137)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at android.app.ActivityThread.main(ActivityThread.java:4918)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at java.lang.reflect.Method.invokeNative(Native Method)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at java.lang.reflect.Method.invoke(Method.java:511)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
04-07 14:40:38.664: E/AndroidRuntime(15173):    at dalvik.system.NativeStart.main(Native Method)
Panama Jack
  • 24,158
  • 10
  • 63
  • 95
  • you are getting null pointer exception coz your webview is null. You set view only if internet is available. When internet is not available you display toast. but you are not setting the view. – Raghunandan Apr 07 '13 at 20:04

2 Answers2

28

To check Network connection availability use the below

    public class CheckNetwork {


private static final String TAG = CheckNetwork.class.getSimpleName();



public static boolean isInternetAvailable(Context context)
{
    NetworkInfo info = (NetworkInfo) ((ConnectivityManager)
    context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();

    if (info == null)
    {
         Log.d(TAG,"no internet connection");
         return false;
    }
    else
    {
        if(info.isConnected())
        {
            Log.d(TAG," internet connection available...");
            return true;
        }
        else
        {
            Log.d(TAG," internet connection");
            return true;
        }

    }
}
    }

In your Activity

              if(CheckNetwork.isInternetAvailable(Activity.this)) //returns true if internet available
                {

                        //do something. loadwebview.
                }   
               else
                {
                    Toast.makeText(Activity.this,"No Internet Connection",1000).show();
                }  

On back button press

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if(event.getAction() == KeyEvent.ACTION_DOWN){
        switch(keyCode)
        {
        case KeyEvent.KEYCODE_BACK:
            if(mWebView.canGoBack() == true){
                mWebView.goBack();
            }else{
                finish();
            }
            return true;
        }

    }
    return super.onKeyDown(keyCode, event);
   }

Update : if you need to check network connection availability at all times, System broadcasts events when there is connectivity change or loss of connectivity. You can capture those broadcasts in your activity by registering for the broadcast. But you need to unregister when not required.

An example is at the below Link.

Android service to check internet connectivity?.

Or you can use a service that checks internet connectivity in the background. But you need to destroy the service when not required. But service is used for running long running operations in background

Update 2:

Try the below. I have tested. It works on my Samsung Galaxy S3.

Add these permissions in manifest

        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Your activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity" >

 <WebView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:id="@+id/wv"/>

</RelativeLayout>

Your activity

 public class MainActivity extends Activity {

 private WebView webView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.wv);
        if(CheckNetwork.isInternetAvailable(MainActivity.this))
        {
        CookieManager cookieManager = CookieManager.getInstance(); 
        cookieManager.setAcceptCookie(true); 

      // webView = (WebView) findViewById(R.id.wv);
       // webView.setWebViewClient(new MyWebViewClient());
        webView.getSettings().setJavaScriptEnabled(true);
        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%
                MainActivity.this.setProgress(progress * 1000);
               }
             });
             webView.setWebViewClient(new WebViewClient() {
               public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                 Toast.makeText(MainActivity.this, "Oh no! " + description, Toast.LENGTH_SHORT).show();
               }
             });

             webView.loadUrl("http://slashdot.org/");
             }
     else{
            //no connection
              Toast toast = Toast.makeText(MainActivity.this, "No Internet Connection", Toast.LENGTH_LONG);
              toast.show();  
    }


}   



@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
        webView.goBack();
        return true;
    }
    else
    {
        finish();
    }
    return super.onKeyDown(keyCode, event);
}
}
Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • Thanks but the app still crashes using back with your code as well. – Panama Jack Apr 07 '13 at 19:12
  • in on press backbutton check if webView is null or not. Coz according to logcat its a nullpointer exception. My guess your webview is null – Raghunandan Apr 07 '13 at 19:14
  • So I took out the webView check and it will then close the app. So somehow it still is trying to use webView when pressing back. The if statement doesn't seem to be working. – Panama Jack Apr 07 '13 at 19:30
  • @Pjack check the update it works. In your activity set the view. get the id of webview . then check if network available if yes proceed and display. else display a message. On press back button if history goback else finish activity. – Raghunandan Apr 07 '13 at 19:57
  • Thanks I tried it but it still crashes when i hit the back button after the toast disappears with the same errors I posted earlier. What am I doing wrong? I'm testing on a Samsung Galaxy S3. – Panama Jack Apr 07 '13 at 20:04
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27737/discussion-between-raghunandan-and-pjack) – Raghunandan Apr 07 '13 at 20:06
  • Wait Did yo put the onKeyDown inside the OnCreate method? – Panama Jack Apr 07 '13 at 20:06
  • no i have not put the onKeyDown in oncreate. may be while copy pasting i missed a curly brace. But the above update 2 should work properly. repasted the code. Check now – Raghunandan Apr 07 '13 at 20:10
  • Question : Why do you return true even if info.isConnected() returns false? – Juan Carlos Ospina Gonzalez Sep 27 '13 at 08:00
1

To keep you application from crashing move all the code that defines the WebView to the place where you check your internet connection, Like this:

....
if ((wifi != null & datac != null) && (wifi.isConnected() || datac.isConnected())) 
{
    setContentView(R.layout.activity_main);
    webView = (WebView) findViewById(R.id.webview);
    webView.setWebViewClient(new MyWebViewClient());
    webView.getSettings().setJavaScriptEnabled(true);
    webView.loadUrl("http://mysite.com/?ma=1");
}
else
{
   //no connection
    Toast toast = Toast.makeText(MainActivity.this, "No Internet Connection",Toast.LENGTH_LONG);
    toast.show();  
}
.....

Now, if your application constantly needs internet connection I would suggest to you to create a Service that will constantly check for this connection, and when it exists this Service will fire a broadcast to the listening parties.

UPDATE:

You are receiving an error because of this line:

webView.goBack();

If there was no internet connection and the WebView was not instantiated then you can't goBack() in it because this null, here you need to check:

if (webView != null)
{
     webView.goBack(); 
}

And there is nothing hard in setting the alternative view: 1. Open the visual editor and create an ImageView with the same size as your webview. 2. Then do this:

....
if ((wifi != null & datac != null) && (wifi.isConnected() || datac.isConnected())) 
{
    imageView.setVisibility(View.GONE);
    setContentView(R.layout.activity_main);
    webView = (WebView) findViewById(R.id.webview);
    webView.setWebViewClient(new MyWebViewClient());
    webView.getSettings().setJavaScriptEnabled(true);
    webView.loadUrl("http://mysite.com/?ma=1");
}
else
{
   imageView.setVisibility(View.VISIBLE); 
   //no connection
    Toast toast = Toast.makeText(MainActivity.this, "No Internet Connection",Toast.LENGTH_LONG);
    toast.show();  
}
.....

of course you would have to find this view by id first before you can manipulate it.

Emil Adz
  • 40,709
  • 36
  • 140
  • 187
  • Ok, that helped but it just gives the toast and stays at a white screen and if you use the back button, it hangs and force closes. Anyway to not crash trying to exit the app using the back and maybe show a logo in place of that plain white screen? – Panama Jack Apr 07 '13 at 18:32
  • Could you show the logcat message when it crash. and you could create an alternative ImageView and just play with the visibility of those view according to the internet connection status. – Emil Adz Apr 07 '13 at 18:34
  • you make it sound so easy to add the alternative view. Any examples anywhere? Also I pasted the errors above I get when using Back. – Panama Jack Apr 07 '13 at 18:46
  • 1
    If you use service remember to destroy it when not required. – Raghunandan Apr 07 '13 at 19:01
  • It still chokes pressing back. Weird. I put in the condition statement to check if webview is null but it still crashes. Any other ideas? Ok I will check out the imageView, thanks for the updated answer. – Panama Jack Apr 07 '13 at 19:11
  • I never worked with WebView but you can check this method @Raghunandan has provided: if(mWebView.canGoBack() == true){mWebView.goBack();} – Emil Adz Apr 07 '13 at 19:13