57

Which listener does my class have to implement inorder to automatically check code if the wifi connects/disconnects?

I'm able to manually check for wifi connection/disconnection but each time I need to connect/disconnect WIFI from android settings and then run my program for the result.

My current code is as simple as:

WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()==true)
{
    tv.setText("You are connected");
}
else
{
    tv.setText("You are NOT connected");
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Neha
  • 569
  • 1
  • 5
  • 6

7 Answers7

80

Actually you're checking for whether Wi-Fi is enabled, that doesn't necessarily mean that it's connected. It just means that Wi-Fi mode on the phone is enabled and able to connect to Wi-Fi networks.

This is how I'm listening for actual Wi-Fi connections in my Broadcast Receiver:

public class WifiReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {     
        ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
        NetworkInfo netInfo = conMan.getActiveNetworkInfo();
        if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI) 
            Log.d("WifiReceiver", "Have Wifi Connection");
        else
            Log.d("WifiReceiver", "Don't have Wifi Connection");    
    }   
};

In order to access the active network info you need to add the following uses-permission to your AndroidManifest.xml:

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

And the following intent receiver (or you could add this programmatically...)

<!-- Receive Wi-Fi connection state changes -->
<receiver android:name=".WifiReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

EDIT: In Lollipop, Job Scheduling may help if you're looking to perform an action when the user connects to an unmetered network connection. Take a look: http://developer.android.com/about/versions/android-5.0.html#Power


EDIT 2: Another consideration is that my answer doesn't check that you have a connection to the internet. You could be connected to a Wi-Fi network which requires you to sign in. Here's a useful "IsOnline()" check: https://stackoverflow.com/a/27312494/1140744

Community
  • 1
  • 1
warbi
  • 2,725
  • 2
  • 20
  • 26
  • This is awesome but how can I use it inside my activity? – sabsab Jan 26 '15 at 23:27
  • its called twice. i am getting this twice, WifiReceiver: Have Wifi Connection – Qadir Hussain Aug 13 '17 at 12:43
  • `android.net.conn.CONNECTIVITY_CHANGE` is deprecated. What is solution now? – Sourav Bagchi Nov 15 '17 at 10:50
  • If you need to be notified (and you're targeting N or above) you'll have to register your receiver within your app instead of in the manifest, meaning your app will have to be already running. See answers to https://stackoverflow.com/q/39076910/1140744. Or you could try Job Scheduling. – warbi Nov 21 '17 at 13:25
  • `conMan` variable +1 – Aaron Lelevier Dec 12 '17 at 14:34
  • 1
    As mentioned before, `android.net.conn.CONNECTIVITY_CHANGE` is now deprecated. You can find another solution involving non-deprecated code here: https://stackoverflow.com/questions/53863034/difference-between-registerdefaultnetworkcallback-and-registernetworkcallback – Peter Lehnhardt Oct 25 '19 at 07:11
18

Create your own class that extends BroadcastReceiver...

public class MyNetworkMonitor extends BroadcastReceiver {

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

        // Process the Intent here

    }
}

In AndroidManifest.xml

<receiver
    android:name=".MyNetworkMonitor" >
        <intent-filter>
            <action android:name="android.net.wifi.STATE_CHANGE" />
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
</receiver>

See WIFI_STATE_CHANGED_ACTION and CONNECTIVITY_ACTION for an explanation of using the Intent.

htafoya
  • 18,261
  • 11
  • 80
  • 104
Squonk
  • 48,735
  • 19
  • 103
  • 135
  • Thank you MisterSquonk. Will try that. – Neha Jun 17 '11 at 19:23
  • those variables coming from WifiManager @Squonk? – gumuruh Jul 21 '14 at 10:32
  • @gumuruh WIFI_STATE_CHANGED_ACTION belongs to WifiManager Class and CONNECTIVITY_ACTION to ConnectivityManager. You could want to check more Connection types, i.e. if Mobile Network is available, then you should ask to active Networks and there you can get the NetworkInfo (->type) ConnectionManager.TYPE_MOBILE... – Gödel77 Dec 19 '14 at 12:58
15

Check out these two pages of javadoc: ConnectivityManager WiFiManager

Notice that each one defines broadcast actions. If you need to learn more about registering broadcast receivers, check this out: Programmatically register a broadcast receiver

BroadcastReceiver receiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    if (wifi.isWifiEnabled()) {
      tv.setText("You are connected");
    } else {
      tv.setText("You are NOT connected");
    }
  }
};

And in your manifest you could do something like this (if you would prefer to NOT register the receiver in code):

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <receiver android:name=".WiFiReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.net.ConnectivityManager.CONNECTIVITY_ACTION" />
        </intent-filter>
    </receiver>
</application>

EDIT:

I should add that it would be better to register this broadcast receiver in your code rather than in the manifest if you only need to receive the broadcast while the app is running. By specifying it in the manifest your process will be notified of a connection change even when it was not previously running.

Apps targeting Android 7.0 (API level 24) and higher do not receive this broadcast if they declare the broadcast receiver in their manifest. Apps will still receive broadcasts if they register their android.content.BroadcastReceiver} with android.content.Context#registerReceiver Context.registerReceiver() and that context is still valid.

Blundell
  • 75,855
  • 30
  • 208
  • 233
Tanner Perrien
  • 3,133
  • 1
  • 28
  • 35
  • 1
    i recommend that you edit your code and make explicit reference to the context: "WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);" otherwise you might get errors with "getSystemService()", if used in a separate class. – tony gil Jul 20 '12 at 14:54
4

I agree with @tanner-perrien's answer, and for 2020, Kotlin represent:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        registerReceiver(wifiBroadcastReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
    }

    private val wifiBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
            Log.d("TUT", "Wifi is ${wifiManager.isWifiEnabled}")
        }
    }

    override fun onDestroy() {
        unregisterReceiver(wifiBroadcastReceiver)
        super.onDestroy()
    }
}

But might want to move with the times: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback

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

Activity:

lateinit var connec: ConnectivityManager

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    connec = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val networkRequestWiFi = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build()

    connec.registerNetworkCallback(networkRequestWiFi, networkCallbackWiFi)
 }

private var networkCallbackWiFi = object : ConnectivityManager.NetworkCallback() {
    override fun onLost(network: Network?) {
        Log.d("TUT", "WiFi disconnected")
    }

    override fun onAvailable(network: Network?) {
        Log.d("TUT", "WiFi connected")
    }
}

override fun onDestroy() {
    connec.unregisterNetworkCallback(networkCallbackWiFi)
    super.onDestroy()
}
Blundell
  • 75,855
  • 30
  • 208
  • 233
  • What is connec? – Sira Lam Feb 06 '20 at 08:58
  • 1
    oo sorry, I'd missed that out, added it back – Blundell Feb 06 '20 at 09:46
  • So I see that this new technique eliminates the need to register a broadcast receiver. :) – SMBiggs Dec 09 '21 at 16:56
  • Yeah the original one is registered on line 4. Programatically instead of in the AndroidManifest is the difference. The new one, correct no broadcast receiver (for our app) perhaps the framework registers one and turns that into callbacks for us. – Blundell Dec 10 '21 at 11:54
3

In AndroidManifest.xml add following permission.

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

Create new Receiver class.

public class ConnectionChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();

        if (activeNetInfo != null
            && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            Toast.makeText(context, "Wifi Connected!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "Wifi Not Connected!", Toast.LENGTH_SHORT).show();
        }
    }

And add that receiver class to AndroidManifest.xml file.

<receiver android:name="ConnectionChangeReceiver"
          android:label="NetworkConnection">
  <intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
  </intent-filter>
</receiver>
Aung Thuya
  • 69
  • 5
2

In response to sabsab. To hook into the Connectivity Change broadcast receiver I utilized warbi's answer and added a class with static methods.

public class WifiHelper
{
    private static boolean isConnectedToWifi;
    private static WifiConnectionChange sListener;

    public interface WifiConnectionChange {
        void wifiConnected(boolean connected);
    }

    /**
     * Only used by Connectivity_Change broadcast receiver
     * @param connected
     */
    public static void setWifiConnected(boolean connected) {
        isConnectedToWifi = connected;
        if (sListener!=null)
        {
            sListener.wifiConnected(connected);
            sListener = null;
        }
    }

    public static void setWifiListener(WifiConnectionChange listener) {
        sListener = listener;
    }
}

Then I made changes to the receiver class on the first answer shown above.

public class ConnectivityReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
    ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = conMan.getActiveNetworkInfo();
    if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI)
    {
        Log.d("WifiReceiver", "Have Wifi Connection");
        WifiHelper.setWifiConnected(true);
    } else
    {
        Log.d("WifiReceiver", "Don't have Wifi Connection");
        WifiHelper.setWifiConnected(false);
    }

}
}

Finally, in your activity you can add a listener to utilize this callback.

wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
wasWifiEnabled = (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED || wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING);
WifiHelper.setWifiListener(new WifiHelper.WifiConnectionChange()
    {
        @Override
        public void wifiConnected(boolean connected)
        {
            //Do logic here
        }
    });

Notice the listener is removed after the callback fires, this is because it's a static listener. Anyhow this implementation works for me and is one way to hook into your activity, or anywhere gives it's static.

Danuofr
  • 1,661
  • 19
  • 25
0

There's also WifiManager.NETWORK_STATE_CHANGED_ACTION:

Broadcast intent action indicating that the state of Wi-Fi connectivity has changed. An extra provides the new state in the form of a NetworkInfo object. No network-related permissions are required to subscribe to this broadcast.

Then there is getState(), which has states like CONNECTING/DISCONNECTING, for example, which CONNECTIVITY_ACTION doesn't. Also, CONNECTING means there's no Internet. CONNECTED means there is Internet: https://android.googlesource.com/platform/frameworks/base/+/android10-release/core/java/android/net/NetworkInfo.java#122. Or there's getDetailedState(), which includes "infinity".

Though, NetworkInfo has been deprecated since API 29, so there's that too. But for me seems better than to use CONNECTIVITY_ACTION on supported devices, because of many and accurate states.

Edw590
  • 447
  • 1
  • 6
  • 23