简体   繁体   中英

Understanding Android's Wifi State

I need to check if my device is connected to a wifi network. But the events that occur confuse me. Here are the steps to reproduce:

registerReceiver

So I registered a receiver with the action WifiManager.NETWORK_STATE_CHANGED_ACTION) :

private void registerReceiver() {
    Log.v(TAG, "registerReceiver");

    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

    broadcastReceiver = new ConnectivityBroadcastReceiver();
    context.registerReceiver(broadcastReceiver, intentFilter);
}

onReceive

And this is how I receive the events.

private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.v("Broadcast", "onReceive: " + intent.getAction());
        final NetworkInfo networkInfo =
                intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

        if (networkInfo != null) {
            final NetworkInfo.State state = networkInfo.getState();
            final NetworkInfo.DetailedState detailedState = networkInfo.getDetailedState();

            Log.d(TAG, "NetworkInfo.State: " + state);
            Log.d(TAG, "NetworkInfo.DetailedState: " + detailedState);
        }

        final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        final WifiInfo wifiInfo = wifiManager.getConnectionInfo();

        final SupplicantState supplicantState = wifiInfo.getSupplicantState();
        final NetworkInfo.DetailedState detailedState = wifiInfo.getDetailedStateOf(supplicantState);

        Log.d(TAG, "SupplicantState: " + supplicantState.toString());
        Log.d(TAG, "DetailedStateOfSupplicant: " + detailedState.toString());
    }
}

User Input

  1. I start the app, pull the Android menu down from above, open wifi settings (by holding the wifi symbol) and connect to a wifi network. I then return back to my app.

or

  1. I start the app, pull the Android menu down from above, active wifi from the quick settings. I then return back to my app. My device automatically connects to a known wifi.

Output

First I receive some events about CONNECTING and AUTHENTICATING . Everything seems to be normal here.

But then I get this output four times in a row during one setup :

onReceive: Broadcast android.net.wifi.STATE_CHANGE
NetworkInfo.State: CONNECTED
NetworkInfo.DetailedState: CONNECTED
SupplicantState: COMPLETED
DetailedStateOfSupplicant: OBTAINING_IPADDR
  1. Why are these four events triggered?

That the supplicant state COMPLETED gets mapped to OBTAINING_IPADDR seems logic according to the documentation:

SupplicantState COMPLETED:
This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet. Typically, a DHCP request needs to be sent at this point to obtain an address.

  1. But why is the network info state and even the detailed state set to CONNECTED if my device is actually just obtaining it's IP address?

  2. How can I ensure that my device is "really" connected, in other words, how do I know when my device finally obtained it's IP address and when the network is ready for use? Is there a better action that I can register upon?

Sources

  • An overview of NetworkInfo.State and NetworkInfo.DetailedState can be found here .
  • An overview of SupplicantState can be found here .

Check network state using the below class:

 public class Connectivity {
    public static NetworkInfo getNetworkInfo(Context context){
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getActiveNetworkInfo();
    }


    public static boolean isConnected(Context context){
        NetworkInfo info = Connectivity.getNetworkInfo(context);
        return (info != null && info.isConnected());
    }

    public static boolean isConnectedWifi(Context context){
        NetworkInfo info = Connectivity.getNetworkInfo(context);
        return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
    }


    public static boolean isConnectedMobile(Context context){
        NetworkInfo info = Connectivity.getNetworkInfo(context);
        return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE);
    }


    public static boolean isConnectedFast(Context context){
        NetworkInfo info = Connectivity.getNetworkInfo(context);
        return (info != null && info.isConnected() && Connectivity.isConnectionFast(info.getType(),info.getSubtype()));
    }


    public static boolean isConnectionFast(int type, int subType){
        if(type== ConnectivityManager.TYPE_WIFI){
            return true;
        }else if(type==ConnectivityManager.TYPE_MOBILE){
            switch(subType){
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_CDMA:
                    return false; // ~ 14-64 kbps
                case TelephonyManager.NETWORK_TYPE_EDGE:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    return true; // ~ 400-1000 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    return true; // ~ 600-1400 kbps
                case TelephonyManager.NETWORK_TYPE_GPRS:
                    return false; // ~ 100 kbps
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                    return true; // ~ 2-14 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPA:
                    return true; // ~ 700-1700 kbps
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                    return true; // ~ 1-23 Mbps
                case TelephonyManager.NETWORK_TYPE_UMTS:
                    return true; // ~ 400-7000 kbps
                case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
                    return true; // ~ 1-2 Mbps
                case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
                    return true; // ~ 5 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
                    return true; // ~ 10-20 Mbps
                case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
                    return false; // ~25 kbps
                case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
                    return true; // ~ 10+ Mbps
                // Unknown
                case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                default:
                    return false;
            }
        }else{
            return false;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM