Volley自動獲取以及儲存Cookie
Volley是Google開發的一款android網路框架,非常適合小資料大併發的訪問伺服器,但Volley中沒有提供Cookie方面的管理,幸好它是開源框架,下面就跟大家分享一下具體的修改流程:
提示:Http請求分為request和response,兩者都有頭資訊,而Cookie的資訊就是在頭資訊中進行傳遞,所以可以鎖定,需要修改的地方在頭資訊相關的地方。
第一步:
通過檢視原始碼發現,com.android.volley.toolbox.HurlStack.java檔案中存在方法performRequest,在方法的下半部分是獲取到了響應頭的相關資訊,所以在遍歷響應頭
for (Entry< String, List<String>> header : connection.getHeaderFields().entrySet()) {
if (header.getKey() != null) {
在這段程式碼的下面新增以下程式碼:
// 將Cookie全部獲取
if ("Set-Cookie".equals(header.getKey())) {
StringBuilder mCookieStr = new StringBuilder();
for (int i = 0; i < header.getValue(). size(); i++) {
if (i == header.getValue().size() - 1) {
mCookieStr.append(header.getValue().get(i));
} else {
mCookieStr.append(header.getValue().get(i)
+ "*end*");
}
}
Header h = new BasicHeader(header.getKey(),
mCookieStr. toString());
response.addHeader(h);
} else {
Header h = new BasicHeader(header.getKey(), header
.getValue().get(0));
response.addHeader(h);
}
說明:程式碼中預設只顯示一條Set-Cookie響應頭,顯然這樣不是我們想要的,因為Set-Cookie可能會存在多條資料,所以我們需要把所有的Set-Cookie拼接起來
第二步:
添加了Cookie資訊到響應頭中,那麼接著就要進行獲取,然後判斷後進行儲存。繼續檢視原始碼,找到com.android.volley.toolbox.BasicNetwork.java檔案中的performRequest方法,在
httpResponse = mHttpStack.performRequest(request, headers);
這段程式碼下面新增
// Save Cookies @author Hunter
try {
SaveCookies(httpResponse);
} catch (DateParseException e) {
e.printStackTrace();
}
這個SaveCookies的方法是處理Cookie並存儲的,程式碼如下:
/**
* @author Hunter
* 用於儲存Cookie的方法
* @param httpResponse
* @throws DateParseException
*/
public void SaveCookies(HttpResponse httpResponse) throws DateParseException {
Header[] headers = httpResponse.getHeaders("Set-Cookie");
Cookie cookieBean = new Cookie();
/** Cookie儲存池 */
List<Cookie> mCookieContiner = new ArrayList<Cookie>();
if (headers == null || headers.length == 0)
return;
// 遍歷Set-Cookie中的所有value
for (int i = 0; i < headers.length; i++) {
// 將每個value中以字串"*end*"分割
String cookie = headers[i].getValue();
String[] cookievalues = cookie.split("\\*end\\*");
// 遍歷每個分割的資料得到多條cookie
for (int j = 0; j < cookievalues.length; j++) {
// 分割每個cookie得到各個屬性
String[] cookiePair = cookievalues[j].split(";");
cookieBean = new Cookie();
// 遍歷每個屬性 將對應的值插入
for (int k = 0; k < cookiePair.length; k++) {
String[] keyPair = cookiePair[k].split("=");
String key = keyPair[0].trim();
String value = keyPair.length > 1 ? keyPair[1].trim() : "";
if("expires".equals(key)){
Date parseDate = DateUtils.parseDate(value);
cookieBean.setExpires(parseDate);
}else if("domain".equals(key)){
cookieBean.setDomain(value);
}else if("path".equals(key)){
cookieBean.setPath(value);
}else{
cookieBean.setKey(key);
cookieBean.setValue(value);
}
}
// 儲存每個cookie到cookie儲存池中
mCookieContiner.add(cookieBean);
MyApplication.setCookies(mCookieContiner);
}
}
MyCookieDao cookieDao = MyCookieDao.getInstance(MyApplication.getInstance());
cookieDao.saveCookieLists(mCookieContiner);
}
上面的方法用到了第三方資料庫框架GreenDao,其中Cookie實體類的程式碼是:
package com.example.android;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit.
/**
* Entity mapped to table COOKIE.
*/
public class Cookie {
private Long id;
/** Not-null value. */
private String key;
private String value;
private String domain;
private String path;
private java.util.Date expires;
public Cookie() {
}
public Cookie(Long id) {
this.id = id;
}
public Cookie(Long id, String key, String value, String domain,
String path, java.util.Date expires) {
this.id = id;
this.key = key;
this.value = value;
this.domain = domain;
this.path = path;
this.expires = expires;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/** Not-null value. */
public String getKey() {
return key;
}
/**
* Not-null value; ensure this value is available before it is saved to the
* database.
*/
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public java.util.Date getExpires() {
return expires;
}
public void setExpires(java.util.Date expires) {
this.expires = expires;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Cookie other = (Cookie) obj;
if (key == null || other.key == null) {
return false;
} else if (!key.equals(other.key))
return false;
return true;
}
}
該方法是自動生成的,不會使用的朋友可以去查詢GreenDao的相關資料。
第三步:
完成後自定義一個MyCookieDao,用於操作Cookie的儲存與刪除等,程式碼如下:
package com.example.android.dao;
import java.util.List;
import org.apache.http.client.methods.HttpUriRequest;
import com.example.android.Cookie;
import com.example.android.CookieDao;
import com.example.android.DaoSession;
import com.example.android.Note;
import com.example.android.NoteDao;
import com.example.android.app.MyApplication;
import com.example.android.utils.CommonUtils;
import com.example.android.utils.LogUtils;
import android.content.Context;
/**
* 測試資料庫操作類,用於操作sqlite
*
* @author Ht
*
*/
public class MyCookieDao {
private static MyCookieDao mInstance;
private DaoSession mDaoSession;
private CookieDao cookieDao;
private MyCookieDao() {
}
public static MyCookieDao getInstance(Context context) {
if (mInstance == null) {
mInstance = new MyCookieDao();
mInstance.mDaoSession = MyApplication.getDaoSession(context);
mInstance.cookieDao = mInstance.mDaoSession.getCookieDao();
}
return mInstance;
}
/**
* 增加或修改某條資料
*
* @param note
*/
public void saveCookie(Cookie cookie) {
cookieDao.insertOrReplace(cookie);
}
/**
* 批量新增資料(開啟執行緒)
*
* @param list
*/
public void saveCookieLists(final List<Cookie> list) {
if (list == null || list.isEmpty()) {
return;
}
cookieDao.getSession().runInTx(new Runnable() {
@Override
public void run() {
for (int i = 0; i < list.size(); i++) {
Cookie cookie = list.get(i);
// 查詢要插入的資料是否已存在
Cookie cacheCookie = queryCookie("where KEY=?",
cookie.getKey());
// 沒有有效期的Cookie無需儲存
if (cookie.getExpires() != null) {
// 已存在的Cookie直接更新
if (cacheCookie != null) {
cookie.setId(cacheCookie.getId());
}
cookieDao.insertOrReplace(cookie);
}
}
}
});
}
/**
* 刪除指定id的資料
*
* @param id
*/
public void deleteCookie(long id) {
cookieDao.deleteByKey(id);
}
/**
* 刪除指定的資料
*
* @param note
*/
public void deleteCookie(Cookie cookie) {
cookieDao.delete(cookie);
}
/**
* 刪除全部資料
*/
public void deleteAllCookie() {
cookieDao.getSession().runInTx(new Runnable() {
@Override
public void run() {
cookieDao.deleteAll();
}
});
}
/**
* 查詢指定資料
*
* @param id
* @return
*/
public Cookie loadCookie(long id) {
return cookieDao.load(id);
}
/**
* 查詢全部資料
*
* @return
*/
public List<Cookie> loadAllCookie() {
return cookieDao.loadAll();
}
/**
* 獲取當前Cookie
*
* @return
*/
public String getCookiesHeader(String url) {
List<Cookie> cookies = loadAllCookie();
StringBuilder cookieStr = new StringBuilder();
for (int i = 0; i < cookies.size(); i++) {
// 驗證Cookie的有效性
if (CommonUtils.checkCookie(url, cookies.get(i))) {
// 驗證通過,拼接Cookie
if (i == cookies.size() - 1) {
cookieStr.append(cookies.get(i).getKey() + "="
+ cookies.get(i).getValue());
} else {
cookieStr.append(cookies.get(i).getKey() + "="
+ cookies.get(i).getValue() + ";");
}
} else {
// 驗證不通過,刪除無效Cookie
deleteCookie(cookies.get(i));
}
}
LogUtils.e("從資料庫中取出了cookie:" + cookieStr.toString());
return cookieStr.toString();
}
/**
* 根據條件查詢多條資料
*
* @param where
* @param params
* @return
*/
public List<Cookie> queryCookies(String where, String... params) {
return cookieDao.queryRaw(where, params);
}
/**
* 根據條件查詢單條資料
*
* @param where
* @param params
* @return
*/
public Cookie queryCookie(String where, String... params) {
List<Cookie> queryRaw = cookieDao.queryRaw(where, params);
if (queryRaw != null && queryRaw.size() > 0)
return queryRaw.get(0);
return null;
}
}
第四步:
由於操作資料庫所消耗的資源相對來說是比較大的,所以將Cookie資料臨時儲存在記憶體當中,獲取資料時,如果記憶體中存在Cookie資料,那麼就直接取出來,如果不存在才會對資料庫進行讀取獲取資料,所以這裡需要用到了自定義的Application
package com.example.android.app;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.methods.HttpUriRequest;
import android.app.Application;
import android.content.Context;
import com.example.android.Cookie;
import com.example.android.DaoMaster;
import com.example.android.DaoMaster.OpenHelper;
import com.example.android.DaoSession;
import com.example.android.dao.MyCookieDao;
import com.example.android.exception.CatchHandler;
import com.example.android.utils.CommonUtils;
import com.example.android.utils.LogUtils;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.utils.StorageUtils;
/**
* 自定義應用入口
*
* @author Ht
*
*/
public class MyApplication extends Application {
private static DaoMaster daoMaster;
private static DaoSession daoSession;
private static Context mInstance;
private static List<Cookie> cookies = new ArrayList<Cookie>();
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
// initCatchHandler();
initImageLoader();
}
/**
* 初始化App異常處理器
*/
private void initCatchHandler() {
CatchHandler catchHandler = CatchHandler.getInstance();
catchHandler.init(getApplicationContext());
catchHandler.setParam(1, "Package", "Application Name", "Server Url",
"Dialog Msg", 0);
}
/**
* 初始化imageloader
*/
private void initImageLoader() {
File cacheDir = StorageUtils.getOwnCacheDirectory(
getApplicationContext(), "imageloader/Cache");
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true) // 載入圖片時會在記憶體中載入快取
.cacheOnDisk(true) // 載入圖片時會在磁碟中載入快取
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
this)
.memoryCacheExtraOptions(480, 800)
// default = device screen dimensions
.diskCacheExtraOptions(480, 800, null)
.threadPoolSize(3)
// default
.threadPriority(Thread.NORM_PRIORITY - 2)
// default
.tasksProcessingOrder(QueueProcessingType.FIFO)
// default
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache(2 * 1024 * 1024))
.memoryCacheSize(2 * 1024 * 1024).memoryCacheSizePercentage(13)
// default
.diskCache(new UnlimitedDiscCache(cacheDir))
// default
.diskCacheSize(50 * 1024 * 1024).diskCacheFileCount(100)
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
.defaultDisplayImageOptions(defaultOptions) // default
.writeDebugLogs().build();
ImageLoader.getInstance().init(config);
}
/**
* 取得DaoMaster
*
* @param context
* @return
*/
public static DaoMaster getDaoMaster(Context context) {
if (daoMaster == null) {
OpenHelper helper = new DaoMaster.DevOpenHelper(context,
Constants.DB_NAME, null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
}
return daoMaster;
}
/**
* 取得DaoSession
*
* @param context
* @return
*/
public static DaoSession getDaoSession(Context context) {
if (daoSession == null) {
if (daoMaster == null) {
daoMaster = getDaoMaster(context);
}
daoSession = daoMaster.newSession();
}
return daoSession;
}
/**
* 設定Cookie
*
* @param cookies
*/
public static void setCookies(List<Cookie> cookies) {
// 如果當前不存在cookie記錄則直接建立
if (MyApplication.cookies == null || MyApplication.cookies.size() == 0) {
MyApplication.cookies.addAll(cookies);
} else {
// 如果已存在則遍歷,替換已有的,新增沒有的
for (Cookie cookie : cookies) {
// 修改標記,true為有修改,false為未修改
boolean flag = false;
if(MyApplication.cookies.contains(cookie)){
for (Cookie c : MyApplication.cookies) {
// 複寫了equals方法,匹配Cookie中key相同的資料
if (cookie.equals(c)) {
// 將已有(key相同)資料替換成新資料
c.setValue(cookie.getValue());
c.setDomain(cookie.getDomain());
c.setExpires(cookie.getExpires());
c.setPath(cookie.getValue());
// 改變修改標記
flag = true;
}
}
}
// 未修改則新增資料
if (!flag) {
MyApplication.cookies.add(cookie);
}
}
}
}
/**
* 獲取當前Cookie
*
* @return
*/
public static String getCookiesHeader(String url) {
List<Cookie> cookies;
MyCookieDao myCookieDao = null;
// 如果當前記憶體中存在cookie資訊則直接取出,否則從資料庫中讀取
if (MyApplication.cookies != null && MyApplication.cookies.size() > 0) {
cookies = MyApplication.cookies;
// 請求路徑
StringBuilder cookieStr = new StringBuilder();
for (int i = 0; i < cookies.size(); i++) {
// 驗證Cookie的有效性
if (CommonUtils.checkCookie(url, cookies.get(i))) {
// 驗證通過,拼接Cookie
if (i == cookies.size() - 1) {
cookieStr.append(cookies.get(i).getKey() + "="
+ cookies.get(i).getValue());
} else {
cookieStr.append(cookies.get(i).getKey() + "="
+ cookies.get(i).getValue() + ";");
}
}
}
LogUtils.e("從記憶體中取出了cookie:" + cookieStr.toString());
return cookieStr.toString();
}
myCookieDao = MyCookieDao.getInstance(MyApplication.getInstance());
return myCookieDao.getCookiesHeader(url);
}
public static Context getInstance() {
return mInstance;
}
}
第五步:
Cookie存在有效期,有效域名等等屬性,所以,我們需要定義一個工具類,用於驗證Cookie的有效性。
/**
* 驗證cookie的有效性
*
* @param url
* @param domain
* @return
*/
public static boolean checkCookie(String url, Cookie cookie) {
String rex = "\\*" + cookie.getDomain() + "\\*";
// 驗證domain的有效性
if (!TextUtils.isEmpty(cookie.getDomain())) {
if (!url.matches(rex)) {
LogUtils.i("domain失效了");
return false;
}
}
// 驗證生命週期的有效性
Date expires = cookie.getExpires();
if (expires == null) {
LogUtils.i(cookie.getKey() + "有效期是空");
return true;
}
LogUtils.i(cookie.getKey() + "有效期:" + expires.after(new Date()));
return expires.after(new Date());
}
第六步:
關於Cookie的儲存和修改已經完成了,那麼接下來就需要在請求的時候帶在請求頭中傳送給伺服器了。修改com.android.volley.Request.java檔案中的getHeaders方法
// 從Application中取出當前的cookie資訊
Map<String, String> cookie = new HashMap<String, String>();
String cookiesHeader = MyApplication.getCookiesHeader(getUrl());
cookie.put("Cookie", cookiesHeader);
return cookie;
到這裡就已經大功告成了,新增完成後Volley會自動儲存Cookie資訊,驗證Cookie的有效期,當超過有效期時會自動刪除過期Cookie。
您有什麼建議,可以通過Email:[email protected]和作者Hunter交流 如果想要關注更多關於Android開發中的一些經驗分享,請訪問http://blog.csdn.net/ht_android
相關推薦
Volley自動獲取以及儲存Cookie
Volley是Google開發的一款android網路框架,非常適合小資料大併發的訪問伺服器,但Volley中沒有提供Cookie方面的管理,幸好它是開源框架,下面就跟大家分享一下具體的修改流程: 提示:Http請求分為request和response,兩者都
python3自動獲取網站的cookie
適合自動獲取ip控制的網站的cookie import requests session = requests.Session() headers = {'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
Java Session的簡單運用 可用於自動登入以及儲存需要的資料等
在WEB開發中,伺服器可以為瀏覽器建立一個會話物件(session物件),通過將一個sessionID 以cookie方式返回給瀏覽器,只要瀏覽器不保持關閉或者沒有超過session的失效
微信小程式獲取cookie以及設定cookie
小程式開發中我們需要獲取到後端給的cookie進行請求驗證,但是微信並沒有幫我們儲存cookie,那麼我們要維持會話需要自己來儲存cookie,並且請求的時候加上cookie 1.獲取cookie 在登入請求後讀取 返回值的, header的cookie,並本地儲存 //登入請求回來
安卓開發 Android Studio生成簽名檔案,自動簽名以及獲取SHA1和MD5值
一、配置IDE生成簽名檔案 1、在studio的選單欄中找到"bulid"這一欄,選擇"Generate Signed APK" ,如下圖所示 2.、新建簽名檔案。 "Create new…"新建一個簽名檔案 "Choose existing…”"擇一個已
springcloud zuul的配置 cookie如何獲取 以及 動態的更新配置
這裡的配置在很多部落格文章都有詳細的介紹如何動態的配置,以及獲取相關的資料,如Http請求頭的資訊,而這裡 介紹如何通過原始碼閱讀來自己學會配置想要的資訊。 譬如,想要獲取到cookie的資訊,我們可以通過檢視原始碼,cookie到底在哪裡體現出來。檢視原始碼可以發現ZuulProperti
實現input移動端自動獲取焦點以及數字鍵盤搜尋功能
最近專案中需要做一個搜尋功能,其中就有自動獲取焦點以及數字鍵盤快捷搜尋,下面就跟大家分享一下我的實現方法:首先跳轉到搜尋頁面input自動獲取焦點,按常規寫法就是加個autofocus或者頁面載入完成後立即給input加個focus()方法,但是這樣進入頁面的時候焦點會自動消
Android Studio生成簽名檔案,自動簽名,以及獲取SHA1和MD5值
前言: 作為谷歌在2013年為開發者提供的IDE環境工具Android Studio,從幾次更新之後Android Studio已經成為了非常強大的IDE開發環境。谷歌也宣佈Android
hibernate級聯儲存 ,同時自動獲取外來鍵值
org.hibernate.exception.ConstraintViolationException: could not execute statementat org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLEx
request post 模擬登入 csdn 獲取儲存cookie
# -*- coding=utf-8 -*- import requests from lxml import etree headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) Apple
Android獲取系統儲存以及記憶體資訊(一)
獲取SD卡上的儲存資訊: /** * 獲得SD卡總大小 * * @return */ private String getSDTotalSize()
基於webkit瀏覽器,自動獲取完整cookie的方法 -- python
在進行自動抓取某些比較x的網站,例如知乎,微博時,需要登入,才能進行某些操作。 例如在抓取知乎首頁,使用requests,肯定是不能獲取獲取登入後的頁面的資訊。而使用selenium 中的firefox 進行操作,獲取登入後的頁面,依舊不能將這個頁面上的資訊抓
13 關於HttpClient自動儲存Cookie
前言 下面是我以前想做的一個專門為了HXBlog “刷訪問” 的工具,, 當時 直接使用的我的HXCrawler進行傳送請求, 但是 很遺憾失敗了,, 也就是 雖然我傳送了”requestTime”個請求, 但是 該部落格的”訪問次數”依然僅僅增加了一次
windows批處理自動改ip和、閘道器、子網、dns以及改為自動獲取
給大家分享兩個批處理指令碼,一個是修改固定ip的,另外一個是改成自動獲取的 自動獲取: @echo off netsh interface ip set address name="本地
Edittext不自動獲取焦點解決方法以及獲取焦點後的事件實現方法
解決之道:在EditText的父級控制元件中找一個,設定成 android:focusable="true"
Form submit 表單自動提交以及自動提交獲取不到數據可能原因分析
bsp 表單 工作目錄 pac 有趣的 默認端口 解決 功能 地址 今天發現一個非常有趣的現象,之前一直在用的表單自動提交功能,居然在一個網站不好用了,如果自動提交的話,就獲取不到數據,只能人工點擊提交,人工點擊的可以獲取到數據。 這裏我們把自動提交代碼發布出來 d
微擎自動獲取地址
conf template onf confirm html 自動 == mes () mobile/commom/footer_new chooseWXPay後面加上openAddress jssdkconfig.jsApiList = [‘checkJsApi‘,‘on
新增客戶端自動獲取微信地址功能、優化商品規格編輯體驗更新!
酷客多 微信小程序最近,微信小程序官方又更新了,又開放十幾項接口,接口的增加意味著擁有小程序的企業主有了更多福利。酷客多作為國內首家微信小程序技術服務商自然要緊跟微信小程序官方的更新步伐,為客戶提供最新最前沿的技術服務,為此我們做了此次更新。此次版本更新主要是小程序端地址添加優化和後端商品規格添加體驗優化。
利用shell腳本自動獲取awr報表
name begin tle 觀察 pre 報表 lec title 實現 觀察Oracle數據庫性能,oracle自帶的awr功能為我們提供了一個近乎完美的解決方案,通過awr特性我們可以隨時從數據庫提取awr報告。通過報告可以了解一個系統的整個運行情況,
python爬蟲--自動獲取seebug的poc
nowait 位數 完成 再次 問題 reading use odi html 簡單的寫了一個爬取www.seebug.org上poc的小玩意兒~ 首先我們進行一定的抓包分析 我們遇到的第一個問題就是seebug需要登錄才能進行下載,這個很好處理,只需要抓取返回值200