1

I'm trying to check for INTERNET connectivity from an Android app but just keep running in to problems.

I'm NOT looking for code that tests for an available network connection - I've got that bit working - this is to test whether I can reach an internet site or not.

(I appreciate that if I am behind a system which presents a logon screen instead of the requested site, I may not get the exact result I want, but I will handle that later)

Thanks to the following question I think I've made some progress, but when I run the app it crashes out (error info below).

The code I have so far is as follows (and I must admit that I find the try/catch stuff a bit puzzling and tedious :-/ )

static public boolean isInternetReachable() {
    int statusCode = -1;
    try{
        URL url = new URL("http://www.google.com/humans.txt");
        HttpURLConnection http = (HttpURLConnection) url.openConnection();
        statusCode = http.getResponseCode();
        http.disconnect();
    } catch (MalformedURLException ex) {
        return false;
    } catch (IOException ex) {
        return false;
    }
    if (statusCode == HttpURLConnection.HTTP_OK) {
        return true;
    }
    else
    {
        //connection is not OK
        return false;
    }
}

I'm sure there are neater ways to do this and so any general advice is welcome.

The error that I'm getting when the app crashes is:

01-24 19:53:14.767 10617-10617/com.nooriginalthought.bluebadgeparking E/AndroidRuntime:
     FATAL EXCEPTION: main
     Process: com.nooriginalthought.bluebadgeparking, PID: 10617
     java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nooriginalthought.bluebadgeparking/com.nooriginalthought.bluebadgeparking.PreLoadChecks}: android.os.NetworkOnMainThreadException
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2411)
         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
         at android.app.ActivityThread.access$800(ActivityThread.java:144)
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
         at android.os.Handler.dispatchMessage(Handler.java:102)
         at android.os.Looper.loop(Looper.java:155)
         at android.app.ActivityThread.main(ActivityThread.java:5696)
         at java.lang.reflect.Method.invoke(Native Method)
         at java.lang.reflect.Method.invoke(Method.java:372)
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
     Caused by: android.os.NetworkOnMainThreadException
         at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1155)
         at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
         at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
         at java.net.InetAddress.getAllByName(InetAddress.java:215)
         at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
         at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:236)
         at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
         at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
         at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
         at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)
         at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)
         at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:491)
         at com.nooriginalthought.bluebadgeparking.PreLoadChecks.isInternetReachable(PreLoadChecks.java:41)
         at com.nooriginalthought.bluebadgeparking.PreLoadChecks.onCreate(PreLoadChecks.java:70)
         at android.app.Activity.performCreate(Activity.java:5958)
         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474) 
         at android.app.ActivityThread.access$800(ActivityThread.java:144) 
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359) 
         at android.os.Handler.dispatchMessage(Handler.java:102) 
         at android.os.Looper.loop(Looper.java:155) 
         at android.app.ActivityThread.main(ActivityThread.java:5696) 
         at java.lang.reflect.Method.invoke(Native Method) 
         at java.lang.reflect.Method.invoke(Method.java:372) 
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028) 
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 
Fat Monk
  • 2,077
  • 1
  • 26
  • 59
  • Thanks David. I'm finding the error reporting in Android Studio (my only experience of Java, so it could be common to all Java IDEs / compilers) - even identifying which error is the one to look for is proving to be a struggle right now, but pointers like this are helping me filter out the additional info and focus in on what is the root cause exception. – Fat Monk Jan 24 '16 at 20:37

1 Answers1

1

As David is mentioning in the comments, you should just Google for the Exception name and try to get a turnaround by yourself.

By looking at the StackOverflow answer that he is referring to, you need to make all network communications outside the Main thread. The most used way to do this is by creating an AsyncTask.

In your case, it would look (you can create a new InternetTask.java or just append it to your current MainActivity.java) something like:

class InternetTask extends AsyncTask<Void, Void, Boolean>{
    private MainActivity activity;

    InternetTask(MainActivity activity){
        this.activity = activity;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        int statusCode = -1;
        try{
            URL url = new URL("http://www.google.com/humans.txt");
            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            statusCode = http.getResponseCode();
            http.disconnect();
        } catch (MalformedURLException ex) {
            return false;
        } catch (IOException ex) {
            return false;
        }
        if (statusCode == HttpURLConnection.HTTP_OK) {
            return true;
        }
        else
        {
            //connection is not OK
            return false;
        }
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        activity.receiveMagic(aBoolean);
    }
}

Then, you just need to add a new public method in your activity to receive the boolean in your MainActivity.

public void receiveMagic(Boolean isGood){
    if (isGood){
        Toast.makeText(MainActivity.this, "It is good", Toast.LENGTH_SHORT).show();
    }else {
        Toast.makeText(MainActivity.this, "It is not connected", Toast.LENGTH_SHORT).show();
    }
}

And you would need to call your new AsyncTask from your Activity with:

new InternetTask(this).execute();

Make sure you add the internet permission to your Manifest also.

Community
  • 1
  • 1
Evin1_
  • 12,292
  • 9
  • 45
  • 47
  • 1
    Wow, every time I feel I'm getting somewhere with Java it throws a curve-ball and makes things even more complex. I can understand the reasoning for not blocking the UI thread, but I cannot for the life of me figure out how this would fit into what I'm trying to do (check for active network connection, then check for internet access, then check for a specific response from a specific URL before proceeding to launch the main app activity). – Fat Monk Jan 24 '16 at 21:19
  • 1
    After a bit of thought, this answer has explained what I failed to understand in linked duplicate. Your explanation here made things much more understandable as it is not confused by the RSS concerns in the duplicate. – Fat Monk Jan 24 '16 at 21:52