2012-09-10 18 views
21

Comencé a usar el HTTPUrlConnection recomendado y me alejé del DefaultHTTPClient. Una de las cosas que no he podido volver a unir es el uso de una tienda de cookies persistente. Me gustaría simplemente adjuntar un gestor/administrador de cookies personalizado a mi conexión para almacenar las cookies. La documentación de Android no ha sido muy útil ya que cierra el tema sobre las cookies en dos líneas.¿Cómo persisto las cookies cuando uso HTTPUrlConnection?

He estado usando LoopJ's PersistentCookieStore anteriormente y eso funcionó maravillosamente.

¿Alguna idea sobre cómo podría configurar una tienda de cookies persistente en Android que pueda adjuntar a mi HTTPUrlConnection que guarda y recupera las cookies automáticamente?

Gracias

Respuesta

23

Su me ha llevado unas cuantas horas, pero me las arreglé para construir un almacenamiento de cookies encargo yo.

tiene que adjuntar esta haciendo esto:

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); 
     } 
    } 

Aquí está el almacenamiento real:

/* 
* 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); 

    } 

} 
+0

Esto no ha sido probado a fondo, pero voy a hacer cambios sobre la marcha. Por favor sugiere mejoras –

+25

A veces me pregunto si estoy loco por esperar algo tan fundamental como que las cookies persistentes se incluyan en el SDK ... Me aseguraré de volver a publicar si puedo sugerir alguna mejora. –

+8

con esta implementación, agregará cookies al URI exacto del que provienen, lo que significa que no se enviarán a ningún otro URI en ese host. Recomiendo reemplazar el URI pasado con un URI nuevo que consiste en solo el nombre de host para hacer que esto se comporte como se esperaba. ex: con la implementación actual, si visita yourdomain.com/pageOne.htm, no se enviará ningún conjunto de cookies cuando visite yourdomain.com/page Two.htm ya que los URI son diferentes. la implementación debe recortar el parámetro URI hacia abajo a solo sudominio.com para que se comporte como (I) esperado. – Keith

0

utilicé la respuesta anterior, pero ha cambiado mi método añadir a la siguiente para manejar más de una cookie del mismo URI (esta cookie store con GAE estaba tratando el token de sesión y el token de recuerdo como dos cookies separadas del mismo URI por alguna razón):

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(); 
} 

Y para acceder y crear una cookie combinado:

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

Adjuntar a la conexión:

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

Hay algunos problemas básicos en muchos encargo aplicación CookieStore.

El primer problema es la serialización HttpCookie en cadena - El método HttpCookie.toString() no es aceptable para esto porque su resultado no es adecuado para el método HttpCookie.parse (String header).

El segundo problema: la mayor parte de la implementación de CookieStore (por ejemplo, aquí https://codereview.stackexchange.com/questions/61494/persistent-cookie-support-using-volley-and-httpurlconnection) no tiene en cuenta el formato del campo HttpCookie.maxAge. Este es un número de segundos para cookie en vivo. Pero si simplemente persiste en su valor y después de un tiempo lo despersistirá, será incorrecto. Debe convertir el campo maxAge en algo así como "expire_at" y persistir en lugar de maxAge.

1

Verifique la implementación en el siguiente enlace. Guarda las cookies por nombre de host como lo hace la implementación original de java.net.InMemoryCookieStore.

Además, contiene una SerializableHttpCookie para poder serializar el HashMap completo en SharedPreferences.

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