Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager)

后端 未结 4 1970
粉色の甜心
粉色の甜心 2020-11-28 20:04

I\'ve seen answers about how this should work with the old DefaultHttpClient but there\'s not a good example for HttpURLConnection

相关标签:
4条回答
  • 2020-11-28 20:26

    I had the same problem, and this is my solution :

    Just after login (it's important because before, you may be don't have cookie yet) using httpurlconnection POST (after getResponseCode), I do :

     responseCode = connexion.getResponseCode();
     if (responseCode == HttpURLConnection.HTTP_OK) {
         final String COOKIES_HEADER = "Set-Cookie";
         cookie = connexion.getHeaderField(COOKIES_HEADER);
         ...
     }
    

    (where cookie is a public String in my class)

    And in the webview activity, where I want to display a web page from server using WebView, I do :

        String url = "http://toto.com/titi.html";        // the url of the page you want to display
        CookieSyncManager.createInstance(getActivity());
        CookieSyncManager.getInstance().startSync();
        android.webkit.CookieManager cookieManager = android.webkit.CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeSessionCookie();
        cookieManager.setCookie(url, cookie);
        CookieSyncManager.getInstance().sync();
    

    As my webview is in a fragment, I had to use getActivity() for the Context, I also had to specify android.webkit. before CookieManager otherwise it cannot be resolved (import java.net instead of android.webkit cookie manager).

    cookie is the same String as above (in my Fragment, I had to recover it using :

        cookie = getArguments().getString(COOKIE);
    

    and in my MainActivity, I send it by :

        Bundle arg = new Bundle();
        arg.putString(Fragment_Cameras.COOKIE, cookie);
        fragment.setArguments(arg);
    

    I hop this can help !

    0 讨论(0)
  • 2020-11-28 20:43

    I would like to suggest a completely different approach to your problem. Instead of copying cookies from one place to another (manual sync), let's make HttpURLConnection and WebViews use the same cookie storage.

    This completely eliminates the need for sync. Any cookie updated in any one of them, will be immediately and automatically reflected in the other.

    To do this, create your own implementation of java.net.CookieManager which forwards all requests to the WebViews' webkit android.webkit.CookieManager.

    Implementation:

    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);
        }
    
        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 finally 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);
    
    0 讨论(0)
  • 2020-11-28 20:43

    I magically solved all my cookie problems with this one line in onCreate:

    CookieHandler.setDefault(new CookieManager());

    0 讨论(0)
  • 2020-11-28 20:45

    As compared with DefaultHttpClient, there are a few extra steps. The key difference is how to access the existing cookies in HTTPURLConnection:

    1. Call CookieHandler.getDefault() and cast the result to java.net.CookieManager.
    2. With the cookie manager, call getCookieStore() to access the cookie store.
    3. With the cookie store, call get() to access the list of cookies for the given URI.

    Here's a complete example:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Get cookie manager for WebView
        // This must occur before setContentView() instantiates your WebView
        android.webkit.CookieSyncManager webCookieSync =
            CookieSyncManager.createInstance(this);
        android.webkit.CookieManager webCookieManager =
            CookieManager.getInstance();
        webCookieManager.setAcceptCookie(true);
    
        // Get cookie manager for HttpURLConnection
        java.net.CookieStore rawCookieStore = ((java.net.CookieManager)
            CookieHandler.getDefault()).getCookieStore();
    
        // Construct URI
        java.net.URI baseUri = null;
        try {
            baseUri = new URI("http://www.example.com");
        } catch (URISyntaxException e) {
            // Handle invalid URI
            ...
        }
    
        // Copy cookies from HttpURLConnection to WebView
        List<HttpCookie> cookies = rawCookieStore.get(baseUri);
        String url = baseUri.toString();
        for (HttpCookie cookie : cookies) {
            String setCookie = new StringBuilder(cookie.toString())
                .append("; domain=").append(cookie.getDomain())
                .append("; path=").append(cookie.getPath())
                .toString();
            webCookieManager.setCookie(url, setCookie);
        }
    
        // Continue with onCreate
        ...
    }
    
    0 讨论(0)
提交回复
热议问题