2012-09-10 18 views
21

Zacząłem używać zalecanego HTTPUrlConnection i odsuwać od DefaultHTTPClient. Jedną z rzeczy, których nie mogłem skleić ze sobą, jest użycie trwałego magazynu plików cookie. Chciałbym po prostu dołączyć niestandardową obsługę plików cookie/menedżera do mojego połączenia, aby przechowywać pliki cookie. Dokumentacja Androida nie była bardzo pomocna, ponieważ zawiera temat dotyczący plików cookie w dwóch wierszach.Jak mogę zachować pliki cookie podczas korzystania z HTTPUrlConnection?

Używam wcześniej LoopJ's PersistentCookieStore i to zadziałało pięknie.

Każdy pomysł, w jaki sposób mogę skonfigurować trwały magazyn plików cookie w systemie Android, który mogę dołączyć do mojego HTTPUrlConnection, który automatycznie zapisuje i pobiera pliki cookie?

Dzięki

Odpowiedz

23

jego zajęło mi kilka godzin, ale udało mi się utworzyć niestandardową STORAGE pliku za siebie.

Musisz dołączyć to w ten sposób:

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

Oto rzeczywisty przechowywania:

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

nie został gruntownie przetestowany, ale zrobię zmiany jak iść. Proszę sugerować ulepszenia. –

+25

Czasami zastanawiam się, czy jestem szalony, by oczekiwać czegoś tak fundamentalnego jak trwałe pliki cookie, które mają być zawarte w SDK ... Na pewno wyślę z powrotem, jeśli będę mógł zaproponować jakieś ulepszenia. –

+8

z tą implementacją doda ciasteczka do dokładnego identyfikatora URI, z którego pochodzą, co oznacza, że ​​nie będą wysyłane do żadnych innych identyfikatorów URI na tym hoście. Zalecam zastąpienie przekazanego URI nowym URI składającym się tylko z nazwy hosta, aby było to zgodne z oczekiwaniami. ex: przy obecnej implementacji, jeśli odwiedzasz twoja_domena.com/pageOne.htm, wszystkie pliki cookie nie zostaną wysłane, gdy odwiedzasz twoja_domena.com/pageTwo.htm, ponieważ identyfikatory URI są różne. implementacja powinna uciąć parametr URI do samej domeny twojadomena.com, aby zachował się tak, jak oczekiwał (I). – Keith

0

Kiedyś odpowiedź powyżej, ale zmieniłem sposób dodać do następujących czynności, aby obsługiwać więcej niż jedno plik cookie z tego samego identyfikatora URI (ten magazyn cookie z GAE traktował token sesji i pamiętnik pamiętnika jako dwa oddzielne pliki cookie z tego samego URI z jakiegoś powodu):

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

I dostęp i utworzyć połączoną ciasteczko:

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

dołączyć do połączenia:

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

Istnieje kilka podstawowych problemów w wielu niestandardowych realizacji CookieStore.

Pierwszy problem to serializacja HttpCookie w łańcuchu - metoda HttpCookie.toString() jest niedopuszczalna, ponieważ jego wynik nie jest odpowiedni dla metody HttpCookie.parse (String header).

Drugi problem: większość implementacji CookieStore (na przykład tutaj https://codereview.stackexchange.com/questions/61494/persistent-cookie-support-using-volley-and-httpurlconnection) nie uwzględnia formatu pola HttpCookie.maxAge. To jest sekunda czasu, w którym plik cookie znajduje się na żywo. Ale jeśli po prostu upierasz się przy swojej wartości i po pewnym czasie ją rozprzesz, to będzie źle. Konieczne jest przekonwertowanie pola maxAge na coś typu "expire_at" i zachowanie go zamiast maxAge.

1

Sprawdź realizację w linku poniżej. Zapisuje pliki cookie według nazwy hosta, tak jak ma to miejsce w oryginalnej implementacji java.net.InMemoryCookieStore.

Poza tym zawiera SerializableHttpCookie, aby móc serializować kompletne HashMap do SharedPreferences.

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

Powiązane problemy