网络查询 Android 中的网络类型,一般通过以下步骤获取:
使用 ConnectivityManager.getActiveNetworkInfo() 拿到 NetworkInfo。
根据 networkInfo.getType() 判断是 WIFI 或者 移动网络。
如果是移动网络,进一步通过 networkInfo.getSubtype() 判断是 2G、3G、4G、5G 等具体类型。
API 29(Android 10)中,NetworkInfo (包含相关 API)都已被标记为 Deprecated,Google 官方推荐使用 NetworkCapabilities 来判断网络状态。步骤如下:
使用 connectManager.getActiveNetwork() 拿到 Network。
使用 connectManager.getNetworkCapabilities(network) 拿到 NetworkCapabilities。
通过 capabilities.hasCapability() 判断是 WIFI 或者 移动网络。
如果是移动网络,使用 telephonyManager.getDataNetworkType() 判断是 2G、3G、4G、5G 等具体类型。
调用 telephonyManager.getDataNetworkType() 接口 需要用到 READ_PHONE_STATE 敏感权限。
NetworkCapabilities 方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public int GetDetailNetworkState (Context context) { try { if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_NETWORK_STATE)) { Log.w(TAG, "has no ACCESS_NETWORK_STATE permission" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } ConnectivityManager connectManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == connectManager) { Log.w(TAG, "ConnectivityManager is null" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } Network network = connectManager.getActiveNetwork(); NetworkCapabilities capabilities = connectManager.getNetworkCapabilities(network); if (null == capabilities) { Log.w(TAG, "NetworkCapabilities is null" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } boolean hasCapability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); if (!hasCapability) { Log.w(TAG, "has no Capability: NET_CAPABILITY_INTERNET" ); return NetworkDefines.NETWORK_STATE_UNAVAILABLE; } boolean hasWifiTrans = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI); if (hasWifiTrans) { return NetworkDefines.NETWORK_STATE_AVAILABLE_WIFI; } boolean hasCellTrans = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR); if (hasCellTrans) { if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)) { Log.w(TAG, "has no READ_PHONE_STATE permission" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_MOBILE; } TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (null == telephonyManager) { return NetworkDefines.NETWORK_STATE_AVAILABLE_MOBILE; } return covertNetType (telephonyManager.getDataNetworkType()); } return NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER; } catch (Exception e) { Log.w(TAG, "check Get exception:" + e.toString()); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } }
通过 telephonyManager.getDataNetworkType() 获取移动网络类型,需要用到 READ_PHONE_STATE 权限。
NetworkInfo 方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public int GetDetailNetworkState (Context context) { try { if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_NETWORK_STATE)) { Log.w(TAG, "has no ACCESS_NETWORK_STATE permission" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } ConnectivityManager connectManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == connectManager) { Log.w(TAG, "ConnectivityManager is null" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } NetworkInfo networkInfo = connectManager.getActiveNetworkInfo(); if (null == networkInfo) { Log.w(TAG, "NetworkInfo is null" ); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } if (ConnectivityManager.TYPE_WIFI == networkInfo.getType()) { return NetworkDefines.NETWORK_STATE_AVAILABLE_WIFI; } if (ConnectivityManager.TYPE_MOBILE == networkInfo.getType()) { return covertNetType (networkInfo.getSubtype()); } return NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER; } catch (Exception e) { Log.w(TAG, "check Get exception:" + e.toString()); return NetworkDefines.NETWORK_STATE_AVAILABLE_UNKNOWN; } }
移动网络类型判断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private int covertNetType (int networkType) { switch (networkType) { case TelephonyManager.NETWORK_TYPE_GPRS: case TelephonyManager.NETWORK_TYPE_EDGE: case TelephonyManager.NETWORK_TYPE_CDMA: case TelephonyManager.NETWORK_TYPE_IDEN: case TelephonyManager.NETWORK_TYPE_1xRTT: return NetworkDefines.NETWORK_STATE_AVAILABLE_2G; case TelephonyManager.NETWORK_TYPE_UMTS: case TelephonyManager.NETWORK_TYPE_EVDO_0: case TelephonyManager.NETWORK_TYPE_EVDO_A: case TelephonyManager.NETWORK_TYPE_EVDO_B: case TelephonyManager.NETWORK_TYPE_HSDPA: case TelephonyManager.NETWORK_TYPE_HSUPA: case TelephonyManager.NETWORK_TYPE_HSPA: case TelephonyManager.NETWORK_TYPE_HSPAP: case TelephonyManager.NETWORK_TYPE_EHRPD: return NetworkDefines.NETWORK_STATE_AVAILABLE_3G; case TelephonyManager.NETWORK_TYPE_LTE: case 19 : return NetworkDefines.NETWORK_STATE_AVAILABLE_4G; case 20 : return NetworkDefines.NETWORK_STATE_AVAILABLE_5G; case TelephonyManager.NETWORK_TYPE_UNKNOWN: default : return NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER; } }
网络监听 早期的 Android 版本,应用一般采用监听广播的方式,监听系统网络事件。但 Android N 以后,google 官方声明此方法已经不推荐使用。高版本的系统,使用 ConnectivityManager.NetworkCallback 进行网络监听。
无论是广播监听方案,或者是网络回调方案,一般在 onCreate/onDestroy 生命周期中,分别进行注册/反注册监听。
网络回调方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 public void registerNetworkListener (Context context) { if (mNetworkChangeCallback != null ) { Log.w(TAG, "NetworkCallback registered" ); return ; } ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager != null ) { mNetworkChangeCallback = new NetworkChangeCallback (); connectivityManager.registerDefaultNetworkCallback(mNetworkChangeCallback); } } public void unregisterNetworkListener (Context context) { if (mNetworkChangeCallback != null ) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager != null ) { connectivityManager.unregisterNetworkCallback(mNetworkChangeCallback); mNetworkChangeCallback = null ; } } } @android .support.annotation.RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)protected class NetworkChangeCallback extends ConnectivityManager .NetworkCallback { @Override public void onAvailable (Network network) { super .onAvailable(network); Log.d(TAG, "network available" ); handleNetworkChange(NETWORK_STATE_AVAILABLE); } @Override public void onLost (Network network) { super .onLost(network); Log.i(TAG, "network unavailable" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_UNAVAILABLE); } @Override public void onCapabilitiesChanged (Network network, NetworkCapabilities networkCapabilities) { super .onCapabilitiesChanged(network, networkCapabilities); if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)){ if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){ Log.i(TAG, "network available for wifi" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_WIFI); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { Log.i(TAG, "network available for mobile" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_MOBILE); } else { Log.i(TAG, "network available for other" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER); } } if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { Log.d(TAG, "internet online" ); } } }
动态注册广播方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public void registerNetworkListener (Context context) { if (mNetworkChangeReceiver != null ) { Log.w(TAG, "NetworkChangeReceiver registered" ); return ; } mNetworkChangeReceiver = new NetworkChangeReceiver (); IntentFilter filter = new IntentFilter (); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mNetworkChangeReceiver, filter); } public void unregisterNetworkListener (Context context) { if (mNetworkChangeReceiver != null ) { context.unregisterReceiver(mNetworkChangeReceiver); mNetworkChangeReceiver = null ; } } protected class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive (Context context, Intent intent) { ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = connManager.getActiveNetworkInfo(); if (null == netInfo || !netInfo.isConnected()) { handleNetworkChange(NetworkDefines.NETWORK_STATE_UNAVAILABLE); } else { switch (netInfo.getType()) { case ConnectivityManager.TYPE_MOBILE: { Log.i(TAG, "Receive Network State TYPE_MOBILE" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_MOBILE); break ; } case ConnectivityManager.TYPE_WIFI: { Log.i(TAG, "Receive Network State TYPE_WIFI" ); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_WIFI); break ; } default : { Log.i(TAG, "Receive Network State, Other:" + netInfo.getType()); handleNetworkChange(NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER); break ; } } } } }
回调通知处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class NetworkDefines { public static final int NETWORK_STATE_AVAILABLE_UNKNOWN= -1 ; public static final int NETWORK_STATE_UNAVAILABLE = 0 ; public static final int NETWORK_STATE_AVAILABLE_MOBILE = 1 ; public static final int NETWORK_STATE_AVAILABLE_WIFI = 2 ; public static final int NETWORK_STATE_AVAILABLE_OTHER = 3 ; public static final int NETWORK_STATE_AVAILABLE_2G = 12 ; public static final int NETWORK_STATE_AVAILABLE_3G = 13 ; public static final int NETWORK_STATE_AVAILABLE_4G = 14 ; public static final int NETWORK_STATE_AVAILABLE_5G = 15 ; } private void handleNetworkChange (int networkState) { if (mLastState == networkState) { Log.w(TAG, "Network State not change:" + networkState); return ; } if (mLastState != NetworkDefines.NETWORK_STATE_UNAVAILABLE && networkState != NetworkDefines.NETWORK_STATE_UNAVAILABLE) { Log.i(TAG,"Notify: Network State change to TYPE_NONE (insert)" ); } mLastState = networkState; switch (networkState){ case NetworkDefines.NETWORK_STATE_UNAVAILABLE: Log.i(TAG,"Notify: Network State change to TYPE_NONE" ); break ; case NetworkDefines.NETWORK_STATE_AVAILABLE_WIFI: Log.i(TAG,"Notify: Network State change to TYPE_WIFI" ); break ; case NetworkDefines.NETWORK_STATE_AVAILABLE_MOBILE: Log.i(TAG,"Notify: Network State change to TYPE_MOBILE" ); break ; case NetworkDefines.NETWORK_STATE_AVAILABLE_OTHER: Log.i(TAG,"Notify: Network State change to TYPE_OTHER" ); break ; default : break ; } }
正常来说,任何两个网络直接切换,都会产生一个断网的中间状态,但是某些情况下,监听结果会直接跳过。为了保证一致性,在回调处理时,会根据前一次的状态,插入一个断网态。
参考文档