2010-05-10 3 views

ответ

406

Если проблема заключается в том, чтобы определить, подключена ли сеть телефона и достаточно быстро, чтобы удовлетворить ваши требования, вам необходимо обрабатывать все типы сетей, возвращаемые 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

+0

отличный код и отличный список всех типов и скоростей сети! – vallllll

+0

Ничего себе! это очень полезно. Все типы сетей перечислены + вы также упомянули о своей ожидаемой скорости. Отличный код! – kuchi

+9

Спасибо. Btw, все константы для сетевых типов ([здесь] (http://developer.android.com/reference/android/telephony/TelephonyManager.html)) являются 'public static final int'. Поэтому вам не нужно делать «взломать». Просто нацелившись на новый SDK, компилятор компилирует реальные значения (целые числа), которые они указывают (а не их экземпляры) на байт-коды. – 2012-11-08 15:03:47

0

В настоящее время поддерживается только MOBILE и WIFI. Взгляните и читайте человека type function.

52

Вы можете использовать getSubtype() для получения более подробной информации. Проверьте слайд-здесь: 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 для более детального погружения в это.

+0

WiMAX тоже, нет? Мне не удалось выяснить, что такое сеть с поддержкой IP-адресов, а что нет (MMS) – sehugg

+0

Спасибо за этот партнер! –

+1

Nice презентации. Спасибо, что поделился! – Udayan

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

вы должны получить имя сети

13

@ Ответ Эмиля выше блестящий.

Небольшое дополнение: мы должны идеально использовать 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())); 
} 
42

Чтобы получить более точную (и удобную для пользователя) информацию о типе подключения. Вы можете использовать этот код (полученный из метода @hide в TelephonyManager.java).

Этот метод возвращает строку, описывающую текущий тип соединения.
т. Е. Один из: «WIFI», «2G», «3G», «4G», «-» (не подключен) или «?» (неизвестно)

Примечание. Этот код требует API 15+, но вы можете легко поддерживать более старые версии, используя 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 
       return "3G"; 
      case TelephonyManager.NETWORK_TYPE_LTE: //api<11 : replace by 13 
       return "4G"; 
      default: 
       return "?"; 
     } 
    } 
    return "?"; 
} 
+0

как реализовать это в своей деятельности? – Joe

+2

Активность реализует контекст, поэтому он тривиален. нет? – ben75

2

На вершине AWSOME ответа Эмиля Я хотел бы добавить еще один метод, для проверки, если вы на самом деле имеете доступ к Интернету, как вы могли бы иметь набор данных от телефона.

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

Обратите внимание, что это только для проверки, если Theres соединение сотовой связи данных и возвратит ложь, если у вас есть Wi-Fi подключен, так как сотовые данные выключен, когда Wi-Fi подключен.

6

Ответ от Эмиля Давтяна хорош, но были добавлены сетевые типы, которые не учитываются в его ответе. Таким образом, isConnectionFast(int type, int subType) может возвращать false, когда это должно быть правдой.

Вот модифицированный класс, который использует отражение для учета добавленных типов сетей в более позднем APIs:

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

} 
+0

как реализовать это для деятельности? – Joe

+0

@Joe Скопируйте класс в свой проект, а затем вызовите один из статических методов утилиты из своей активности. Пример: 'if (NetworkUtils.isWifiConnection (this) {/ * do stuff * /}' –

1

Вы можете проверить, как это

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

Спасибо jeff за ваше предложение. –

3

Вы можете сделать пользовательский метод для выполнения этой задачи ,

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"; 
     } 
    } 
Смежные вопросы