Android上如何检查网络连接

24
我有以下用于检查应用程序的网络连接wifi/EDGE/GPRS/3G的代码。
代码如下:
public static boolean checkConn(Context ctx) {
    ConnectivityManager conMgr = (ConnectivityManager) ctx
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (conMgr.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED
        || conMgr.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTING) {
        return true;
    } else if (conMgr.getNetworkInfo(0).getState()==NetworkInfo.State.DISCONNECTED
        || conMgr.getNetworkInfo(1).getState() == NetworkInfo.State.DISCONNECTED){
        return false;
    }
    return false;
}

我这样调用:

if (CheckInternet.checkConn(introPage.this) == true) {
    Intent toMainPage = new Intent(introPage.this, mainPage.class);
    System.gc();
    startActivity(toMainPage);
} else if (CheckInternet.checkConn(getApplicationContext()) == false) {
    Toast.makeText(getApplicationContext(),
        "Sorry, No internet connectivity found", Toast.LENGTH_SHORT)
            .show();
}

我遇到了一个问题,就是当我连接WiFi并打开应用程序时,它可以正常工作,但是如果我关闭应用程序并关闭WiFi,然后重新打开应用程序,它不会出现“无连接”的错误提示,我需要关闭设备然后重新开启,而且如果WiFi处于关闭状态,我打开应用程序时,它会抛出“无连接”的错误提示,并且即使我打开WiFi,仍然会出现相同的“无连接”错误提示,除非我关闭设备并重新打开。


通过按主页或返回键关闭应用程序?因为如果您通过按主页键关闭它,那么应用程序将在后台运行,oncreate将不会被触发。 - DeRagan
@Rahul,但是为什么即使打开了Wi-Fi,它仍然显示无连接的问题呢? - Adil Bhatty
@Paresh 我有三星Vibrant手机,但即使在模拟器上也遇到了同样的问题。 - Adil Bhatty
你不需要测试函数是否返回某个值,因为if语句会对其进行评估。你可以像这样编写条件语句: if(CheckInternet.checkConn(introPage.this)) { ... } else { ... } - dinigo
显示剩余3条评论
9个回答

69

有时活动连接不在列表中的第一位,或者处于非活动或错误状态。我会这样做:

  NetworkInfo i = conMgr.getActiveNetworkInfo();
  if (i == null)
    return false;
  if (!i.isConnected())
    return false;
  if (!i.isAvailable())
    return false;
  return true;

[编辑 1] 别忘了在应用清单中添加这个权限:

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

这有帮助吗?

Emmanuel


2
你需要检查网络类型。i.getType() == ConnectivityManager.TYPE_MOBILE,你甚至可以获取子类型。i.getSubType() == TelephonyManager.NETWORK_TYPE_* - Emmanuel
1
请将此编辑为 return i != null && i.isConnected() && i.isAvailable(); - Mr_and_Mrs_D
@Mr_and_Mrs_D:看,我复制/粘贴了一些我已经应用“使用守卫语句替换嵌套条件表达式”重构的代码。这3个条件只是开始;还有其他条件。再加上它更易读。 - Emmanuel
请在此处查看程序相关内容的翻译:https://dev59.com/nG855IYBdhLWcg3w6IvV#8343843 - 答案越简洁越好 ;) - Mr_and_Mrs_D
2
@Emmanuel: 另外,在一些国家,禁止没有{}的if块是违法的。 - njzk2
显示剩余4条评论

3
简而言之:
public boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager = (ConnectivityManager)getActivity().getApplicationContext()
                                              .getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}

2
public static boolean checkNetworkStatus(Context context) {
    ConnectivityManager connectivity = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    TelephonyManager telephony = (TelephonyManager) context
            .getSystemService(Context.TELEPHONY_SERVICE);
    NetworkStatus netStatus = new NetworkStatus(connectivity, telephony);
    if (netStatus.isNetworkAvailable() == true) {
        Log.e(" in checkNetworkStatus()", "network available");
        return true;
    } else {
        Log.e(" in checkNetworkStatus()", "no network");
        return false;
    }
}

wifi-


void chkStatus() {
    final ConnectivityManager connMgr = (ConnectivityManager) this
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    final android.net.NetworkInfo wifi = connMgr
            .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    final android.net.NetworkInfo mobile = connMgr
            .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    if (wifi.isAvailable()) {
        Toast.makeText(this, "Wifi", Toast.LENGTH_LONG).show();
    } else if (mobile.isAvailable()) {
        Toast.makeText(this, "Mobile 3G ", Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(this, "No Network ", Toast.LENGTH_LONG).show();
    }
}

2

更好的方式是:

if (conMgr != null) {
    NetworkInfo i = conMgr.getActiveNetworkInfo();
    if (i != null) {
        if (!i.isConnected())
            ret = false;
        if (!i.isAvailable())
            ret = false;                
    }

    if (i == null)
        ret = false;

} else
    ret = false;

使用另一种形式,如果 "Network i" 等于 null,则必须在其后检查 !i.isConnected() 是否失败(其中 i 为 null)。

为什么不采用黑色方法而不是白色方法? - Emre Yazici
你错了,在另一种形式中,“如果(i==null)”将“返回false”,所以跳过其余所有检查。此外,在另一种方式中,嵌套较少(CC减少)。 - NicoGranelli
“return”比使用“else”更好(“else”会导致错误) - SparK

1

试试这个:

public boolean isInternetAvailable(Context context) {
        ConnectivityManager conMgr = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo i = conMgr.getActiveNetworkInfo();
          if (i == null)
            return false;
          if (!i.isConnected())
            return false;
          if (!i.isAvailable())
            return false;
          return true;

    }

还有这个权限:

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


0

与批准的答案相同,但简短:

public static boolean isNetworkAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo info = cm.getActiveNetworkInfo();
    return info != null && info.isConnected() && info.isAvailable();
}

0
你可以使用这个很棒的 emil2k 的 gist

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;

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

}

0
我以前常用这种方式检查我的网络连接状态。但请别忘了,如果你在平板电脑中使用,有些平板电脑没有移动数据连接功能,对于 TYPE_MOBILE 的 NetworkInfo 返回值将为 null,所以也要注意检查它是否为空值。
public static boolean collectionAllowed(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo mobileInfo = connectivityManager.getNetworkInfo(
            ConnectivityManager.TYPE_MOBILE);
    State mobile = NetworkInfo.State.DISCONNECTED;
    if ( mobileInfo != null) {
        mobile = mobileInfo.getState();
    }
    NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(
            ConnectivityManager.TYPE_WIFI);
    State wifi = NetworkInfo.State.DISCONNECTED;
    if ( wifiInfo != null) {
        wifi = wifiInfo.getState();
    }
    boolean dataOnWifiOnly = (Boolean) PreferenceManager
            .getDefaultSharedPreferences(context).getBoolean(
                    "data_wifi_only", true);
    if ((!dataOnWifiOnly && (mobile.equals(NetworkInfo.State.CONNECTED) || wifi
            .equals(NetworkInfo.State.CONNECTED)))
            || (dataOnWifiOnly && wifi.equals(NetworkInfo.State.CONNECTED))) {
        return true;
    } else {
        return false;
    }
}

0

嗨,试试下面的代码:

   public class NetworkCheckDemo extends Activity
 {
TextView tvstatus;
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    tvstatus=(TextView)findViewById(R.id.txtviewstatus);
    ConnectivityManager cn=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo nf=cn.getActiveNetworkInfo();
    if(nf != null && nf.isConnected()==true )
    {
        Toast.makeText(this, "Network Available", Toast.LENGTH_LONG).show();
        tvstatus.setText("Network Available");
    }
    else
    {
        Toast.makeText(this, "Network Not Available", Toast.LENGTH_LONG).show();
        tvstatus.setText("Network Not Available");
      }
    }
  }

请在Android清单文件中添加以下3个权限。
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

2
CHANGE_NETWORK_STATE 不是必需的。 - njzk2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接