首页 文章

检测Android上的网络连接类型

提问于
浏览
176

如何检测Android上的网络连接类型?

它是通过 ConnectivityManager.getActiveNetworkInfo().getType() ,并且答案仅限于Wifi和移动?

11 回答

  • 0

    如果问题是要确定手机网络是否已连接且速度足以满足您的要求,则必须处理 getSubType() 返回的所有网络类型 .

    我花了一两个小时来研究和编写这个类就是为了做到这一点,我想我会与其他可能会觉得有用的人分享 .

    这是Gist of the class,所以你可以分叉并编辑它 .

    package com.emil.android.util;
    
    import android.content.Context;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.telephony.TelephonyManager;
    
    /**
     * Check device's network connectivity and speed 
     * @author emil http://stackoverflow.com/users/220710/emil
     *
     */
    public class Connectivity {
    
        /**
         * Get the network info
         * @param context
         * @return
         */
        public static NetworkInfo getNetworkInfo(Context context){
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            return cm.getActiveNetworkInfo();
        }
    
        /**
         * Check if there is any connectivity
         * @param context
         * @return
         */
        public static boolean isConnected(Context context){
            NetworkInfo info = Connectivity.getNetworkInfo(context);
            return (info != null && info.isConnected());
        }
    
        /**
         * Check if there is any connectivity to a Wifi network
         * @param context
         * @param type
         * @return
         */
        public static boolean isConnectedWifi(Context context){
            NetworkInfo info = Connectivity.getNetworkInfo(context);
            return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
        }
    
        /**
         * Check if there is any connectivity to a mobile network
         * @param context
         * @param type
         * @return
         */
        public static boolean isConnectedMobile(Context context){
            NetworkInfo info = Connectivity.getNetworkInfo(context);
            return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE);
        }
    
        /**
         * Check if there is fast connectivity
         * @param context
         * @return
         */
        public static boolean isConnectedFast(Context context){
            NetworkInfo info = Connectivity.getNetworkInfo(context);
            return (info != null && info.isConnected() && Connectivity.isConnectionFast(info.getType(),info.getSubtype()));
        }
    
        /**
         * Check if the connection is fast
         * @param type
         * @param subType
         * @return
         */
        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
                /*
                 * Above API level 7, make sure to set android:targetSdkVersion 
                 * to appropriate level to use these
                 */
                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;
            }
        }
    
    }
    

    另外,请确保将此权限添加到AndroidManifest.xml中

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

    网络速度的来源包括维基百科和http://3gstore.com/page/78_what_is_evdo_mobile_broadband.html

  • 7

    您可以使用getSubtype()获取更多详细信息 . 在这里查看幻灯片9:http://dl.google.com/io/2009/pres/W_0300_CodingforLife-BatteryLifeThatIs.pdf

    ConnectivityManager mConnectivity = null;
    TelephonyManager mTelephony = null;
    // Skip if no connection, or background data disabled
    NetworkInfo info = mConnectivity.getActiveNetworkInfo();
    if (info == null || !mConnectivity.getBackgroundDataSetting()) {
        return false;
    }
    
    // Only update if WiFi or 3G is connected and not roaming
    int netType = info.getType();
    int netSubtype = info.getSubtype();
    if (netType == ConnectivityManager.TYPE_WIFI) {
        return info.isConnected();
    } else if (netType == ConnectivityManager.TYPE_MOBILE
        && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS
        && !mTelephony.isNetworkRoaming()) {
            return info.isConnected();
    } else {
        return false;
    }
    

    另外,请查看Emil的答案,以便更详细地了解这一点 .

  • 2

    获取有关连接类型的更精确(和用户友好)信息 . 您可以使用此代码(从TelephonyManager.java中的@hide方法派生) .

    此方法返回描述当前连接类型的String .
    即以下之一:"WIFI","2G","3G","4G","-"(未连接)或"?"(未知)

    备注:此代码需要API 25,但您可以使用int而不是const轻松支持旧版本 . (参见代码中的注释) .

    public static String getNetworkClass(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);      
        NetworkInfo info = cm.getActiveNetworkInfo();
        if(info==null || !info.isConnected())
            return "-"; //not connected
        if(info.getType() == ConnectivityManager.TYPE_WIFI)
            return "WIFI";
        if(info.getType() == ConnectivityManager.TYPE_MOBILE){
            int networkType = info.getSubtype();
            switch (networkType) {
                case TelephonyManager.NETWORK_TYPE_GPRS:
                case TelephonyManager.NETWORK_TYPE_EDGE:
                case TelephonyManager.NETWORK_TYPE_CDMA:
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
                    return "2G";
                case TelephonyManager.NETWORK_TYPE_UMTS:
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                case TelephonyManager.NETWORK_TYPE_HSPA:
                case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14
                case TelephonyManager.NETWORK_TYPE_EHRPD:  //api<11 : replace by 12
                case TelephonyManager.NETWORK_TYPE_HSPAP:  //api<13 : replace by 15
                case TelephonyManager.NETWORK_TYPE_TD_SCDMA:  //api<25 : replace by 17
                    return "3G";
                case TelephonyManager.NETWORK_TYPE_LTE:    //api<11 : replace by 13
                case TelephonyManager.NETWORK_TYPE_IWLAN:  //api<25 : replace by 18
                case 19:  //LTE_CA
                    return "4G";
                default:
                    return "?";
             }
        }
        return "?";
    }
    
  • 0

    @ Emil上面的答案很精彩 .

    小补充:理想情况下,我们应该使用TelephonyManager来检测网络类型 . 所以上面应该改为:

    /**
     * Check if there is fast connectivity
     * @param context
     * @return
     */
    public static boolean isConnectedFast(Context context){
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return (info != null && info.isConnected() && Connectivity.isConnectionFast(info.getType(), tm.getNetworkType()));
    }
    
  • 2

    Emil Davtyan的答案很好,但是添加的网络类型在他的答案中没有考虑到 . 所以, isConnectionFast(int type, int subType) 可能会返回false,应该是真的 .

    这是一个修改过的类,它使用反射来解释以后的API中添加的网络类型:

    import android.content.Context;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.telephony.TelephonyManager;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * <p>Utility methods to check the current network connection status.</p>
     *
     * <p>This requires the caller to hold the permission
     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.</p>
     */
    public class NetworkUtils {
    
      /** The absence of a connection type. */
      public static final int TYPE_NONE = -1;
    
      /** Unknown network class. */
      public static final int NETWORK_CLASS_UNKNOWN = 0;
      /** Class of broadly defined "2G" networks. */
      public static final int NETWORK_CLASS_2_G = 1;
      /** Class of broadly defined "3G" networks. */
      public static final int NETWORK_CLASS_3_G = 2;
      /** Class of broadly defined "4G" networks. */
      public static final int NETWORK_CLASS_4_G = 3;
    
      /**
       * Returns details about the currently active default data network. When connected, this network
       * is the default route for outgoing connections. You should always check {@link
       * NetworkInfo#isConnected()} before initiating network traffic. This may return {@code null}
       * when there is no default network.
       *
       * @return a {@link NetworkInfo} object for the current default network or {@code null} if no
       * network default network is currently active
       *
       * This method requires the call to hold the permission
       * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
       * @see ConnectivityManager#getActiveNetworkInfo()
       */
      public static NetworkInfo getInfo(Context context) {
        return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE))
            .getActiveNetworkInfo();
      }
    
      /**
       * Reports the current network type.
       *
       * @return {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} ,
       * {@link ConnectivityManager#TYPE_WIMAX}, {@link ConnectivityManager#TYPE_ETHERNET}, {@link
       * ConnectivityManager#TYPE_BLUETOOTH}, or other types defined by {@link ConnectivityManager}.
       * If there is no network connection then -1 is returned.
       * @see NetworkInfo#getType()
       */
      public static int getType(Context context) {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return TYPE_NONE;
        }
        return info.getType();
      }
    
      /**
       * Return a network-type-specific integer describing the subtype of the network.
       *
       * @return the network subtype
       * @see NetworkInfo#getSubtype()
       */
      public static int getSubType(Context context) {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return TYPE_NONE;
        }
        return info.getSubtype();
      }
    
      /** Returns the NETWORK_TYPE_xxxx for current data connection. */
      public static int getNetworkType(Context context) {
        return ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
            .getNetworkType();
      }
    
      /** Check if there is any connectivity */
      public static boolean isConnected(Context context) {
        return getType(context) != TYPE_NONE;
      }
    
      /** Check if there is any connectivity to a Wifi network */
      public static boolean isWifiConnection(Context context) {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return false;
        }
        switch (info.getType()) {
          case ConnectivityManager.TYPE_WIFI:
            return true;
          default:
            return false;
        }
      }
    
      /** Check if there is any connectivity to a mobile network */
      public static boolean isMobileConnection(Context context) {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return false;
        }
        switch (info.getType()) {
          case ConnectivityManager.TYPE_MOBILE:
            return true;
          default:
            return false;
        }
      }
    
      /** Check if the current connection is fast. */
      public static boolean isConnectionFast(Context context) {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return false;
        }
        switch (info.getType()) {
          case ConnectivityManager.TYPE_WIFI:
          case ConnectivityManager.TYPE_ETHERNET:
            return true;
          case ConnectivityManager.TYPE_MOBILE:
            int networkClass = getNetworkClass(getNetworkType(context));
            switch (networkClass) {
              case NETWORK_CLASS_UNKNOWN:
              case NETWORK_CLASS_2_G:
                return false;
              case NETWORK_CLASS_3_G:
              case NETWORK_CLASS_4_G:
                return true;
            }
          default:
            return false;
        }
      }
    
      private static int getNetworkClassReflect(int networkType)
          throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method getNetworkClass = TelephonyManager.class.getDeclaredMethod("getNetworkClass", int.class);
        if (!getNetworkClass.isAccessible()) {
          getNetworkClass.setAccessible(true);
        }
        return (int) getNetworkClass.invoke(null, networkType);
      }
    
      /**
       * Return general class of network type, such as "3G" or "4G". In cases where classification is
       * contentious, this method is conservative.
       */
      public static int getNetworkClass(int networkType) {
        try {
          return getNetworkClassReflect(networkType);
        } catch (Exception ignored) {
        }
    
        switch (networkType) {
          case TelephonyManager.NETWORK_TYPE_GPRS:
          case 16: // TelephonyManager.NETWORK_TYPE_GSM:
          case TelephonyManager.NETWORK_TYPE_EDGE:
          case TelephonyManager.NETWORK_TYPE_CDMA:
          case TelephonyManager.NETWORK_TYPE_1xRTT:
          case TelephonyManager.NETWORK_TYPE_IDEN:
            return NETWORK_CLASS_2_G;
          case TelephonyManager.NETWORK_TYPE_UMTS:
          case TelephonyManager.NETWORK_TYPE_EVDO_0:
          case TelephonyManager.NETWORK_TYPE_EVDO_A:
          case TelephonyManager.NETWORK_TYPE_HSDPA:
          case TelephonyManager.NETWORK_TYPE_HSUPA:
          case TelephonyManager.NETWORK_TYPE_HSPA:
          case TelephonyManager.NETWORK_TYPE_EVDO_B:
          case TelephonyManager.NETWORK_TYPE_EHRPD:
          case TelephonyManager.NETWORK_TYPE_HSPAP:
          case 17: // TelephonyManager.NETWORK_TYPE_TD_SCDMA:
            return NETWORK_CLASS_3_G;
          case TelephonyManager.NETWORK_TYPE_LTE:
          case 18: // TelephonyManager.NETWORK_TYPE_IWLAN:
            return NETWORK_CLASS_4_G;
          default:
            return NETWORK_CLASS_UNKNOWN;
        }
      }
    
      private NetworkUtils() {
        throw new AssertionError();
      }
    
    }
    
  • 51

    您可以使用自定义方法来完成此任务 .

    public String getNetworkClass(Context context) {
            TelephonyManager mTelephonyManager = (TelephonyManager)
                    context.getSystemService(Context.TELEPHONY_SERVICE);
            int networkType = mTelephonyManager.getNetworkType();
            switch (networkType) {
                case TelephonyManager.NETWORK_TYPE_GPRS:
                case TelephonyManager.NETWORK_TYPE_EDGE:
                case TelephonyManager.NETWORK_TYPE_CDMA:
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                case TelephonyManager.NETWORK_TYPE_IDEN:
                    return "2G";
                case TelephonyManager.NETWORK_TYPE_UMTS:
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                case TelephonyManager.NETWORK_TYPE_HSPA:
                case TelephonyManager.NETWORK_TYPE_EVDO_B:
                case TelephonyManager.NETWORK_TYPE_EHRPD:
                case TelephonyManager.NETWORK_TYPE_HSPAP:
                    return "3G";
                case TelephonyManager.NETWORK_TYPE_LTE:
                    return "4G";
                default:
                    return "Unknown";
            }
        }
    
  • 433

    除了Emil的绝佳答案之外,我还想添加一个方法,用于检查您是否确实可以访问Internet,因为您可以在手机上关闭数据 .

    public static boolean hasInternetAccess(Context c){
        TelephonyManager tm = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
        if(isConnected(c) && tm.getDataState() == TelephonyManager.DATA_CONNECTED)
           return true;
        else
            return false;
    }
    

    请注意,这仅用于检查是否为蜂窝数据连接,如果已连接WiFi,则返回false,因为连接WiFi时蜂窝数据已关闭 .

  • 52
    String active_network = ((ConnectivityManager)
        .getSystemService(Context.CONNECTIVITY_SERVICE))
        .getActiveNetworkInfo().getSubtypeName();
    

    应该得到你的网络名称

  • 13

    你可以这样检查

    public void checktype() {
        ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (activeNetwork != null) { // connected to the internet
            if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                // connected to wifi
                Toast.makeText(this, activeNetwork.getTypeName(), Toast.LENGTH_SHORT).show();
            } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                // connected to the mobile provider's data plan
                Toast.makeText(this, activeNetwork.getTypeName(), Toast.LENGTH_SHORT).show();
            }
        }
    }
    
  • 4

    目前,仅支持MOBILE和WIFI . 看看和人类可读type function .

  • 2

    你可以试试这个:

    public String ConnectionQuality() {
        NetworkInfo info = getInfo(context);
        if (info == null || !info.isConnected()) {
          return "UNKNOWN";
        }
    
        if(info.getType() == ConnectivityManager.TYPE_WIFI) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            int numberOfLevels = 5;
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            int level = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), numberOfLevels);
            if(level == 2 )
                    return "POOR";
                else if(level == 3 )
                    return "MODERATE";
                else if(level == 4 )
                    return "GOOD";
                else if(level == 5 )
                    return "EXCELLENT";
                else
                return "UNKNOWN";
            }else if(info.getType() == ConnectivityManager.TYPE_MOBILE) {
                int networkClass = getNetworkClass(getNetworkType(context));
                if(networkClass == 1)
                    return "POOR";
                else if(networkClass == 2 )
                    return "GOOD";
                else if(networkClass == 3 )
                    return "EXCELLENT";
                else
                    return "UNKNOWN";
            }else
                return "UNKNOWN";  
    }
    
    public NetworkInfo getInfo(Context context) {
        return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
    }
    
    public int getNetworkClass(int networkType) {
        try {
          return getNetworkClassReflect(networkType);
        }catch (Exception ignored) {
        }
    
        switch (networkType) {
          case TelephonyManager.NETWORK_TYPE_GPRS:
          case 16: // TelephonyManager.NETWORK_TYPE_GSM:
          case TelephonyManager.NETWORK_TYPE_EDGE:
          case TelephonyManager.NETWORK_TYPE_CDMA:
          case TelephonyManager.NETWORK_TYPE_1xRTT:
          case TelephonyManager.NETWORK_TYPE_IDEN:
            return 1;
          case TelephonyManager.NETWORK_TYPE_UMTS:
          case TelephonyManager.NETWORK_TYPE_EVDO_0:
          case TelephonyManager.NETWORK_TYPE_EVDO_A:
          case TelephonyManager.NETWORK_TYPE_HSDPA:
          case TelephonyManager.NETWORK_TYPE_HSUPA:
          case TelephonyManager.NETWORK_TYPE_HSPA:
          case TelephonyManager.NETWORK_TYPE_EVDO_B:
          case TelephonyManager.NETWORK_TYPE_EHRPD:
          case TelephonyManager.NETWORK_TYPE_HSPAP:
          case 17: // TelephonyManager.NETWORK_TYPE_TD_SCDMA:
            return 2;
          case TelephonyManager.NETWORK_TYPE_LTE:
          case 18: // TelephonyManager.NETWORK_TYPE_IWLAN:
            return 3;
          default:
            return 0;
        }
    }
    
    private int getNetworkClassReflect(int networkType) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {  
        Method getNetworkClass = TelephonyManager.class.getDeclaredMethod("getNetworkClass", int.class);
        if (!getNetworkClass.isAccessible()) {
          getNetworkClass.setAccessible(true);
        }
        return (Integer) getNetworkClass.invoke(null, networkType); 
    }
    
    public static int getNetworkType(Context context) {
        return ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getNetworkType();
    }
    

相关问题