HttpURLConnection(java.net.CookieManager)和WebView(android.webkit.CookieManager)之间的cookie的双向同步

tal*_*kol 34 cookies android http httpurlconnection android-webview

不幸的是,Android上有很多cookie管理器.Cookie HttpURLConnection由以下人员维护,java.net.CookieManagerCookie WebView由以下人员维护android.webkit.CookieManager.这些cookie存储库是独立的,需要手动同步.

我的应用程序使用HttpURLConnections和显示WebViews(它是本机HTML混合).当然,我希望两者共享所有cookie - 所以我将在整个过程中进行透明会话.

进一步来说:

  1. 在HttpURLConnection中设置/更改cookie时,我希望WebViews也能看到此更改.
  2. 在WebView中设置/更改cookie时,我希望下一个HttpURLConnections也能看到此更改.

简单地说 - 我正在寻找双向同步.或者甚至更好,让它们都使用相同的cookie存储库.您可以假设它们同时处于活动状态(如在不同的选项卡上).

问题:

  1. 有没有办法让两个使用相同的cookie存储库?

  2. 如果没有,建议的做法是手动同步?什么时候我应该同步,怎么样?

相关问题:这个问题解决了类似的问题,但只实现了单向同步(HttpURLConnection - > WebView).

我最好的想法:我真的想避免手动同步,所以我试着想如何让两者都使用相同的存储库.也许我可以创建自己的扩展核心处理程序java.net.CookieManager.我将使用它将其设置为核心cookie处理程序java.net.CookieHandler.setDefault().它的实现将是android.webkit.CookieManager处理程序实例的代理(对于我只是访问webkit管理器的每个函数).

tal*_*kol 63

我实现了自己的想法.它真的很酷.我创建了自己的实现java.net.CookieManager,将所有请求转发给WebViews的webkit android.webkit.CookieManager.这意味着不需要同步,HttpURLConnection使用 WebView 相同的 cookie存储.

类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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并在应用程序初始化时使用它:

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);
Run Code Online (Sandbox Code Playgroud)

测试

我最初的测试显示这很好用.我看到在WebViews和HttpURLConnection之间共享cookie.我希望我不会遇到任何问题.如果您尝试这一点并发现任何问题,请发表评论.

  • 这个答案是黄金! (4认同)
  • 如果您的目标是API级别21+,则可能需要考虑[Webview-behavior](http://developer.android.com/about/versions/android-5.0-changes.html)中的更改饼干和混合内容.毕竟这个实现依赖于android.webkit.CookieManager. (2认同)