不幸的是,Android上有很多cookie管理器。 HttpURLConnection
的Cookie由java.net.CookieManager
维护,WebView
的Cookie由android.webkit.CookieManager
维护。这些cookie存储库是独立的,需要手动同步。
我的应用使用HttpURLConnections
并显示WebViews
(它是原生HTML混合)。当然,我希望两者共享所有的cookie - 所以我将在整个过程中进行透明的会话。
更具体:
简单地说 - 我正在寻找双向同步。或者甚至更好,让它们都使用相同的cookie存储库。您可以假设两者在同一时间处于活动状态(如在不同的选项卡上)。
问题:
有没有办法让两者都使用相同的Cookie存储库?
如果没有,建议的做法是手动同步?我应该何时同步以及如何进行同步?
相关问题:此question解决了类似的问题,但只实现了单向同步(HttpURLConnection - > WebView)。
我最好的想法:我真的想避免手动同步,所以我试着想一下如何使用同一个存储库。也许我可以创建自己的核心处理程序,扩展java.net.CookieManager
。我将使用java.net.CookieHandler.setDefault()
将其设置为核心cookie处理程序。它的实现将是android.webkit.CookieManager
处理程序实例的代理(对于我只是访问webkit管理器的每个函数)。
答案 0 :(得分:62)
我已经实现了自己的想法。它真的很酷。我创建了自己的java.net.CookieManager
实现,它将所有请求转发给WebViews的webkit android.webkit.CookieManager
。这意味着不需要同步,HttpURLConnection使用相同的 cookie存储作为WebViews。
类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();
}
}
在应用程序初始化时使用它:
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);
<强>测试强>
我的初步测试表明这种方法运行良好。我看到在WebViews和HttpURLConnection之间共享cookie。我希望我不会遇到任何问题。如果您尝试这一点并发现任何问题,请发表评论。