web-dev-qa-db-fra.com

Passer des cookies de HttpURLConnection (Java.net.CookieManager) à WebView (Android.webkit.CookieManager)

J'ai vu des réponses sur la façon dont cela devrait fonctionner avec l'ancien DefaultHttpClient mais il n'y a pas un bon exemple pour HttpURLConnection

J'utilise HttpURLConnection pour faire des demandes à une application Web. Au début de l'application my Android Android, j'utilise CookieHandler.setDefault(new CookieManager()) pour gérer automatiquement les cookies de session, et cela fonctionne bien.

À un moment donné après la connexion, je souhaite afficher les pages en direct de l'application Web à l'utilisateur avec un WebView au lieu de télécharger des données en arrière-plan avec HttpURLConnection. Cependant, je souhaite utiliser la même session que celle que j'ai établie plus tôt pour empêcher l'utilisateur d'avoir à se reconnecter.

Comment copier les cookies de Java.net.CookieManager utilisé par HttpURLConnection à Android.webkit.CookieManager utilisé par WebView pour partager la session?

30
quietmint

Par rapport à DefaultHttpClient, il y a quelques étapes supplémentaires. La principale différence est de savoir comment accéder aux cookies existants dans HTTPURLConnection:

  1. Appelez CookieHandler.getDefault() et convertissez le résultat en Java.net.CookieManager.
  2. Avec le gestionnaire de cookies, appelez getCookieStore() pour accéder au magasin de cookies.
  3. Avec le magasin de cookies, appelez get() pour accéder à la liste des cookies pour le URI donné.

Voici un exemple complet:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // Get cookie manager for WebView
    // This must occur before setContentView() instantiates your WebView
    Android.webkit.CookieSyncManager webCookieSync =
        CookieSyncManager.createInstance(this);
    Android.webkit.CookieManager webCookieManager =
        CookieManager.getInstance();
    webCookieManager.setAcceptCookie(true);

    // Get cookie manager for HttpURLConnection
    Java.net.CookieStore rawCookieStore = ((Java.net.CookieManager)
        CookieHandler.getDefault()).getCookieStore();

    // Construct URI
    Java.net.URI baseUri = null;
    try {
        baseUri = new URI("http://www.example.com");
    } catch (URISyntaxException e) {
        // Handle invalid URI
        ...
    }

    // Copy cookies from HttpURLConnection to WebView
    List<HttpCookie> cookies = rawCookieStore.get(baseUri);
    String url = baseUri.toString();
    for (HttpCookie cookie : cookies) {
        String setCookie = new StringBuilder(cookie.toString())
            .append("; domain=").append(cookie.getDomain())
            .append("; path=").append(cookie.getPath())
            .toString();
        webCookieManager.setCookie(url, setCookie);
    }

    // Continue with onCreate
    ...
}
17
quietmint

Je voudrais suggérer une approche complètement différente de votre problème. Au lieu de copier les cookies d'un endroit à un autre (synchronisation manuelle), faisons en sorte que HttpURLConnection et WebViews utilisent le stockage de cookies identique.

Cela élimine complètement le besoin de synchronisation. Tout cookie mis à jour dans l'un d'eux sera immédiatement et automatiquement reflété dans l'autre.

Pour ce faire, créez votre propre implémentation de Java.net.CookieManager qui transmet toutes les demandes au webkit des WebViews Android.webkit.CookieManager.

La mise en oeuvre:

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

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

et enfin l'utiliser en faisant cela lors de l'initialisation de votre application:

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

J'ai résolu comme par magie tous mes problèmes de cookies avec cette seule ligne dans onCreate:

CookieHandler.setDefault(new CookieManager());

11
Chani