Как сохранить куки при использовании HTTPUrlConnection?

Я начал использовать рекомендуемые HTTPUrlConnection и отошел от DefaultHTTPClient, Одна из вещей, которую я не смог склеить, - это постоянное хранилище файлов cookie. Я хотел бы просто прикрепить свой обработчик / менеджер файлов cookie к своему соединению для хранения файлов cookie. Документация по Android не очень полезна, поскольку она заключает тему о куки в две строки.

Я использовал LoopJ's PersistentCookieStore раньше, и это работало прекрасно.

Любая идея о том, как я могу настроить постоянное хранилище файлов cookie в Android, которое я могу прикрепить к своему HTTPUrlConnection что сохраняет и получает куки автоматически?

Спасибо

4 ответа

Решение

Это заняло у меня несколько часов, но мне удалось создать собственное хранилище файлов 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);

    }

}

Я использовал ответ выше, но изменил свой метод добавления на следующий, чтобы обрабатывать более одного файла cookie с одного и того же URI (этот магазин cookie с GAE обрабатывал маркер сеанса и маркер запоминания как два отдельных файла cookie из одного и того же URI).:

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

И чтобы получить доступ и создать объединенный файл 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); 

Во многих пользовательских реализациях CookieStore есть некоторые основные проблемы.

Первая проблема - сериализация HttpCookie в строку - метод HttpCookie.toString() для этого неприемлем, поскольку его результат не подходит для метода HttpCookie.parse(заголовок строки).

Вторая проблема: большая часть реализации CookieStore (например, здесь https://codereview.stackexchange.com/questions/61494/persistent-cookie-support-using-volley-and-httpurlconnection) не учитывает формат HttpCookie. поле maxAge. Это количество секунд, в течение которых файл cookie активируется. Но если вы просто сохраните его значение и через некоторое время не сохраните его, это будет неправильно. Вы должны преобразовать поле maxAge во что-то вроде "expire_at" и сохранить его вместо maxAge.

Оформить заказ по ссылке ниже. Он сохраняет куки по имени хоста, как это делает оригинальная реализация java.net.InMemoryCookieStore.

Кроме того, он содержит SerializableHttpCookie, чтобы иметь возможность сериализовать полный HashMap в SharedPreferences.

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

Другие вопросы по тегам