Android 控件WebView設置Cookie

 

01. 設置方式

同步的問題很常見,網上搜到的解決方法基本相似。數據庫

/**
   * 給WebView同步Cookie
   *
   * @param context 上下文
   * @param url     可使用[domain][host]
   */
  private void syncCookie(Context context, String url) {
    CookieSyncManager.createInstance(context);
    CookieManager cookieManager = CookieManager.getInstance();
    cookieManager.setAcceptCookie(true);
    cookieManager.removeSessionCookie();// 移除舊的[能夠省略]
    List<HttpCookie> cookies = new PersistentCookieStore(context).getCookies();// 獲取Cookie[能夠是其餘的方式獲取]
    for (int i = 0; i < cookies.size(); i++) {
      HttpCookie cookie = cookies.get(i);
      String value = cookie.getName() + "=" + cookie.getValue();
      cookieManager.setCookie(url, value);
    }
    CookieSyncManager.getInstance().sync();// To get instant sync instead of waiting for the timer to trigger, the host can call this.
  }

這裏簡單說明:服務器

  • 參數中的URL在使用過程當中基本是域名。例如https://www.baidu.com/就可使www.baidu.com
  • Cookie列表的獲取根據本身項目的存儲方式不一樣而不一樣。例如使用SharedPreferencesHashMap
  • 注意使用for循環進行setCookie(String url, String value)調用。網上有博客表示使用分號手動拼接的value值會致使cookie不能完整設置或者無效
  • 注意value的值是使用key=value的完整形式。文檔提示the cookie as a string, using the format of the 'Set-Cookie' HTTP response header
  • CookieSyncManager是個過期的類,Api21中WebView能夠自動同步。
  • CookieSyncManager.getInstance().sync();方法的替代方法是cookieManager.flush();
  • Cookie同步方法要在WebView的setting設置完以後調用,不然無效。
  • 調用loadUrl(url);前一句調用此方法進行Cookie同步操做。
/**
 * 獲取URL的域名
 */
private String getDomain(String url){
  url = url.replace("http://", "").replace("https://", "");
  if (url.contains("/")) {
    url = url.substring(0, url.indexOf('/'));
  }
  return url;
}

02. 保存Cookie

在這裏記錄一下使用SharedPreferences保存整個Cookie串並使用HashMap存儲鍵值對cookie

/**
 * 獲取本地存儲的 Cookie 集合
 *
 * @return Cookie 鍵值對
 */
public Map<String, String> getCookieMap() {
    Map<String, String> cookieMap = new HashMap<>();
    String cookie = getCookie();// 從SharedPreferences中獲取整個Cookie串
    if (!TextUtils.isEmpty(cookie)) {
        String[] cookieArray = cookie.split(";");// 多個Cookie是使用分號分隔的
        for (int i = 0; i < cookieArray.length; i++) {
            int position = cookieArray[i].indexOf("=");// 在Cookie中鍵值使用等號分隔
            String cookieName = cookieArray[i].substring(0, position);// 獲取鍵
            String cookieValue = cookieArray[i].substring(position + 1);// 獲取值
            cookieMap.put(cookieName, NetCodeUtil.encodeURL(cookieValue));// 存至Map
            // 解碼使用 URLEncoder.encode(str, "UTF-8");
        }
    }
    return cookieMap;
}

注意:編解碼,從請求頭中獲取到的Cookie是通過URL 編碼的,解碼後能夠獲取到姓名之類中文,在給WebView或者是其餘請求設置Cookie的時候須要進行編碼。app

CookieUtil cookieUtil = new CookieUtil(this);// 將 Cookie 保存在了 SharedPreferences
Map<String, String> cookieMap = cookieUtil.getCookieMap();// 獲取鍵值對
for (Map.Entry<String, String> entry : cookieMap.entrySet()) {// 遍歷 Map
    String value = entry.getKey() + "=" + entry.getValue();// 鍵值對拼接成 value
    cookieManager.setCookie(url, value);// 設置 Cookie
}

03. 域名不一樣

使用WebView加載A接口獲取到展現的界面,界面須要填充的數據會自動請求B接口。這兩接口域名不相同,以前服務器升級的時候搞了一個新的域名。抓包發現AB兩個接口域名不一樣A爲舊 B爲新dom

  • 嘗試對兩個域名設置Cookie測試發現不沒有效果
  • 嘗試將兩個接口的域名設置爲相同的測試發現兩個接口都攜帶了Cookie

進行了一番搜索以後,發現有在強調,只有cookie的domain和path與請求的URL匹配纔會發送這個cookie學習

/**
 * Sets a cookie for the given URL. Any existing cookie with the same host,
 * path and name will be replaced with the new cookie. The cookie being set
 * will be ignored if it is expired.
 *
 * @param url the URL for which the cookie is to be set
 * @param value the cookie as a string, using the format of the 'Set-Cookie'
 *              HTTP response header
 */
public abstract void setCookie(String url, String value);

註釋中寫到,具備相同的hostpathname的任何現有的Cookie將會被替換爲新的Cookie。測試

04. Cookie保存位置

項目中使用WebView其實會自動將Cookie保存在本地數據庫中。保存是路徑爲data/data/package_name/app_WebView/Cookies雖然不是.db結尾的,實際就是一個.db文件this

參考文檔

  1. 安卓學習筆記---AndroidWebview裏設置Cookie遇到的坑



做者:JustDo23
連接:http://www.jianshu.com/p/c9a9c4e1756d
來源:簡書
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。編碼

相關文章
相關標籤/搜索