How to detect when WIFI Connection has been established in Android?

AndroidAndroid Wifi

Android Problem Overview


I need to detect when I have network connectivity over WIFI. What broadcast is sent to establish that a valid network connection has been made. I need to validate that a valid network connection for HTTP exists. What should I listen for and what additional tests do I need to make to know that a valid connection exists.

Android Solutions


Solution 1 - Android

You can register a BroadcastReceiver to be notified when a WiFi connection is established (or if the connection changed).

Register the BroadcastReceiver:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

And then in your BroadcastReceiver do something like this:

@Override
public void onReceive(Context context, Intent intent) {
    final String action = intent.getAction();
    if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
        if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
            //do stuff
        } else {
            // wifi connection was lost
        }
    }
}

For more info, see the documentation for BroadcastReceiver and WifiManager

Of course you should check whether the device is already connected to WiFi before this.

EDIT: Thanks to ban-geoengineering, here's a method to check whether the device is already connected:

private boolean isConnectedViaWifi() {
     ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
     NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 	
     return mWifi.isConnected();
}

Solution 2 - Android

The best that worked for me:

###AndroidManifest

<receiver android:name="com.AEDesign.communication.WifiReceiver" >
   <intent-filter android:priority="100">
      <action android:name="android.net.wifi.STATE_CHANGE" />
   </intent-filter>
</receiver>

###BroadcastReceiver class

public class WifiReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {

      NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
      if(info != null && info.isConnected()) {
        // Do your work. 

        // e.g. To check the Network Name or other info:
        WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        String ssid = wifiInfo.getSSID();
      }
   }
}

###Permissions

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

Solution 3 - Android

For me only WifiManager.NETWORK_STATE_CHANGED_ACTION works.

Register a broadcast receiver:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

and receive:

@Override
public void onReceive(Context context, Intent intent) {

    final String action = intent.getAction();
    
    if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
        NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
        boolean connected = info.isConnected();
	
        //call your method
    }      
}

Solution 4 - Android

Answer given by user @JPM and @usman are really very useful. It works fine but in my case it come in onReceive multiple time in my case 4 times so my code execute multiple time.

I do some modification and make as per my requirement and now it comes only 1 time

Here is java class for Broadcast.

public class WifiReceiver extends BroadcastReceiver {

String TAG = getClass().getSimpleName();
private Context mContext;

@Override
public void onReceive(Context context, Intent intent) {

	mContext = context;


	if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();

		if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
				networkInfo.isConnected()) {
			// Wifi is connected
			WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
			WifiInfo wifiInfo = wifiManager.getConnectionInfo();
			String ssid = wifiInfo.getSSID();
			
			Log.e(TAG, " -- Wifi connected --- " + " SSID " + ssid );

		}
	}
	else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION))
	{
		int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
		if (wifiState == WifiManager.WIFI_STATE_DISABLED)
		{
			Log.e(TAG, " ----- Wifi  Disconnected ----- ");
		}

	}
}
}

In AndroidManifest

<receiver android:name=".util.WifiReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </receiver>


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

Solution 5 - Android

You can start a wifi connection if you give the user a choice to override the normal behavior of asking each time.

I choose to use three methods...

public boolean isOnline() 
{
 ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
 NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
 return (networkInfo != null && networkInfo.isConnected());
}  

This is quick check if there is an internet connect either Wifi or CellData. From here you can choose what action you want to take. Is it in Airplane mode needs to be checked also.

On a separate thread. I set a variable IpAddress to = " " And poll until I have a valid an ip address.

  WifiManager wifi;
  wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
  WifiInfo wifiInfo = wifi.getConnectionInfo();
  int ipAddress = wifiInfo.getIpAddress();
  String ip = null;
  ip = String.format("%d.%d.%d.%d",
  (ipAddress & 0xff),
  (ipAddress >> 8 & 0xff),
  (ipAddress >> 16 & 0xff),
  (ipAddress >> 24 & 0xff));
  Log.e(" >>IP number Begin ",ip);

Another code snippet... If its not on turn it on (with users prior permission)

   if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);  

Solution 6 - Android

To detect WIFI connection state, I have used CONNECTIVITY_ACTION from ConnectivityManager class so:

   	IntentFilter filter=new IntentFilter();
    filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
   	registerReceiver(receiver, filter);

and from your BroadCastReceiver:

	if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
		int networkType = intent.getIntExtra(
				android.net.ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
		if (ConnectivityManager.TYPE_WIFI == networkType) {
			NetworkInfo networkInfo = (NetworkInfo) intent
					.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
			if (networkInfo != null) {
				if (networkInfo.isConnected()) {

					// TODO: wifi is connected
				} else {
					// TODO: wifi is not connected
				}
			}
		}

	}

ps:works fine for me:)

Solution 7 - Android

This code does not require permission at all. It is restricted only to Wi-Fi network connectivity state changes (any other network is not taken into account). The receiver is statically published in the AndroidManifest.xml file and does not need to be exported as it will be invoked by the system protected broadcast, NETWORK_STATE_CHANGED_ACTION, at every network connectivity state change.

AndroidManifest:

<receiver
    android:name=".WifiReceiver"
    android:enabled="true"
    android:exported="false">

    <intent-filter>
        <!--protected-broadcast: Special broadcast that only the system can send-->
        <!--Corresponds to: android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION-->
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>

</receiver>

BroadcastReceiver class:

public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/*
 Tested (I didn't test with the WPS "Wi-Fi Protected Setup" standard):
 In API15 (ICE_CREAM_SANDWICH) this method is called when the new Wi-Fi network state is:
 DISCONNECTED, OBTAINING_IPADDR, CONNECTED or SCANNING

 In API19 (KITKAT) this method is called when the new Wi-Fi network state is:
 DISCONNECTED (twice), OBTAINING_IPADDR, VERIFYING_POOR_LINK, CAPTIVE_PORTAL_CHECK
 or CONNECTED

 (Those states can be obtained as NetworkInfo.DetailedState objects by calling
 the NetworkInfo object method: "networkInfo.getDetailedState()")
*/
    /*
     * NetworkInfo object associated with the Wi-Fi network.
     * It won't be null when "android.net.wifi.STATE_CHANGE" action intent arrives.
     */
    NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

    if (networkInfo != null && networkInfo.isConnected()) {
        // TODO: Place the work here, like retrieving the access point's SSID

        /*
         * WifiInfo object giving information about the access point we are connected to.
         * It shouldn't be null when the new Wi-Fi network state is CONNECTED, but it got
         * null sometimes when connecting to a "virtualized Wi-Fi router" in API15.
         */
        WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
        String ssid = wifiInfo.getSSID();
    }
}
}

Permissions:

None

Solution 8 - Android

Android O removed the possibility to receive the implicit broadcasts for a wifi state change. So if your app is closed, you'll not be able to receive them. The new WorkManager has the ability to run when your app is closed, so I've experimented a bit with it and it seems to work quite well:

Add this to your dependencies:

implementation "android.arch.work:work-runtime:1.0.0-alpha08"

WifiConnectWorker.kt

class WifiConnectWorker : Worker() {

    override fun doWork(): Result {
        Log.i(TAG, "I think we connected to a wifi")
        return Result.SUCCESS
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        val workManager = WorkManager.getInstance()

        // Add constraint to start the worker when connecting to WiFi
        val request = OneTimeWorkRequest.Builder(WifiConnectWorker::class.java)
            .setConstraints(Constraints.Builder()
                .setRequiredNetworkType(UNMETERED)
                .build())
            .build()

        // The worker should be started, even if your app is closed
        workManager.beginUniqueWork("watch_wifi", REPLACE, request).enqueue()
    }
}

Keep in mind that this was just a quick test for a one-time notification. There is more work to do to always get notified when WiFi is turned on and off.

PS: When the app is force quit, the worker is not started, it seems WorkManager is canceling the requests then.

Solution 9 - Android

November 2020:

I have dealt too much with items deprecated by Google. Finally I found a solution to my particular requirement using "registerNetworkCallback" as Google currently suggests.

What I needed was a simple way to detect that my device has an IPv4 assigned in WIFI. (I haven't tried other cases, my requirement was very specific, but maybe this method, without deprecated elements, will serve as a basis for other cases).

Tested on APIs 23, 24 and 26 (physical devices) and APIs 28 and 29 (emulated devices).

    ConnectivityManager cm 
            = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder = new NetworkRequest.Builder();

    cm.registerNetworkCallback
            (
                    builder.build(),
                    new ConnectivityManager.NetworkCallback()
                    {
                        @Override
                        public void onAvailable(Network network)
                        {
                            //Actions to take with Wifi available.
                        }
                        @Override
                        public void onLost(Network network)
                        {
                            //Actions to take with lost Wifi.
                        }
                    }

            );

(Implemented inside "MainActivity.Oncreate")

Note: In manifest needs "android.permission.ACCESS_NETWORK_STATE"

Solution 10 - Android

Here is an example of my code, that takes into account the users preference of only allowing comms when connected to Wifi.

I am calling this code from inside an IntentService before I attempt to download stuff.

Note that NetworkInfo will be null if there is no network connection of any kind.

private boolean canConnect()
{
	ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	
	boolean canConnect = false;
	boolean wifiOnly = SharedPreferencesUtils.wifiOnly();
	
	NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
	if(networkInfo != null)
	{
		if(networkInfo.isConnected())
		{
			if((networkInfo.getType() == ConnectivityManager.TYPE_WIFI) ||
			   (networkInfo.getType() != ConnectivityManager.TYPE_WIFI && !wifiOnly))
			{
				canConnect = true;
			}
		}
	}
	
	return canConnect;
}

Solution 11 - Android

I have two methods to detect WIFI connection receiving the application context:

1)my old method
public boolean isConnectedWifi1(Context context) {
    try {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();           
        if (networkInfo != null) {
            NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo();
            for (NetworkInfo ni : netInfo) {
                if ((ni.getTypeName().equalsIgnoreCase("WIFI"))
                        && ni.isConnected()) {
                    return true;
                }                   
            }
        }
        return false;
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }
    return false;
}
2)my New method (I´m currently using this method):
public boolean isConnectedWifi(Context context) {
         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
         return networkInfo.isConnected();
}

Solution 12 - Android

  1. I tried Broadcast Receiver approach as well even though I know CONNECTIVITY_ACTION/CONNECTIVITY_CHANGE is deprecated in API 28 and not recommended. Also bound to using explicit register, it listens as long as app is running.

  2. I also tried Firebase Dispatcher which works but not beyond app killed.

  3. Recommended way found is WorkManager to guarantee execution beyond process killed and internally using registerNetworkRequest()

The biggest evidence in favor of #3 approach is referred by Android doc itself. Especially for apps in the background.

Also here

> In Android 7.0 we're removing three commonly-used implicit broadcasts — CONNECTIVITY_ACTION, ACTION_NEW_PICTURE, and ACTION_NEW_VIDEO — since those can wake the background processes of multiple apps at once and strain memory and battery. If your app is receiving these, take advantage of the Android 7.0 to migrate to JobScheduler and related APIs instead.

So far it works fine for us using Periodic WorkManager request.

Update: I ended up writing 2 series medium post about it.

Solution 13 - Android

I used this code:

public class MainActivity extends Activity
	{
	.
	.
	.
	@Override
	protected void onCreate(Bundle savedInstanceState)
		{
		super.onCreate(savedInstanceState);
		.
		.
		.
		}
	
	@Override
	protected void onResume()
		{
		super.onResume();
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
		registerReceiver(broadcastReceiver, intentFilter);	
		}

	@Override
	protected void onPause()
		{
		super.onPause();
		unregisterReceiver(broadcastReceiver);
		}
	
	private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
		{
		@Override
		public void onReceive(Context context, Intent intent)
			{
			final String action = intent.getAction();
			if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION))
				{
				if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false))
					{
					// wifi is enabled
					}
				else
					{
					// wifi is disabled
					}
				}
			}
		};
	}

Solution 14 - Android

For all those who enjoying CONNECTIVITY_CHANGE broadcast, please note this is no more fired when app is in background in Android O.

https://developer.android.com/about/versions/o/background.html

Solution 15 - Android

You Can use Broadcast With Filter

 <receiver
        android:name=".receivers.ConnectionType"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
        </intent-filter>
    </receiver>

after that, you can listen to the value returned like that

  @Override
public void onReceive(Context context, Intent intent) {

    int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
    if(wifiState==WifiManager.WIFI_STATE_ENABLED){
        Toast.makeText(context, "WIFI on", Toast.LENGTH_SHORT).show();

    }else if(wifiState==WifiManager.WIFI_STATE_DISABLED) {
        Toast.makeText(context, "WIFI OFF", Toast.LENGTH_SHORT).show();
    }


}

it will fire every time WIFI enabled or disabled

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndroiderView Question on Stackoverflow
Solution 1 - AndroidjpmView Answer on Stackoverflow
Solution 2 - AndroidM. Usman KhanView Answer on Stackoverflow
Solution 3 - AndroidYarView Answer on Stackoverflow
Solution 4 - AndroidYog GuruView Answer on Stackoverflow
Solution 5 - Androiduser1445716View Answer on Stackoverflow
Solution 6 - AndroidamineView Answer on Stackoverflow
Solution 7 - AndroidCodegatewayView Answer on Stackoverflow
Solution 8 - AndroidmboView Answer on Stackoverflow
Solution 9 - AndroidcesargastonecView Answer on Stackoverflow
Solution 10 - AndroidJustin PhillipsView Answer on Stackoverflow
Solution 11 - AndroidJorgesysView Answer on Stackoverflow
Solution 12 - AndroidWahib Ul HaqView Answer on Stackoverflow
Solution 13 - AndroidCuarcuiuView Answer on Stackoverflow
Solution 14 - AndroidIshamView Answer on Stackoverflow
Solution 15 - AndroidNoah MohamedView Answer on Stackoverflow