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