OkHttp3 cookie 本地SharedPrefrence管理

interface ICookieStore {/**保存对应url 的cookie*/ fun saveCookie(url: HttpUrl?, cookies: MutableList?)/**获取对应url的所有cookie*/ fun loadCookie(httpUrl: HttpUrl): List/**加载所有cookie*/ fun loadAllCookie(): List/**移除多有cookie*/ fun removeAllCookie(): Boolean/**移除对应url的cookie*/ fun removeCookie(httpUrl: HttpUrl): Boolean }

/** * Created by HeXiangyuan on 18-3-21. * Description:这个cookie进行本地化保存 保存在SP opt_cookie_sp中 * * sp中储存方式 是 key :url.hostvalue :,opr_cookie_cookie1,opt_cookie_cookie2,opt_cookie_cookie3 */ object CookieMgr { const val COOKIE_SP = "OPT_COOKIE_SP" private const val COOKIE_PREFIX = ",opt_cookie_"fun mapCookiesToString(httpUrl: HttpUrl, cookies: List): String { return if (cookies.isEmpty()) { "" } else { val sb = StringBuilder() cookies.forEach { sb.append(CookieMgr.COOKIE_PREFIX) sb.append(SerializableCookie.encodeCookie(httpUrl.host(), it)) } sb.toString() } }fun mapStringToCookies(cookieString: String): MutableList { return if (cookieString.isEmpty()) { mutableListOf() } else { val cookies = arrayListOf() cookieString .split(CookieMgr.COOKIE_PREFIX) .forEach { if (!it.isEmpty()) { val cookie = SerializableCookie.decodeCookie(it) Log.e("cookieLog", "name == ${cookie.name()}domain == ${cookie.domain()}cookieString == $cookie ") cookies.add(cookie) } } return cookies } }/**以Cookie的name 和domain 作为判断依据, * 如果是 一致的则通过map 的key 唯一性进行替换 * 也就是说如果两个cookie 对比name 和domain * */ fun addToCookies(originCookies: MutableList, cookies: MutableList?): MutableList { if (cookies == null || cookies.size == 0) { return originCookies } else { val cookieMap = ConcurrentHashMap() originCookies.forEach { cookieMap.put("${it.name()}@${it.domain()}", it) } cookies.forEach { cookieMap.put("${it.name()}@${it.domain()}", it) } val currentCookie = mutableListOf() cookieMap.forEach { currentCookie.add(it.value) } return currentCookie } } }class LocalCookieStore(val context: Application) : ICookieStore { private val cookieSp: SharedPreferences = context.getSharedPreferences(CookieMgr.COOKIE_SP, MODE_PRIVATE) private val cookiesMap: ConcurrentHashMap> = ConcurrentHashMap()init { //初始化之前先将Cookie全部从Sp中读取到内存中 cookieSp.all.forEach { if (it.value != null) { cookiesMap[it.key] = CookieMgr.mapStringToCookies(it.value.toString()) } } }@Synchronized override fun saveCookie(url: HttpUrl?, cookies: MutableList?) { if (cookies != null && url != null) { //先存到内存在缓存 val newCookie = CookieMgr.addToCookies(cookiesMap[url.host()] ?: arrayListOf(), cookies) cookiesMap[url.host()] = newCookieval prefsWriter = cookieSp.edit() prefsWriter.putString(url.host(), CookieMgr.mapCookiesToString(url, newCookie)) prefsWriter.apply() } }override fun loadCookie(httpUrl: HttpUrl): List { if (cookiesMap.containsKey(httpUrl.host())) { return cookiesMap[httpUrl.host()] ?: emptyList() } return emptyList() }override fun loadAllCookie(): List { val cookies = arrayListOf() cookiesMap.forEach { it.value.forEach { cookie -> cookies.add(cookie) } } return cookies }override fun removeAllCookie(): Boolean { cookiesMap.clear() cookieSp.edit().clear().apply() return true }override fun removeCookie(httpUrl: HttpUrl): Boolean { cookiesMap.remove(httpUrl.host()) cookieSp.edit().remove(httpUrl.host()).apply() return true }}

class MyCookieJarImp( val cookieStore: ICookieStore) : CookieJar {override fun saveFromResponse(url: HttpUrl?, cookies: MutableList?) { cookieStore.saveCookie(url, cookies) }override fun loadForRequest(url: HttpUrl?): List { return if (url != null) { cookieStore.loadCookie(url) } else { emptyList() } }}

public class SerializableCookie implements Serializable { private static final long serialVersionUID = 6374381323722046732L; public static final String HOST = "host"; public static final String NAME = "name"; public static final String DOMAIN = "domain"; public static final String COOKIE = "cookie"; public String host; public String name; public String domain; private transient Cookie cookie; private transient Cookie clientCookie; public SerializableCookie(String host, Cookie cookie) { this.cookie = cookie; this.host = host; this.name = cookie.name(); this.domain = cookie.domain(); }public Cookie getCookie() { Cookie bestCookie = cookie; if (clientCookie != null) { bestCookie = clientCookie; } return bestCookie; }private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(cookie.name()); out.writeObject(cookie.value()); out.writeLong(cookie.expiresAt()); out.writeObject(cookie.domain()); out.writeObject(cookie.path()); out.writeBoolean(cookie.secure()); out.writeBoolean(cookie.httpOnly()); out.writeBoolean(cookie.hostOnly()); out.writeBoolean(cookie.persistent()); }private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); String name = (String) in.readObject(); String value = https://www.it610.com/article/(String) in.readObject(); long expiresAt = in.readLong(); String domain = (String) in.readObject(); String path = (String) in.readObject(); boolean secure = in.readBoolean(); boolean httpOnly = in.readBoolean(); boolean hostOnly = in.readBoolean(); boolean persistent = in.readBoolean(); Cookie.Builder builder = new Cookie.Builder(); builder = builder.name(name); builder = builder.value(value); builder = builder.expiresAt(expiresAt); builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain); builder = builder.path(path); builder = secure ? builder.secure() : builder; builder = httpOnly ? builder.httpOnly() : builder; clientCookie = builder.build(); }public static SerializableCookie parseCursorToBean(Cursor cursor) { String host = cursor.getString(cursor.getColumnIndex(HOST)); byte[] cookieBytes = cursor.getBlob(cursor.getColumnIndex(COOKIE)); Cookie cookie = bytesToCookie(cookieBytes); return new SerializableCookie(host, cookie); }public static ContentValues getContentValues(SerializableCookie serializableCookie) { ContentValues values = new ContentValues(); values.put(SerializableCookie.HOST, serializableCookie.host); values.put(SerializableCookie.NAME, serializableCookie.name); values.put(SerializableCookie.DOMAIN, serializableCookie.domain); values.put(SerializableCookie.COOKIE, cookieToBytes(serializableCookie.host, serializableCookie.getCookie())); return values; }/** * cookies 序列化成 string * * @param cookie 要序列化 * @return 序列化之后的string */ public static String encodeCookie(String host, Cookie cookie) { if (cookie == null) return null; byte[] cookieBytes = cookieToBytes(host, cookie); return byteArrayToHexString(cookieBytes); }public static byte[] cookieToBytes(String host, Cookie cookie) { SerializableCookie serializableCookie = new SerializableCookie(host, cookie); ByteArrayOutputStream os = new ByteArrayOutputStream(); try { ObjectOutputStream outputStream = new ObjectOutputStream(os); outputStream.writeObject(serializableCookie); } catch (IOException e) {return null; } return os.toByteArray(); }/** * 将字符串反序列化成cookies * * @param cookieString cookies string * @return cookie object */ public static Cookie decodeCookie(String cookieString) { byte[] bytes = hexStringToByteArray(cookieString); return bytesToCookie(bytes); }public static Cookie bytesToCookie(byte[] bytes) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); Cookie cookie = null; try { ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); cookie = ((SerializableCookie) objectInputStream.readObject()).getCookie(); } catch (Exception e) {} return cookie; }/** * 二进制数组转十六进制字符串 * * @param bytes byte array to be converted * @return string containing hex values */ private static String byteArrayToHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte element : bytes) { int v = element & 0xff; if (v < 16) { sb.append('0'); } sb.append(Integer.toHexString(v)); } return sb.toString().toUpperCase(Locale.US); }/** * 十六进制字符串转二进制数组 * * @param hexString string of hex-encoded values * @return decoded byte array */ private static byte[] hexStringToByteArray(String hexString) { int len = hexString.length(); byte[] data = https://www.it610.com/article/new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16)); } return data; }/** host, name, domain 标识一个cookie是否唯一 */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SerializableCookie that = (SerializableCookie) o; if (host != null ? !host.equals(that.host) : that.host != null) return false; if (name != null ? !name.equals(that.name) : that.name != null) return false; return domain != null ? domain.equals(that.domain) : that.domain == null; }@Override public int hashCode() { int result = host != null ? host.hashCode() : 0; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (domain != null ? domain.hashCode() : 0); return result; } }

OkHttpClient.Builder() ... .cookieJar(MyCookieJarImp(LocalCookieStore(context))) .build()

    推荐阅读