Android - Why ConnectivityManager.isActiveNetworkMetered always returning true (even when on Wifi)

前端 未结 1 1807
时光取名叫无心
时光取名叫无心 2020-12-30 10:33

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 ConnectivityManage

相关标签:
1条回答
  • 2020-12-30 10:57

    I've tested this too, but I'm observing the "expected" result: false for WiFi and true for 3G. This is in a Nexus 4 with Android 4.4.2.

    Curiously enough the ConnectivityManagerCompat class in the support library does return false for 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;
    }
    

    EDIT - Found it (I think)

    NetworkPolicyManagerService seems to be the class that ultimately produces the result for this method. And according to it, WiFi connections can indeed be metered. It contains a BroadcastReceiver that "listen(s) for wifi state changes to catch metered hint" (line 567). This information is obtained from NetworkInfo.getMeteredHint(), which, on closer inspection, contains this interesting comment:

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

    This flag is loaded from 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;
        }
    }
    

    So it would seem that, indeed, the AP may notify its WiFi clients that the underlying internet connection is metered by using this flag.

    EDIT #2 Relevant information, from http://www.lorier.net/docs/android-metered

    When an android phone is using another android phone's hotspot, it knows it's on a "metered connection" and therefore disables the expensive sync options ( eg: photo sync). How does it know this? The android hotspot sends DHCP Option 43 (Vendor specific options) with the value ANDROID_METERED. The client, if it sees ANDROID_METERED anywhere in the option 43 values, turns on the "expensive data connection" option.

    Looks like this flag was added to "play nice" with a hotspot offered by another Android device.

    EDIT #3 The commit that introduced this feature:

    Connect metered DHCP hint for Wi-Fi networks.

    When DHCP lease includes vendor info indicating that remote Wi-Fi network is metered, advise NetworkPolicy. Users can still manually change the metered flag in Settings.

    You can access this setting by going:

    Settings -> Data Usage -> (Overflow Menu) -> Mobile Hotspots

    0 讨论(0)
提交回复
热议问题