Get SSID of disconnected WiFi network in Android using BroadcastReceiver?
Asked Answered
B

2

7

I have the following BroadcastRecevier:

public class WiFiConnectionEventsReceiver extends BroadcastReceiver {

    private static final String TAG = WiFiConnectionEventsReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, @NonNull Intent intent) {
        Log.v(TAG, "action: " + intent.getAction());
        Log.v(TAG, "component: " + intent.getComponent());
        Bundle extras = intent.getExtras();
        if (extras != null) {
            for (String key : extras.keySet()) {
                Log.v(TAG, "key [" + key + "]: " +
                        extras.get(key));
            }
        } else {
            Log.v(TAG, "no extras");
        }

        ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = conMan.getActiveNetworkInfo();
        if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            Log.d("NetworkInfo", "Have Wifi Connection");
            Log.d("NetworkInfo", netInfo.getExtraInfo());
            Log.d("NetworkInfo", netInfo.getTypeName());
        }
        else {
            Log.d("NetworkInfo", "Don't have Wifi Connection");
            Log.d("NetworkInfo", netInfo.getExtraInfo());
            Log.d("NetworkInfo", netInfo.getTypeName());
        }

        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        Log.d("WifiInfo",  wifiManager.getConnectionInfo().toString());
    }
}

It receives network connection and disconnection events.

When it connects to a WiFi network, I am able to get the SSID of the network easily.

But I want to be able to get the SSID of the WiFi network when the network is disconnected as well (without having to store previously connected networks and then matching them up that way etc). Is this possible?

Logs when WiFi connects:

V/WiFiConnectionEventsReceiver: action: android.net.conn.CONNECTIVITY_CHANGE
V/WiFiConnectionEventsReceiver: component: ComponentInfo{com.example.test/com.example.test.WiFiConnectionEventsReceiver}
V/WiFiConnectionEventsReceiver: key [networkInfo]: [type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: "SKY123”, roaming: false, failover: false, isAvailable: true]
V/WiFiConnectionEventsReceiver: key [networkType]: 1
V/WiFiConnectionEventsReceiver: key [inetCondition]: 100
V/WiFiConnectionEventsReceiver: key [extraInfo]: "SKY123”
D/NetworkInfo: Have Wifi Connection
D/NetworkInfo: "SKY123”
D/NetworkInfo: WIFI
D/WifiInfo: SSID: SKY123, BSSID: 10:40:03:ad:6x:c9, MAC: 02:00:00:00:00:00, Supplicant state: COMPLETED, RSSI: -79, Link speed: 43Mbps, Frequency: 2412MHz, Net ID: 1, Metered hint: false, score: 60

Logs when WiFi disconnects (note unknown SSID):

V/WiFiConnectionEventsReceiver: action: android.net.conn.CONNECTIVITY_CHANGE
V/WiFiConnectionEventsReceiver: component: ComponentInfo{com.example.test/com.example.test.WiFiConnectionEventsReceiver}
V/WiFiConnectionEventsReceiver: key [networkInfo]: [type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: <unknown ssid>, roaming: false, failover: false, isAvailable: true]
V/WiFiConnectionEventsReceiver: key [networkType]: 1
V/WiFiConnectionEventsReceiver: key [inetCondition]: 0
V/WiFiConnectionEventsReceiver: key [extraInfo]: <unknown ssid>
V/WiFiConnectionEventsReceiver: key [noConnectivity]: true
D/NetworkInfo: Don't have Wifi Connection
D/NetworkInfo: id
D/NetworkInfo: MOBILE
D/WifiInfo: SSID: <unknown ssid>, BSSID: <none>, MAC: 02:00:00:00:00:00, Supplicant state: COMPLETED, RSSI: -127, Link speed: -1Mbps, Frequency: -1MHz, Net ID: -1, Metered hint: false, score: 0

The reason I'd like this info is I want to be able to track a user's WiFi usage on each network - the connection and disconnection times.

Without the SSID of the disconnected network, the only way I can think to do this is something like:

if (WiFi network ABC disconnected)
  if (if previous stored connection for WiFi network ABC has no disconnection time)
      set WiFI network ABC disconnection time to now

However, the above approach feels flaky, for example, what if for some reason a WiFi disconnection event is missed etc

Brattishing answered 24/9, 2016 at 16:25 Comment(0)
O
1

You can definitely do it, by using a different approach than what you've tried.

  1. You need to register a receiver which listens to WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.
  2. Whenever you're doing a wifi scan, this receiver will be called with the scan results, within those results you'll have any router available ssid (regardless of its connected status)
  3. You need to then match the disconnected wifi you found on your code with the scan list.

Add this permissions to your manifest, and don't forget, if you're using marshmallow, request permission for the location.

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

This is the MainActivty, results are received on the broadcast receiver.

public class MainActivity extends AppCompatActivity {

    private WifiManager mWifiManager;
    private List<ScanResult> mScanResults;

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

        mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (mWifiManager.isWifiEnabled() ||
                (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && mWifiManager.isScanAlwaysAvailable())) {
            registerReceiver(mReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
        }
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equalsIgnoreCase(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                mScanResults = mWifiManager.getScanResults();
                for (ScanResult result : mScanResults) {
                    Log.i(getClass().getSimpleName(), "wifi Ssid : " + result.SSID);
                }
            }
        }
    };

    @Override
    protected void onDestroy() {
        try {
            unregisterReceiver(mReceiver);
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }
}
Opt answered 28/9, 2016 at 8:14 Comment(1)
You're right, but after you receive this list, you can compare each item's bssid with the disconnected wifi. It may not find it at all times, but to the major part it will.Opt
C
0

This is not possible. When onReceive is called the connection is already lost and current info show there is no connection.

Also note that you might get another call to onRecieve right after you've recieved disconnection information. From spec:

CONNECTIVITY_ACTION

[...]

If this is a connection that was the result of failing over from a disconnected network, then the FAILOVER_CONNECTION boolean extra is set to true.

For a loss of connectivity, if the connectivity manager is attempting to connect (or has already connected) to another network, the NetworkInfo for the new network is also passed as an extra. This lets any receivers of the broadcast know that they should not necessarily tell the user that no data traffic will be possible. Instead, the receiver should expect another broadcast soon, indicating either that the failover attempt succeeded (and so there is still overall data connectivity), or that the failover attempt failed, meaning that all connectivity has been lost.

[...]

Contra answered 26/9, 2016 at 16:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.