2010-05-10 93 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 2012-01-10 10:16:42

+0

哇!这非常有用。所有的网络类型都列出了,你也提到了他们的预期速度。伟大的代码! – kuchi 2012-01-20 10:24:53

+9

谢谢。顺便说一句,网络类型的所有常量([here](http://developer.android.com/reference/android/telephony/TelephonyManager.html))都是'public static final int'。所以你不需要做“黑客”。只要定位到最新的SDK,编译器就会将它们指向的真实值(整数)(不是它们的实例)编译成字节码。 – 2012-11-08 15:03:47

52

您可以使用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; 
} 

另外,请检查埃米尔的答案更详细的潜入这一点。

+0

WiMAX也没有?我无法弄清楚什么是支持IP的网络,什么不是(MMS) – sehugg 2010-09-20 16:49:37

+0

感谢您的文档队友! – 2011-04-08 10:43:03

+1

不错的演示文稿。感谢分享! – Udayan 2011-05-23 15:15:24

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

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

此方法返回描述当前连接类型的字符串。
即:“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 2015-12-07 10:31:23

+2

一个活动实现上下文,所以它是微不足道的。不是? – ben75 2015-12-07 12:06:58

2

在埃米尔的要命答案的顶部,我想补充一个方法,检查如果你确实有上网你可以有数据设置为关闭您的手机上。

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

请注意,这只是检查是否那里有一个蜂窝数据连接,并且将返回false,如果你有无线网络连接,如无线网络连接,当蜂窝数据关闭。

6

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

} 
+0

如何实现这个活动? – Joe 2015-12-07 10:30:16

+0

@Joe将该类复制到您的项目中,然后从您的活动中调用其中一个静态实用程序方法。例如:'if(NetworkUtils.isWifiConnection(this){/ * do stuff * /}' – 2015-12-07 10:40:38

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的建议。 – 2016-08-17 11:16:33

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