Dwukierunkowa synchronizacja plików cookie między HttpURLConnection (java.net.CookieManager) i WebView (android.webkit.CookieManager)

Niestety, istnieje wiele menedżerów plików cookie dla Androida. Pliki cookie dla HttpURLConnection są utrzymywane przez java.net.CookieManager, A pliki cookie dla WebView są utrzymywane przez android.webkit.CookieManager. Te repozytoria plików cookie są oddzielne i wymagają ręcznej synchronizacji.

Moja aplikacja używa zarówno HttpURLConnections, jak i pokazuje WebViews (jest hybrydą natywnego HTML). Oczywiście chcę, aby obie strony udostępniały wszystkie pliki cookie - więc będę mieć przejrzystą sesję na całym świecie.

Dokładniej:

  1. gdy a plik cookie jest ustawiany/zmieniany w połączeniu HttpURLConnection, chcę, aby WebViews również widział tę zmianę.
  2. gdy plik cookie jest ustawiany/zmieniany w widoku sieci Web, chcę, aby następne połączenia HttpURLConnections również zobaczyły tę zmianę.

Mówiąc najprościej-Szukam dwukierunkowej synchronizacji. Albo jeszcze lepiej, aby oboje korzystali z tego samego repozytorium plików cookie. Można założyć, że oba są aktywne w tym samym czasie(jak na różnych kartach).

Pytania:

  1. Czy jest sposób na czy obie strony korzystają z tego samego repozytorium plików cookie?

  2. Jeśli nie, Jaka jest zalecana praktyka wykonywania ręcznej synchronizacji? Kiedy dokładnie powinienem synchronizować i jak?

Podobne pytanie: to pytanie rozwiązuje podobny problem, ale implementuje tylko synchronizację jednokierunkową (HttpURLConnection- > WebView).

Mój najlepszy jak dotąd pomysł: naprawdę chcę uniknąć ręcznej synchronizacji, więc próbowałem pomyśleć, jak sprawić, by obie używały tego samego repozytorium. Może uda mi się stworzyć mój własny program obsługi rdzenia, który rozszerza java.net.CookieManager. Ustawię go jako główny mechanizm obsługi plików cookie za pomocą java.net.CookieHandler.setDefault(). Jego implementacja będzie proxy do instancji android.webkit.CookieManager handler (dla każdej funkcji po prostu uzyskam dostęp do webkit managera).

Author: Community, 2013-08-05

1 answers

Wdrożyłem swój własny pomysł. To całkiem fajne. Stworzyłem własną implementację java.net.CookieManager, która przekazuje wszystkie żądania do webkit android.webkit.CookieManager WebViews. Oznacza to, że nie jest wymagana Synchronizacja, A HttpURLConnection używa tego samego przechowywania plików cookie, co WebViews.

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

I użyj go, wykonując to podczas inicjalizacji aplikacji:

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

Testowanie

Moje wstępne testy pokazują to działa dobrze. Widzę pliki cookie współdzielone między WebViews i HttpURLConnection. Mam nadzieję, że nie napotkam żadnych problemów. Jeśli wypróbujesz to i odkryjesz jakikolwiek problem, skomentuj.

 61
Author: talkol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-08 14:37:09