消除Android 5.0 ~ 7.1.1原生系統中感嘆號或叉號

weixin_34146805發表於2017-06-09

版權宣告:本文源自簡書tianma,轉載請務必註明出處: http://www.jianshu.com/p/441863cbc9ef

在使用Android5.0以上的原生系統過程中,大家會遇到明明自己網路是OK的,但是會在狀態列的移動訊號或 WiFi 圖示旁顯示感嘆號(5.0 ~ 7.0.0)或叉號(7.1.1),並且會提示“已連線,但不能接入網際網路”的情況... 如下圖所示:


448665-c2dfe80a96aa7a4f.jpg
原生系統中的歎號

原因

從Android 5.0開始,系統連線網路或切換網路時,系統模組 NetworkMonitor 會向一特定網址傳送資料請求,根據響應的結果從而判斷網路的連通性。在原生Android系統中,這一特定網址是Google的網址,不翻牆訪問不了,故而會出現感嘆號或叉號。

解決方案

既然知曉了原理,那麼解決方案也很明確了:

  1. 完全關閉網路檢查服務(不可取):
    adb shell settings put global captive_portal_detection_enabled 0
    
    缺點: 完全遮蔽該系統功能帶來明顯的問題,當你使用公共 Wi-Fi 這種需要使用 portal 驗證的網路時,因為網路檢查被關閉,系統在訪問 portal 驗證頁面時無法返回正確的值,最終導致無法完成驗證和上網。
  2. 替換檢查網路的網址(可取):
    通過ADB命令,將驗證服務的網址替換為國內正常可以訪問的網址

Android 5.x ~ 6.x 解決方案

adb shell "settings put global captive_portal_server www.v2ex.com"
adb shell reboot

Android 7.0.0 ~ 7.1.0 解決方案

adb shell "settings put global captive_portal_server captive.v2ex.co"
adb shell reboot

Android 7.1.1 解決方案

adb shell "settings put global captive_portal_https_url https://captive.v2ex.co/generate_204"
adb shell reboot

原始碼

問題解決了,問題產生的根本源頭在哪呢,在原始碼裡面 :)

Android 5.x ~ 6.x

    private int isCaptivePortal() {
        if (!mIsCaptivePortalCheckEnabled) return 204;
        HttpURLConnection urlConnection = null;
        int httpResponseCode = 599;
        try {
            URL url = new URL("http", mServer, "/generate_204");
            if (DBG) {
                log("Checking " + url.toString() + " on " +
                        mNetworkAgentInfo.networkInfo.getExtraInfo());
            }
        } // ...
    }

原來的 mServerclients3.google.com,我們最終將其換為 www.v2ex.com.

Android 7.0 ~ 7.1.0

private static String getCaptivePortalServerUrl(Context context, boolean isHttps) {
    String server = Settings.Global.getString(context.getContentResolver(),
            Settings.Global.CAPTIVE_PORTAL_SERVER);
    if (server == null) server = DEFAULT_SERVER;
    return (isHttps ? "https" : "http") + "://" + server + "/generate_204";
}

Android 7.0 ~ 7.1.0 新增了https的驗證請求,所以我們把 server 的值改為支援https的 captive.v2ex.co.

Android 7.1.1

private static String getCaptivePortalServerHttpsUrl(Context context) {
    return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
}

DEFAULT_HTTPS_URL 的值由原來的 https://www.google.com/generate_204 替換為 https://captive.v2ex.co/generate_204.

相關原始碼連結:

參考

消除 Android 7.0 中 Wi-Fi 和行動網路上的感嘆號 | 一日一技 · Android

相關文章