android中okhttp与webview的cookie共享

转载请注明出处:https://blog.csdn.net/u011038298/article/details/84551136

1.在WebView中同步cookie



import android.os.Build;
import android.text.TextUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Cookie;
import okhttp3.HttpUrl;

public class CookieUtil {

    private static CookieUtil instance;
    private PersistentCookieStore mPersistentCookieStore;

    public static CookieUtil getInstance() {
        if (instance == null) {
            instance = new CookieUtil();
        }
        return instance;
    }

    private CookieUtil() {
        mPersistentCookieStore = new PersistentCookieStore(BaseApplication.getInstance());
    }

    /**
     * 注意事项:
     * 1.如果需要传第三方cookie,请调用方法setAcceptThirdPartyCookies
     * 2.如果这里有多个cookie,不要使用分号手动拼接,请多次调用setCookie方法
     * 3.请在调用loadUrl方法前执行
     * 
     * <p>
     *
     * @param webView
     * @param url
     */
    public void syncCookie(WebView webView, String url) {
        try {
            if (!TextUtils.isEmpty(url) && url.startsWith("http")) {
                // 在上下文中创建单个CookieSyncManager
                CookieSyncManager.createInstance(BaseApplication.getInstance());
                // 获取单例CookieManager实例
                CookieManager cookieManager = CookieManager.getInstance();
                // 设置应用程序的WebView实例是否应发送和接受cookie
                cookieManager.setAcceptCookie(true);
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    // 删除所有会话cookie
                    cookieManager.removeSessionCookie();
                    // 此方法在API级别21中已弃用.WebView会自动处理删除过期的Cookie。
                    cookieManager.removeExpiredCookie();
                    // 删除所有cookie
                    // cookieManager.removeAllCookie();
                } else {
                    if (webView != null) {
                        // 设置是否WebView应允许设置第三方cookie
                        cookieManager.setAcceptThirdPartyCookies(webView, true);
                    }
                    // 删除所有会话cookie
                    cookieManager.removeSessionCookies(null);
                    // 删除所有cookie
                    // cookieManager.removeAllCookies(null);
                }
                List<Cookie> cookies = mPersistentCookieStore.get(HttpUrl.parse(url));
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    // 设置原生cookie
                    if (cookies != null && cookies.size() > 0) {
                        for (int i = 0; i < cookies.size(); i++) {
                            Cookie cookie = cookies.get(i);
                            cookieManager.setCookie(url, cookie.name() + "=" + cookie.value());
                        }
                    }
                    // 设置第三方cookie
                    cookieManager.setCookie(url, String.format("这里填写cookie的名称=%s", "这里填写cookie的值"));
                    // 确保当前可通过getCookie API访问的所有cookie都写入持久存储
                    CookieSyncManager.getInstance().sync();
                } else {
                    // 设置原生cookie
                    if (cookies != null && cookies.size() > 0) {
                        for (int i = 0; i < cookies.size(); i++) {
                            Cookie cookie = cookies.get(i);
                            cookieManager.setCookie(url, cookie.name() + "=" + cookie.value(), null);
                        }
                    }
                    // 设置第三方cookie
                    cookieManager.setCookie(url, String.format("这里填写cookie的名称=%s", "这里填写cookie的值"),null);
                    // 确保当前可通过getCookie API访问的所有cookie都写入持久存储
                    cookieManager.flush();
                }
            }
        } catch (Exception e) {
        }
    }

    /**
     * 添加cookie
     * 在WebViewClient的onPageFinished函数中调用
     *
     * @param url
     */
    public void addCookie(String url) {
        try {
            if (!TextUtils.isEmpty(url) && url.startsWith("http")) {
                String cookies = CookieManager.getInstance().getCookie(url);
                if (!TextUtils.isEmpty(cookies)) {
                    HttpUrl httpUrl = HttpUrl.parse(url);
                    List<Cookie> list = new ArrayList<>();
                    list.add(Cookie.parse(httpUrl, cookies));
                    mPersistentCookieStore.add(httpUrl, list);
                }
            }
        } catch (Exception ex) {
        }
    }

    /**
     * 删除所有cookies
     */
    public void removeAllCookies() {
        try {
            // 在上下文中创建单个CookieSyncManager
            CookieSyncManager.createInstance(BaseApplication.getInstance());
            // 获取单例CookieManager实例
            CookieManager cookieManager = CookieManager.getInstance();
            // 设置应用程序的WebView实例是否应发送和接受cookie
            cookieManager.setAcceptCookie(true);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                // 删除所有会话cookie
                cookieManager.removeSessionCookie();
                // 此方法在API级别21中已弃用.WebView会自动处理删除过期的Cookie。
                cookieManager.removeExpiredCookie();
                // 删除所有cookie
                cookieManager.removeAllCookie();
                // 确保当前可通过getCookie API访问的所有cookie都写入持久存储
                CookieSyncManager.getInstance().sync();
            } else {
                // 删除所有会话cookie
                cookieManager.removeSessionCookies(null);
                // 删除所有cookie
                cookieManager.removeAllCookies(null);
                // 确保当前可通过getCookie API访问的所有cookie都写入持久存储
                cookieManager.flush();
            }
            mPersistentCookieStore.removeAll();
        } catch (Exception ex) {
        }
    }

}

2.PersistentCookieStore 类

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Cookie;
import okhttp3.HttpUrl;

public class PersistentCookieStore implements CookieStore {

    private static final String COOKIE_NAME_PREFIX = "cookie_";
    private static final String COOKIE_PREFS = "CookiePrefsProjectName";

    private final SharedPreferences cookiePrefs;
    private final HashMap<String, ConcurrentHashMap<String, Cookie>> cookies;

    /**
     * Construct a persistent cookie store.
     *
     * @param context Context to attach cookie store to
     */
    public PersistentCookieStore(Context context) {
        cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);
        cookies = new HashMap<String, ConcurrentHashMap<String, Cookie>>();

        // Load any previously stored cookies into the store
        Map<String, ?> prefsMap = cookiePrefs.getAll();
        for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
            if ((entry.getValue()) != null && !((String) entry.getValue()).startsWith(COOKIE_NAME_PREFIX)) {
                String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
                for (String name : cookieNames) {
                    String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null);
                    if (encodedCookie != null) {
                        Cookie decodedCookie = decodeCookie(encodedCookie);
                        if (decodedCookie != null) {
                            if (!cookies.containsKey(entry.getKey()))
                                cookies.put(entry.getKey(), new ConcurrentHashMap<String, Cookie>());
                            cookies.get(entry.getKey()).put(name, decodedCookie);
                        }
                    }
                }

            }
        }
    }

    private static boolean isCookieExpired(Cookie cookie) {
        return cookie.expiresAt() < System.currentTimeMillis();
    }

    protected void add(HttpUrl uri, Cookie cookie) {
        String name = getCookieToken(cookie);
        boolean hasExpired = cookie.persistent() ? isCookieExpired(cookie) : false;
        if (!hasExpired) {
            if (!cookies.containsKey(uri.host())) {
                cookies.put(uri.host(), new ConcurrentHashMap<String, Cookie>());
            }
            cookies.get(uri.host()).put(name, cookie);
        } else {
            if (cookies.containsKey(uri.host())) {
                cookies.get(uri.host()).remove(name);
            } else {
                return;
            }
        }

        // Save cookie into persistent store
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        prefsWriter.putString(uri.host(), TextUtils.join(",", cookies.get(uri.host()).keySet()));
        prefsWriter.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableHttpCookie(cookie)));
        prefsWriter.apply();
    }

    protected String getCookieToken(Cookie cookie) {
        return cookie.name() + cookie.domain();
    }

    @Override
    public void add(HttpUrl uri, List<Cookie> cookies) {
        for (Cookie cookie : cookies) {
            add(uri, cookie);
        }
    }

    @Override
    public List<Cookie> get(HttpUrl uri) {
        ArrayList<Cookie> ret = new ArrayList<Cookie>();
        for (Map.Entry<String, ConcurrentHashMap<String, Cookie>> entry : cookies.entrySet()) {
            Collection<Cookie> cookies = this.cookies.get(entry.getKey()).values();
            for (Cookie cookie : cookies) {
                if (cookie.matches(uri)) {
                    if (isCookieExpired(cookie)) {
                        remove(uri, cookie);
                    } else {
                        ret.add(cookie);
                    }
                }
            }
        }
        return ret;
    }

    @Override
    public boolean removeAll() {
        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
        prefsWriter.clear();
        prefsWriter.apply();
        cookies.clear();
        return true;
    }


    @Override
    public boolean remove(HttpUrl uri, Cookie cookie) {
        String name = getCookieToken(cookie);

        if (cookies.containsKey(uri.host()) && cookies.get(uri.host()).containsKey(name)) {
            cookies.get(uri.host()).remove(name);

            SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
            if (cookiePrefs.contains(COOKIE_NAME_PREFIX + name)) {
                prefsWriter.remove(COOKIE_NAME_PREFIX + name);
            }
            prefsWriter.putString(uri.host(), TextUtils.join(",", cookies.get(uri.host()).keySet()));
            prefsWriter.apply();

            return true;
        } else {
            return false;
        }
    }

    protected String encodeCookie(SerializableHttpCookie cookie) {
        if (cookie == null)
            return null;
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ObjectOutputStream outputStream = new ObjectOutputStream(os);
            outputStream.writeObject(cookie);
        } catch (IOException e) {
            return null;
        }
        return byteArrayToHexString(os.toByteArray());
    }

    protected Cookie decodeCookie(String cookieString) {
        byte[] bytes = hexStringToByteArray(cookieString);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Cookie cookie = null;
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            cookie = ((SerializableHttpCookie) objectInputStream.readObject()).getCookie();
        } catch (IOException e) {
        } catch (ClassNotFoundException e) {
        }
        return cookie;
    }

    /**
     * Using some super basic byte array &lt;-&gt; hex conversions so we don't have to rely on any
     * large Base64 libraries. Can be overridden if you like!
     *
     * @param bytes byte array to be converted
     * @return string containing hex values
     */
    protected 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);
    }

    /**
     * Converts hex values from strings to byte arra
     *
     * @param hexString string of hex-encoded values
     * @return decoded byte array
     */
    protected 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;
    }

}

3.SerializableHttpCookie类 

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import okhttp3.Cookie;

public class SerializableHttpCookie implements Serializable {

    private transient final Cookie cookie;
    private transient Cookie clientCookie;

    public SerializableHttpCookie(Cookie cookie) {
        this.cookie = cookie;
    }

    public Cookie getCookie() {
        Cookie bestCookie = cookie;
        if (clientCookie != null) {
            bestCookie = clientCookie;
        }
        return bestCookie;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        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 {
        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();
    }

}

4.okHttp中cookie的实现

OkHttpClient.Builder builder = new OkHttpClient.Builder();
CookieJarImpl cookieJarImpl = new CookieJarImpl(new PersistentCookieStore(context));
builder.cookieJar(cookieJarImpl);
OkHttpClient okHttpClient = builder.build();

5. CookieJarImpl的实现

import java.util.List;

import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;

public class CookieJarImpl implements CookieJar {

    private CookieStore cookieStore;

    public CookieJarImpl(CookieStore cookieStore) {
        if (cookieStore == null) new IllegalArgumentException("cookieStore can not be null.");
        this.cookieStore = cookieStore;
    }

    /**
     * 服务端给客户端发送Cookie时调用
     *
     * @param url
     * @param cookies
     */
    @Override
    public synchronized void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        cookieStore.add(url, cookies);
    }

    /**
     * 当访问到某个域名时,会通过此方法获取保存的Cookie,并且发送给服务器
     *
     * @param url
     * @return
     */
    @Override
    public synchronized List<Cookie> loadForRequest(HttpUrl url) {
        return cookieStore.get(url);
    }

}

 6.CookieStore接口

import java.util.List;

import okhttp3.Cookie;
import okhttp3.HttpUrl;

public interface CookieStore {

    void add(HttpUrl uri, List<Cookie> cookie);

    List<Cookie> get(HttpUrl uri);

    boolean remove(HttpUrl uri, Cookie cookie);

    boolean removeAll();

}

okHttp依赖配置(app/build.gradle)

implementation 'com.squareup.okio:okio:1.14.0'
implementation 'com.squareup.okhttp3:okhttp:3.11.0'

猜你喜欢

转载自blog.csdn.net/u011038298/article/details/84551136
今日推荐