In my music streaming app for Android, the code path below helps decides between a high bitrate stream vs. a lower bitrate based on values returned by the ConnectivityManager class instance.
I am trying to understand why ConnectivityManager.isActiveNetworkMetered() would return "true", when it's evident I'm on a local Wifi network. Take the following Android/Java code:
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);
}
When I have Wifi turned off and my only connection is to AT&T's LTE network, it prints out the following to the log console:
active network type = mobile
active network subtype = LTE
isConnected = true
isWifi = false
isEthernet = false
isRoaming = false
isMetered = true
Everything above matches expectations - I'm on a mobile carrier network that is metered.
Now switch to my home Wifi and the same block of code prints this:
active network type = WIFI
active network subtype =
isConnected = true
isWifi = true
isEthernet = false
isRoaming = false
isMetered = true
Why is isMetered
, the result of isActiveNetworkMetered
, still showing as true? This is causing the following code path to favor the lower bitrate stream even though I'm on my home wifi network:
if ((isWifi || isEthernet) && !isMetered)
{
result = BITRATE_HIGH_KBIT_SEC;
}
else
{
result = BITRATE_LOW_KBIT_SEC;
}
How does isActiveNetworkMetered() decide if the network is metered? Is this part of the WIFI negotiation or a bit in the SSID broadcast? A network setting on Android? I couldn't find any setting on my Android Kitkat device that let me toggle or discover the setting for a metered network.
Last week I my ISP (Frontier) sent me a new Wifi router. Possibly related? I didn't see anything on the router's firmware pages for such a setting.
I'm going to swing by work later today to see how it behaves on another network. In any case, I'm likely to edit the above code to skip the metered check unless I can prove its just an incorrect setting somewhere.
UPDATE - issue of always returning metered network reproduces on my HTC One M8 phone (running Kitkat), but not on my Nexus 7 from 2012 (also upgraded to Android 4.4 Kitkat).
PROBLEM SOLVED - it turns out my Wifi was flagged by my phone as a "Mobile Hotspot". More details on how to find and toggle this flag is here.