Two way sync for cookies between HttpURLConnection (java.net.CookieManager) and WebView (android.webkit.CookieManager)

后端 未结 1 433
挽巷
挽巷 2020-12-04 11:01

Unfortunately, there\'s a multitude of cookie managers for Android. The cookies for HttpURLConnection are maintained by java.net.CookieManager and

相关标签:
1条回答
  • 2020-12-04 11:26

    I've implemented my own idea. It's actually pretty cool. I've created my own implementation of java.net.CookieManager which forwards all requests to the WebViews' webkit android.webkit.CookieManager. This means no sync is required and HttpURLConnection uses the same cookie storage as the WebViews.

    Class WebkitCookieManagerProxy:

    import java.io.IOException;
    import java.net.CookieManager;
    import java.net.CookiePolicy;
    import java.net.CookieStore;
    import java.net.URI;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    public class WebkitCookieManagerProxy extends CookieManager 
    {
        private android.webkit.CookieManager webkitCookieManager;
    
        public WebkitCookieManagerProxy()
        {
            this(null, null);
        }
    
        public WebkitCookieManagerProxy(CookieStore store, CookiePolicy cookiePolicy)
        {
            super(null, cookiePolicy);
    
            this.webkitCookieManager = android.webkit.CookieManager.getInstance();
        }
    
        @Override
        public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException 
        {
            // make sure our args are valid
            if ((uri == null) || (responseHeaders == null)) return;
    
            // save our url once
            String url = uri.toString();
    
            // go over the headers
            for (String headerKey : responseHeaders.keySet()) 
            {
                // ignore headers which aren't cookie related
                if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;
    
                // process each of the headers
                for (String headerValue : responseHeaders.get(headerKey))
                {
                    this.webkitCookieManager.setCookie(url, headerValue);
                }
            }
        }
    
        @Override
        public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException 
        {
            // make sure our args are valid
            if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");
    
            // save our url once
            String url = uri.toString();
    
            // prepare our response
            Map<String, List<String>> res = new java.util.HashMap<String, List<String>>();
    
            // get the cookie
            String cookie = this.webkitCookieManager.getCookie(url);
    
            // return it
            if (cookie != null) res.put("Cookie", Arrays.asList(cookie));
            return res;
        }
    
        @Override
        public CookieStore getCookieStore() 
        {
            // we don't want anyone to work with this cookie store directly
            throw new UnsupportedOperationException();
        }
    }
    

    And use it by doing this on your application initialization:

    android.webkit.CookieSyncManager.createInstance(appContext);
    // unrelated, just make sure cookies are generally allowed
    android.webkit.CookieManager.getInstance().setAcceptCookie(true);
    
    // magic starts here
    WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL);
    java.net.CookieHandler.setDefault(coreCookieManager);
    

    Testing

    My initial testing show this is working well. I see cookies shared between the WebViews and HttpURLConnection. I hope I'll not run into any issues. If you try this out and discover any problem, please comment.

    0 讨论(0)
提交回复
热议问题