Android – Por qué ConnectivityManager.isActiveNetworkMetered siempre devuelve true (incluso en Wifi)

En mi aplicación de streaming de música para Android, la ruta de código a continuación ayuda a decidir entre un flujo de bitrate alto y un bitrate inferior basado en los valores devueltos por la instancia de clase ConnectivityManager.

Estoy tratando de entender por qué ConnectivityManager.isActiveNetworkMetered () devolvería "true", cuando es evidente que estoy en una red Wifi local. Tome el siguiente código de Android / Java:

boolean isMetered = false; boolean isWifi = false; boolean isEthernet = false; boolean isRoaming = false; boolean isConnected = false; NetworkInfo netinfo = connManager.getActiveNetworkInfo(); if (netinfo != null) { isWifi = (netinfo.getType() == ConnectivityManager.TYPE_WIFI); isEthernet = (netinfo.getType() == ConnectivityManager.TYPE_ETHERNET); isRoaming = netinfo.isRoaming(); isConnected = netinfo.isConnected(); Log.d(TAG, "active network type = " + netinfo.getTypeName()); Log.d(TAG, "active network subtype = " + netinfo.getSubtypeName()); Log.d(TAG, "isConnected = " + isConnected); Log.d(TAG, "isWifi = " + isWifi); Log.d(TAG, "isEthernet = " + isEthernet); Log.d(TAG, "isRoaming = " + isRoaming); } // isActiveNetworkMetered was introduced in API 16 (Jelly Bean) if (android.os.Build.VERSION.SDK_INT >= 16) { isMetered = connManager.isActiveNetworkMetered(); Log.d(TAG, "isMetered = " + isMetered); } 

Cuando tengo Wifi apagado y mi única conexión es a la red LTE de AT & T, imprime lo siguiente a la consola de registro:

 active network type = mobile active network subtype = LTE isConnected = true isWifi = false isEthernet = false isRoaming = false isMetered = true 

Todo por encima de las expectativas – estoy en una red de carrier móvil que se mide.

Ahora cambie a mi casa Wifi y el mismo bloque de código imprime esto:

 active network type = WIFI active network subtype = isConnected = true isWifi = true isEthernet = false isRoaming = false isMetered = true 

¿Por qué isMetered , el resultado de isActiveNetworkMetered , sigue mostrando como verdad ? Esto está causando la ruta de código siguiente para favorecer el flujo de bitrate inferior aunque estoy en mi red wifi de casa:

 if ((isWifi || isEthernet) && !isMetered) { result = BITRATE_HIGH_KBIT_SEC; } else { result = BITRATE_LOW_KBIT_SEC; } 

¿Cómo se isActiveNetworkMetered () decide si la red se mide? ¿Es esta parte de la negociación WIFI o un poco en la difusión SSID? ¿Una configuración de red en Android? No pude encontrar ninguna configuración en mi dispositivo Kitkat de Android que me permite cambiar o descubrir el ajuste de una red medida.

La semana pasada mi ISP (Frontier) me envió un nuevo enrutador Wifi. ¿Posiblemente relacionado? No vi nada en las páginas de firmware del enrutador para ese ajuste.

Voy a trabajar por el trabajo más tarde hoy para ver cómo se comporta en otra red. En cualquier caso, es probable que modifique el código anterior para omitir el cheque medido a menos que pueda probar que es sólo un ajuste incorrecto en alguna parte.

ACTUALIZACIÓN : el problema de la reproducción de la red siempre medida se reproduce en mi teléfono HTC One M8 (con Kitkat), pero no en mi Nexus 7 a partir de 2012 (también actualizado a Android 4.4 Kitkat).

PROBLEMA SOLUCIONADO – resulta que mi Wifi fue marcado por mi teléfono como un "Mobile Hotspot". Más detalles sobre cómo encontrar y activar esta bandera está aquí .

One Solution collect form web for “Android – Por qué ConnectivityManager.isActiveNetworkMetered siempre devuelve true (incluso en Wifi)”

He probado esto también, pero estoy observando el resultado "esperado": falso para WiFi y verdadero para 3G. Esto está en un Nexus 4 con Android 4.4.2.

Curiosamente, la clase ConnectivityManagerCompat en la biblioteca de soporte técnico devuelve false para WiFi.

 final int type = info.getType(); switch (type) { case TYPE_MOBILE: return true; case TYPE_WIFI: return false; default: // err on side of caution return true; } 

EDITAR – Lo encontré (creo)

NetworkPolicyManagerService parece ser la clase que finalmente produce el resultado para este método. Y de acuerdo con ella, las conexiones WiFi pueden de hecho ser medido. Contiene un BroadcastReceiver que "escucha (s) los cambios de estado wifi para capturar la indicación medida" (línea 567). Esta información se obtiene de NetworkInfo.getMeteredHint() , que, en una inspección más cercana, contiene este interesante comentario:

 /** * Flag indicating that AP has hinted that upstream connection is metered, * and sensitive to heavy data transfers. */ private boolean mMeteredHint; 

Este indicador se carga desde DhcpResults.hasMeteredHint()

 /** * Test if this DHCP lease includes vendor hint that network link is * metered, and sensitive to heavy data transfers. */ public boolean hasMeteredHint() { if (vendorInfo != null) { return vendorInfo.contains("ANDROID_METERED"); } else { return false; } } 

Por lo tanto, parece que, de hecho, el AP puede notificar a sus clientes WiFi que la conexión subyacente de Internet se mide mediante el uso de este indicador.

EDIT # 2 Información relevante, desde http://www.lorier.net/docs/android-metered

Cuando un teléfono Android está usando el hotspot de otro teléfono de Android, sabe que está en una "conexión medida" y, por lo tanto, desactiva las opciones de sincronización caro (por ejemplo: sincronización de fotos). ¿Cómo lo sabe? El hotspot de Android envía la Opción DHCP 43 (Opciones específicas del proveedor) con el valor ANDROID_METERED. El cliente, si ve ANDROID_METERED en cualquier parte de los valores de la opción 43, activa la opción "costosa conexión de datos".

Parece que esta bandera se añadió a "play nice" con un hotspot ofrecido por otro dispositivo Android.

EDIT # 3 El commit que introdujo esta característica :

Conecte la sugerencia DHCP medida para redes Wi-Fi.

Cuando el arrendamiento de DHCP incluye información del proveedor que indica que la red Wi-Fi remota se mide, aconseje a NetworkPolicy. Los usuarios pueden cambiar manualmente el indicador medido en Configuración.

Puede acceder a esta configuración:

Configuración -> Uso de datos -> (menú de desbordamiento) -> Hotspots móviles

  • ¿Pueden funcionar wifi y 3G al mismo tiempo en Android?
  • ¿Es posible intercambiar mensajes entre 2 dispositivos Android a través de wifi?
  • Android tethering, cómo deshabilitar dhcp
  • Flujo de Android Wifi
  • Android WifiManager getScanResult se queja Necesita el permiso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION aunque el permiso declarado
  • Android: Simular WiFi en el emulador?
  • Establecer proxy WiFi sin rooting teléfono
  • Android 6.0 No se puede agregar WifiConfiguration si ya hay otra WifiConfiguration para ese SSID
  • Conexión WiFi de Android mediante programación
  • LocationManager devuelve la antigua ubicación en caché "Wifi" con la marca de hora actual
  • ¿Cómo obtener la fuerza de conexión de los puntos de acceso Wifi?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.