Check network connection and internet availability in Android Android 13.10.2016

android_check_network.png

Before you perform any network operations, you must first check that are you connected to that network or internet etc.

In android we can check internet connectivity using ConnectivityManager class. We need to instantiate an object of ConnectivityManager class by calling getSystemService() method.

After this we can get information of all networks using getAllNetworkInfo() method. This method will return an array of NetworkInfo type.

First we need following permission in order to access network state. Add following permission to your AndroidManifest.xml file.

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

Following is simple snippet for network connection check

public static boolean isNetworkConnected(Context ctx) {
    ConnectivityManager cm = (ConnectivityManager) 
                                  ctx.getSystemService (Context.CONNECTIVITY_SERVICE);
    NetworkInfo ni = cm.getActiveNetworkInfo();
    return ni != null && ni.isConnectedOrConnecting();
}

Once you instantiate the object of ConnectivityManager class, you can use getAllNetworkInfo method to get the information of all the networks. This method returns an array of NetworkInfo. Or you can use getActiveNetworkInfo() to get info about active network.

public static int TYPE_WIFI = 1;
public static int TYPE_MOBILE = 2;
public static int TYPE_NOT_CONNECTED = 0;

public static int getConnectivityStatus(Context ctx) {
    ConnectivityManager cm = (ConnectivityManager) 
                                  ctx.getSystemService (Context.CONNECTIVITY_SERVICE);

    NetworkInfo ni = cm.getActiveNetworkInfo();
    if (null != ni) {
        if(ni.getType() == ConnectivityManager.TYPE_WIFI)
            return TYPE_WIFI;

        if(ni.getType() == ConnectivityManager.TYPE_MOBILE)
            return TYPE_MOBILE;
    }
    return TYPE_NOT_CONNECTED;
}

Following method checks if device is connected to internet (there is a possibility it's connected to a network but not to internet).

public static boolean isInternetAvailable() {
    Boolean isConnection = false;
    int connectTimeout = 5000; // in ms
    int readTimeout = 5000; // in ms
    String ip204 = "http://clients3.google.com/generate_204";

    try {
        URL url = new URL(ip204);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(connectTimeout);
        conn.setReadTimeout(readTimeout);
        conn.setRequestMethod("HEAD");
        InputStream in = conn.getInputStream();
        int status = conn.getResponseCode();
        in.close();
        conn.disconnect();
        if (status == HttpURLConnection.HTTP_NO_CONTENT) {
            isConnection = true;
        }
    } catch (Exception e) {
        isConnection = false;
    }
}

Example of MainActivity which shows result for network connection and internet available

public class MainActivity extends AppCompatActivity {
    TextView tvN, tvI;

    private class TaskIsInternetAvailable extends AsyncTask<String, Void, Boolean> {
        protected Boolean doInBackground(String... args) {
            Boolean result = NetworkUtil.isInternetAvailable();
            return result;
        }

        protected void onPostExecute(Boolean result) {
            Toast.makeText(MainActivity.this, String.valueOf(result), Toast.LENGTH_SHORT).show();
            tvI.setText("Internet connected");
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvN = (TextView) findViewById(R.id.network);
        tvI = (TextView) findViewById(R.id.internet);

        if (NetworkUtil.isNetworkConnected(this)) {
            tvN.setText("Network connected");

            TaskIsInternetAvailable task = new TaskIsInternetAvailable();
            task.execute();
        }
    }
}

We can also use RxJava2 for asynchronous request. Let's enable lambda and include RxJava2 in your build.gradle file:

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    implementation 'io.reactivex.rxjava2:rxjava:2.1.13'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
}

Following is a example of Disposable and Observable.

public class MainActivity extends AppCompatActivity  {
    Disposable disposableData;
    Observable<Pair<Boolean, Integer>> obsIsInternetAvailable = Observable.fromCallable(
         new Callable<Pair<Boolean, Integer>>() {
        @Override
        public Pair<Boolean, Integer> call() {
            Boolean isConnection = false;
            int connectTimeout = 5000; // in ms
            int readTimeout = 5000; // in ms
            String ip204 = "http://clients3.google.com/generate_204";

            long startTime = System.currentTimeMillis();

            try {
                URL url = new URL(ip204);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(connectTimeout);
                conn.setReadTimeout(readTimeout);
                conn.setRequestMethod("HEAD");
                InputStream in = conn.getInputStream();
                int status = conn.getResponseCode();
                in.close();
                conn.disconnect();
                if (status == HttpURLConnection.HTTP_NO_CONTENT) {
                    isConnection = true;
                }
            } catch (Exception e) {
                isConnection = false;
            }

            long endTime = System.currentTimeMillis();

            return new Pair(isConnection, endTime - startTime);
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        disposableData = obsIsInternetAvailable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    result -> {
                        Log.d(TAG, "Items: " + result);
                    },
                    err -> err.printStackTrace()
                    );        
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (disposableData != null && !disposableData.isDisposed()) {
            disposableData.dispose();
        }
    }                        
}

Broadcast Receiver to handle changes in network state

You can easily handle the changes in network state by creating your own Broadcast Receiver. Following is a broadcast receiver class where we handle the changes in network.

Check onReceive() method. This method will be called when state of network changes. Here we are just creating a Toast message and displaying current network state. You can write your custom code in here to handle changes in connection state.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        int status = NetworkUtil.getConnectivityStatus(context);
        Toast.makeText(context, "STATUS: " + String.valueOf(status), Toast.LENGTH_LONG).show();
    }
}

Once we define our BroadcastReceiver, we need to define the same in AndroidMenifest.xml file. Add following to your menifest file.

<application  ...>
     ...
        <receiver
            android:name="me.proft.NetworkChangeReceiver"
            android:label="NetworkChangeReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>
      ...
</application>

We defined our broadcast receiver class in menifest file. Also we defined a intent CONNECTIVITY_CHANGE. Thus this will register our receiver for given intents. Whenever there is change in network state, android will fire these intents and our broadcast receiver will be called.

Using BroadcastReceiver from Activity

In this section I show how to instantiate a BroadcastReceiver in an Activity.

Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="STATUS: ?"
        android:layout_gravity="center"
        android:textSize="40dp"/>
</LinearLayout>

Activity

public class SevenActivity extends AppCompatActivity {
    TextView tvStatus;
    private BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_seven);

        tvStatus = (TextView) findViewById(R.id.tvStatus);
        setStatus();
    }

    @Override
    protected void onResume() {
        super.onResume();

        IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                setStatus();
            }
        };
        this.registerReceiver(receiver, intentFilter);
    }


    public void setStatus() {
        tvStatus.setText("STATUS: " + Utils.isNetworkConnected(this));
    }

    @Override
    protected void onPause() {
        super.onPause();
        this.unregisterReceiver(this.receiver);
    }
}

Result

android_receiver_activity

Broadcast Receiver to handle changes in WiFi state

We can cehck WiFi state via BroadcastReceiver class. The onReceive method of the BroadcastReceiver will be called each time there is a change in the WiFi state. The following code shows a basic implementation:

BroadcastReceiver wifiStatusReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {);
        SupplicantState supState;
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        supState = wifiInfo.getSupplicantState();
        if (supState.equals(SupplicantState.COMPLETED)) {
            // wifi is connected
        } else if (supState.equals(SupplicantState.SCANNING)) {
            // no wifi is available, but scanning is in progress
        } else if (supState.equals(SupplicantState.DISCONNECTED)) {
            // wifi not connected
        }
    }
};

Each time you implement a BroadcastReceiver, you need to register it in the onResume method of your app and unregister it in the onPause method, as follows:

@Override
protected void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
    this.registerReceiver(wifiStatusReceiver, filter);
}

@Override
public void onPause() {
    this.unregisterReceiver(wifiStatusReceiver);
    super.onPause();
}