美文网首页
OkHttp3 cookie 本地SharedPrefrence

OkHttp3 cookie 本地SharedPrefrence

作者: SheepYan9 | 来源:发表于2018-03-29 15:16 被阅读21次
    interface ICookieStore {
    
        /**保存对应url 的cookie*/
        fun saveCookie(url: HttpUrl?, cookies: MutableList<Cookie>?)
    
        /**获取对应url的所有cookie*/
        fun loadCookie(httpUrl: HttpUrl): List<Cookie>
    
        /**加载所有cookie*/
        fun loadAllCookie(): List<Cookie>
    
        /**移除多有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.host   value :,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<Cookie>): 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<Cookie> {
            return if (cookieString.isEmpty()) {
                mutableListOf()
            } else {
                val cookies = arrayListOf<Cookie>()
                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<Cookie>, cookies: MutableList<Cookie>?): MutableList<Cookie> {
            if (cookies == null || cookies.size == 0) {
                return originCookies
            } else {
                val cookieMap = ConcurrentHashMap<String, Cookie>()
                originCookies.forEach {
                    cookieMap.put("${it.name()}@${it.domain()}", it)
                }
                cookies.forEach {
                    cookieMap.put("${it.name()}@${it.domain()}", it)
                }
                val currentCookie = mutableListOf<Cookie>()
                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<String, MutableList<Cookie>> = 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<Cookie>?) {
            if (cookies != null && url != null) {
                //先存到内存在缓存
                val newCookie = CookieMgr.addToCookies(cookiesMap[url.host()] ?: arrayListOf(), cookies)
                cookiesMap[url.host()] = newCookie
    
                val prefsWriter = cookieSp.edit()
                prefsWriter.putString(url.host(), CookieMgr.mapCookiesToString(url, newCookie))
                prefsWriter.apply()
            }
        }
    
        override fun loadCookie(httpUrl: HttpUrl): List<Cookie> {
            if (cookiesMap.containsKey(httpUrl.host())) {
                return cookiesMap[httpUrl.host()] ?: emptyList()
            }
            return emptyList()
        }
    
        override fun loadAllCookie(): List<Cookie> {
            val cookies = arrayListOf<Cookie>()
            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<Cookie>?) {
            cookieStore.saveCookie(url, cookies)
        }
    
        override fun loadForRequest(url: HttpUrl?): List<Cookie> {
            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 = (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 = 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()
    

    相关文章

      网友评论

          本文标题:OkHttp3 cookie 本地SharedPrefrence

          本文链接:https://www.haomeiwen.com/subject/zgimcftx.html