190

Android でネットワーク接続の種類をどのように検出しますか?

経由ConnectivityManager.getActiveNetworkInfo().getType()ですか、答えは Wifi とモバイルに限られますか?

4

14 に答える 14

456

問題が電話のネットワークが接続されていて、要求を満たすのに十分な速さであるかどうかを確認することである場合は、によって返されるすべてのネットワークタイプを処理する必要がありますgetSubType()

まさにそれを行うためにこのクラスを研究して書くのに1、2時間かかりました、そして私はそれが役に立つかもしれない他の人とそれを共有したいと思いました。

これがクラスの要点ですので、フォークして編集することができます。

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
     * @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
     * @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が含まれます。

于 2011-12-18T00:15:45.930 に答える
66

接続タイプに関するより正確な (そしてユーザーフレンドリーな) 情報を取得するため。このコードを使用できます ( TelephonyManager.javaの @hide メソッドから派生)。

このメソッドは、現在の接続タイプを表す文字列を返します。
つまり、「WIFI」、「2G」、「3G」、「4G」、「5G」、「-」(未接続)、「?」のいずれかです。(わからない)

備考: このコードには API 25+ が必要ですが、const の代わりに int を使用することで古いバージョンを簡単にサポートできます。(コード内のコメントを参照してください)。

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
            case TelephonyManager.NETWORK_TYPE_GSM:      // api<25: replace by 16
                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 12
            case TelephonyManager.NETWORK_TYPE_EHRPD:    // api<11: replace by 14
            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";
            case TelephonyManager.NETWORK_TYPE_NR:       // api<29: replace by 20
                return "5G";
            default:
                return "?";
         }
    }
    return "?";
}
于 2014-09-18T12:20:40.803 に答える
53

詳細については、 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 の回答をご覧ください。

于 2010-05-31T20:10:57.257 に答える
12

上記の@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()));
}
于 2013-03-01T11:54:21.630 に答える
7

Emil Davtyan からの回答は良いですが、彼の回答では説明されていないネットワーク タイプが追加されています。そのため、isConnectionFast(int type, int subType)true であるべきときに 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();
  }

}
于 2015-11-13T01:27:39.903 に答える
5

カスタム メソッドを作成して、このタスクを実行できます。

  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";
        }
    }
于 2017-02-02T10:16:13.527 に答える
2

Emil の素晴らしい回答に加えて、もう 1 つの方法を追加したいと思います。これは、電話でデータをオフに設定できるため、実際にインターネットにアクセスできるかどうかを確認するためのものです。

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 が接続されている場合はセルラー データがオフになるため、WiFi が接続されている場合は false を返すことに注意してください。

于 2015-01-08T18:53:34.270 に答える
2

このように確認できます

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();
        }
    }
}
于 2016-08-16T14:23:23.647 に答える
1
String active_network = ((ConnectivityManager)
    .getSystemService(Context.CONNECTIVITY_SERVICE))
    .getActiveNetworkInfo().getSubtypeName();

ネットワーク名を取得する必要があります

于 2012-09-27T19:04:35.917 に答える
1

私はこの簡単なコードを使用します:

fun getConnectionInfo(): ConnectionInfo {
    val cm = appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    return if (cm.activeNetwork == null) {
        ConnectionInfo.NO_CONNECTION
    } else {
        if (cm.isActiveNetworkMetered) {
            ConnectionInfo.MOBILE
        } else {
            ConnectionInfo.WI_FI
        }
    }
}
于 2020-10-27T12:56:56.187 に答える
0

現在、モバイルと WIFI のみがサポートされています。人間が読める型 functionを見てください。

于 2010-05-10T12:20:22.060 に答える