簡體   English   中英

了解Android的Wifi狀態

[英]Understanding Android's Wifi State

我需要檢查我的設備是否連接到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。

輸出量

首先,我收到一些有關CONNECTINGAUTHENTICATING事件。 這里似乎一切正常。

但是然后在一次設置中,我連續四次獲得此輸出:

onReceive: Broadcast android.net.wifi.STATE_CHANGE
NetworkInfo.State: CONNECTED
NetworkInfo.DetailedState: CONNECTED
SupplicantState: COMPLETED
DetailedStateOfSupplicant: OBTAINING_IPADDR
  1. 為什么觸發這四個事件?

根據文檔,將請求者狀態COMPLETED映射到OBTAINING_IPADDR似乎是邏輯:

SupplicantState已完成:
此狀態指示請求方已完成其對關聯階段的處理,並且數據連接已完全配置。 但是請注意,該連接可能還沒有任何IP地址。 通常,此時需要發送DHCP請求以獲得地址。

  1. 但是,如果我的設備實際上只是在獲取其IP地址,為什么將網絡信息狀態甚至詳細狀態設置為CONNECTED

  2. 如何確保設備“真正”連接,換句話說,我如何知道設備何時最終獲得其IP地址以及何時可以使用網絡? 我可以注冊一個更好的措施嗎?

資料來源

  • 可以在此處找到NetworkInfo.StateNetworkInfo.DetailedState的概述。
  • SupplicantState的概述可以在此處找到。

使用下面的類檢查網絡狀態:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM