使用HTTPUrlConnection时如何保持cookie?

我已经开始使用推荐的HTTPUrlConnection并从DefaultHTTPClient移开。 我一直无法粘贴在一起的事情之一是使用持久性cookie存储。 我想简单地附加一个自定义的cookie处理程序/pipe理器到我的连接来存储cookie。 Android文档并没有太大的帮助,因为它包含了两行cookies的主题。

我以前一直在使用LoopJ的PersistentCookieStore ,而且工作得很好。

任何想法,我怎么可以在Android中build立一个持久的cookie存储,我可以附加到我的HTTPUrlConnection自动保存和检索cookie?

谢谢

Solutions Collecting From Web of "使用HTTPUrlConnection时如何保持cookie?"

它“花了我几个小时,但我设法build立一个自定义cookie存储自己。

你必须这样做:

 public class application extends Application { @Override public void onCreate() { super.onCreate(); CookieManager cmrCookieMan = new CookieManager(new MyCookieStore(this.objContext), CookiePolicy.ACCEPT_ALL); CookieHandler.setDefault(cmrCookieMan); } } 

这是实际的存储:

 /* * This is a custom cookie storage for the application. This * will store all the cookies to the shared preferences so that it persists * across application restarts. */ class MyCookieStore implements CookieStore { /* * The memory storage of the cookies */ private Map<URI, List<HttpCookie>> mapCookies = new HashMap<URI, List<HttpCookie>>(); /* * The instance of the shared preferences */ private final SharedPreferences spePreferences; /* * @see java.net.CookieStore#add(java.net.URI, java.net.HttpCookie) */ public void add(URI uri, HttpCookie cookie) { System.out.println("add"); System.out.println(cookie.toString()); List<HttpCookie> cookies = mapCookies.get(uri); if (cookies == null) { cookies = new ArrayList<HttpCookie>(); mapCookies.put(uri, cookies); } cookies.add(cookie); Editor ediWriter = spePreferences.edit(); HashSet<String> setCookies = new HashSet<String>(); setCookies.add(cookie.toString()); ediWriter.putStringSet(uri.toString(), spePreferences.getStringSet(uri.toString(), setCookies)); ediWriter.commit(); } /* * Constructor * * @param ctxContext the context of the Activity */ @SuppressWarnings("unchecked") public MyCookieStore(Context ctxContext) { spePreferences = ctxContext.getSharedPreferences("CookiePrefsFile", 0); Map<String, ?> prefsMap = spePreferences.getAll(); for(Map.Entry<String, ?> entry : prefsMap.entrySet()) { for (String strCookie : (HashSet<String>) entry.getValue()) { if (!mapCookies.containsKey(entry.getKey())) { List<HttpCookie> lstCookies = new ArrayList<HttpCookie>(); lstCookies.addAll(HttpCookie.parse(strCookie)); try { mapCookies.put(new URI(entry.getKey()), lstCookies); } catch (URISyntaxException e) { e.printStackTrace(); } } else { List<HttpCookie> lstCookies = mapCookies.get(entry.getKey()); lstCookies.addAll(HttpCookie.parse(strCookie)); try { mapCookies.put(new URI(entry.getKey()), lstCookies); } catch (URISyntaxException e) { e.printStackTrace(); } } System.out.println(entry.getKey() + ": " + strCookie); } } } /* * @see java.net.CookieStore#get(java.net.URI) */ public List<HttpCookie> get(URI uri) { List<HttpCookie> lstCookies = mapCookies.get(uri); if (lstCookies == null) mapCookies.put(uri, new ArrayList<HttpCookie>()); return mapCookies.get(uri); } /* * @see java.net.CookieStore#removeAll() */ public boolean removeAll() { mapCookies.clear(); return true; } /* * @see java.net.CookieStore#getCookies() */ public List<HttpCookie> getCookies() { Collection<List<HttpCookie>> values = mapCookies.values(); List<HttpCookie> result = new ArrayList<HttpCookie>(); for (List<HttpCookie> value : values) { result.addAll(value); } return result; } /* * @see java.net.CookieStore#getURIs() */ public List<URI> getURIs() { Set<URI> keys = mapCookies.keySet(); return new ArrayList<URI>(keys); } /* * @see java.net.CookieStore#remove(java.net.URI, java.net.HttpCookie) */ public boolean remove(URI uri, HttpCookie cookie) { List<HttpCookie> lstCookies = mapCookies.get(uri); if (lstCookies == null) return false; return lstCookies.remove(cookie); } } 

在许多定制的CookieStore实现中有一些基本的问题。

第一个问题是HttpCookie序列化成string – HttpCookie.toString()方法是不可接受的,因为它的结果不适合HttpCookie.parse(String header)方法。

第二个问题:CookieStore的大部分实现(例如https://codereview.stackexchange.com/questions/61494/persistent-cookie-support-using-volley-and-httpurlconnection )并没有考虑到HttpCookie的格式。 maxAge字段。 这是几秒钟的cookie生活。 但是,如果你坚持自己的价值,经过一段时间的不经意,那将是错误的。 您必须将maxAge字段转换为类似“expire_at”的字符,并将其保留,而不是maxAge。

我使用了上面的答案,但将add方法更改为以下内容以处理来自同一个URI的多个cookie(此GAE的cookie存储将会话标记和记忆标记作为来自同一URI的两个单独的Cookie出于某种原因) :

 public void add(URI uri, HttpCookie cookie) { List<HttpCookie> cookies = mapCookies.get(uri); if (cookies == null) { cookies = new ArrayList<HttpCookie>(); mapCookies.put(uri, cookies); } cookies.add(cookie); Editor ediWriter = spePreferences.edit(); HashSet<String> setCookies = new HashSet<String>(); setCookies.add(cookie.toString()); HashSet<String> emptyCookieSet = new HashSet<String>(); if(spePreferences.contains(uri.toString())){ emptyCookieSet = (HashSet<String>) spePreferences.getStringSet(uri.toString(), emptyCookieSet); if(!emptyCookieSet.isEmpty()){ if(!emptyCookieSet.contains(cookie.toString())){ emptyCookieSet.add(cookie.toString()); ediWriter.putStringSet(uri.toString(), emptyCookieSet); } } } else{ ediWriter.putStringSet(uri.toString(), setCookies); } ediWriter.commit(); } 

并访问并创build一个组合的cookie:

 MyCookieStore store = new MyCookieStore(this.context, false); String cookie = TextUtils.join(",", store.get(new URI(URLString))); 

连接到连接:

 URL urlToRequest = new URL(stringPath); HttpURLConnection urlConnection = (HttpURLConnection) urlToRequest.openConnection(); urlConnection.setRequestProperty("Cookie", cookie); 

在下面的链接中检查实现。 它像原始的java.net.InMemoryCookieStore实现那样通过主机名保存cookie。

除此之外,它还包含一个SerializableHttpCookie,可以将完整的HashMap序列化到SharedPreferences中。

https://gist.github.com/jacobtabak/78e226673d5a6a4c4367