了解Android的Wifi状态

时间:2017-09-13 19:58:12

标签: android networking

我需要检查我的设备是否连接到wifi网络。但是发生的事件让我很困惑。以下是重现的步骤:

registerReceiver

所以我注册了一个带有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

这就是我收到活动的方式。

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

用户输入

  1. 我启动应用程序,从上方拉下Android菜单,打开wifi设置(通过按住wifi符号)并连接到wifi网络。然后我回到我的应用程序。
    1. 我启动应用程序,从上方拉下Android菜单,从快速设置中激活wifi。然后我回到我的应用程序。我的设备会自动连接到已知的wifi。
    2. 输出

      首先,我收到一些关于CONNECTINGAUTHENTICATING的事件。这里的一切似乎都很正常。

      但是,在一次设置期间,我连续输出四次

      onReceive: Broadcast android.net.wifi.STATE_CHANGE
      NetworkInfo.State: CONNECTED
      NetworkInfo.DetailedState: CONNECTED
      SupplicantState: COMPLETED
      DetailedStateOfSupplicant: OBTAINING_IPADDR
      
      1. 为什么会触发这四个事件?
      2. 根据文档,请求者状态COMPLETED被映射到OBTAINING_IPADDR似乎是逻辑:

          

        SupplicantState已完成:
          该状态表示请求者已完成其处理   对于关联阶段,数据连接是完全的   配置。但请注意,可能没有任何IP地址   与连接相关联。通常,DHCP请求需要   此时发送以获取地址。

        1. 但是,如果我的设备实际上只是获取IP地址,为什么网络信息状态甚至详细状态都设置为CONNECTED

        2. 如何确保我的设备“真正”连接,换句话说,我怎么知道我的设备何时最终获得它的IP地址以及网络何时可以使用?我可以注册一个更好的行动吗?

        3. 来源

          • 可以找到NetworkInfo.StateNetworkInfo.DetailedState的概述here
          • 可以找到SupplicantState的概述here

1 个答案:

答案 0 :(得分:2)

使用以下类检查网络状态:

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