La sincronización bidireccional para las cookies entre HttpURLConnection (java.net.CookieManager) y WebView (android.webkit.CookieManager)

Desafortunadamente, hay una multitud de administradores de cookies para Android. Las cookies para HttpURLConnection son mantenidas por java.net.CookieManager y las cookies para WebView son mantenidas por android.webkit.CookieManager . Estos repositorios de cookies son independientes y requieren sincronización manual.

Mi aplicación utiliza HttpURLConnections y muestra WebViews (es un híbrido nativo-HTML). Naturalmente, quiero compartir las cookies, así que tendré una sesión transparente en todas partes.

Más específicamente:

  1. Cuando una cookie es establecida / cambiada en una HttpURLConnection, quiero que las WebViews vean este cambio también.
  2. Cuando se configura / cambia una cookie en un WebView, quiero que las siguientes HttpURLConnections vean este cambio también.

En pocas palabras – estoy buscando una sincronización bidireccional. O incluso mejor, hacer que ambos usen el mismo repositorio de cookies. Puede asumir que ambos están activos al mismo tiempo (como en diferentes pestañas).

Preguntas:

  1. ¿Hay alguna manera de hacer que ambos usen el mismo repositorio de cookies?

  2. Si no, ¿cuál es la práctica recomendada para realizar la sincronización manual? ¿Cuándo debo sincronizar exactamente y cómo?

Pregunta relacionada: Esta pregunta aborda un problema similar, pero sólo implementa la sincronización unidireccional (HttpURLConnection -> WebView).

Mi mejor idea hasta el momento: Realmente quiero evitar una sincronización manual, así que traté de pensar cómo hacer que ambos usen el mismo repositorio. Tal vez pueda crear mi propio controlador central que extienda java.net.CookieManager . Lo estableceré como el manejador de la galleta principal usando java.net.CookieHandler.setDefault() . Su implementación será un proxy para la instancia del manejador android.webkit.CookieManager (para cada función accederé simplemente al administrador de webkit).

He implementado mi propia idea. En realidad, es genial. He creado mi propia implementación de java.net.CookieManager que reenvía todas las solicitudes al webkit de WebViews android.webkit.CookieManager . Esto significa que no se requiere sincronización y HttpURLConnection utiliza el mismo almacenamiento de cookies que las WebViews.

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

Y úselo haciendo esto en la inicialización de la aplicación:

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

Pruebas

Mi prueba inicial muestra que esto está funcionando bien. Veo las cookies compartidas entre las WebViews y HttpURLConnection. Espero no tener problemas. Si lo prueba y descubre cualquier problema, por favor comente.

  • Reutilizando HttpURLConnection para mantener la sesión viva
  • Cómo detener HttpURLConnection.getInputStream ()?
  • HttpsURLConnection y conexiones intermitentes
  • Cómo configurar el tipo de contenido en HttpURLConnection?
  • HTC Un error? Partes del encabezado HTTP que aparecen en URLConnection InputStream
  • HttpUrlConnection carga de archivo multipart con ProgressBar
  • Evitar llamadas de método CONNECT no solicitadas desde HttpURLConnection
  • Httpurlconnection es muy lento en Android 4.2
  • Java.io.IOException: No se han encontrado problemas de autenticación
  • Emita las direcciones de streaming para Google Maps API v2 Android
  • Android HttpsUrlConnection eofexception
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.