Передайте файлы cookie из HttpURLConnection (java.net.CookieManager) в WebView (android.webkit.CookieManager)

Я видел ответы о том, как это должно работать со старым DefaultHttpClient но нет хорошего примера для HttpURLConnection

Я использую HttpURLConnection чтобы делать запросы к веб-приложению. В начале моего приложения для Android я использую CookieHandler.setDefault(new CookieManager()) чтобы автоматически обрабатывать файлы cookie сеанса, и это работает нормально.

В какой-то момент после входа в систему я хочу показать живые страницы из веб-приложения пользователю с помощью WebView вместо загрузки данных за кулисами с помощью HttpURLConnection . Тем не менее, я хочу использовать тот же самый сеанс, который я установил ранее, чтобы не допустить повторного входа пользователя в систему.

Как скопировать файлы cookie из java.net.CookieManager используемые HttpURLConnection в android.webkit.CookieManager используемый WebView чтобы я мог поделиться сеансом?

    Я хотел бы предложить совершенно другой подход к вашей проблеме. Вместо того, чтобы копировать файлы cookie из одного места в другое (ручная синхронизация), давайте сделаем HttpURLConnection и WebViews одним и тем же хранилищем файлов cookie.

    Это полностью исключает необходимость синхронизации. Любой cookie, обновленный в любом из них, будет немедленно и автоматически отражен в другом.

    Для этого создайте собственную реализацию java.net.CookieManager, которая пересылает все запросы веб-браузеру webkit android.webkit.CookieManager.

    Реализация:

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

    И, наконец, используйте его, выполнив это при инициализации вашего приложения:

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

    По сравнению с DefaultHttpClient , есть несколько дополнительных шагов. Ключевое различие заключается в доступе к существующим файлам cookie в HTTPURLConnection :

    1. Вызовите CookieHandler.getDefault() и CookieHandler.getDefault() результат в java.net.CookieManager .
    2. С менеджером getCookieStore() cookie вызовите getCookieStore() для доступа к хранилищу getCookieStore() cookie.
    3. В хранилище файлов cookie вызовите get() для доступа к списку файлов cookie для данного URI .

    Вот полный пример:

     @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 ... } 

    Я волшебно решил все проблемы с файлом cookie с этой одной строкой в ​​onCreate:

    CookieHandler.setDefault(new CookieManager());

    У меня была та же проблема, и это мое решение:

    Просто после входа в систему (это важно, потому что раньше у вас может быть еще не cookie), используя httpurlconnection POST (после getResponseCode), я делаю:

      responseCode = connexion.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { final String COOKIES_HEADER = "Set-Cookie"; cookie = connexion.getHeaderField(COOKIES_HEADER); ... } 

    (Где cookie – это публичная строка в моем классе)

    И в активности веб-просмотра, где я хочу отображать веб-страницу с сервера с помощью WebView, я делаю:

      String url = "http://toto.com/titi.html"; // the url of the page you want to display CookieSyncManager.createInstance(getActivity()); CookieSyncManager.getInstance().startSync(); android.webkit.CookieManager cookieManager = android.webkit.CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.removeSessionCookie(); cookieManager.setCookie(url, cookie); CookieSyncManager.getInstance().sync(); 

    Поскольку мой веб-просмотр в фрагменте, мне пришлось использовать getActivity () для контекста, мне также пришлось указать android.webkit. Перед CookieManager иначе он не может быть разрешен (импортируйте java.net вместо менеджера android.webkit cookie).

    Cookie – это тот же String, что и выше (в моем фрагменте мне пришлось восстановить его, используя:

      cookie = getArguments().getString(COOKIE); 

    И в моем MainActivity, я отправляю его:

      Bundle arg = new Bundle(); arg.putString(Fragment_Cameras.COOKIE, cookie); fragment.setArguments(arg); 

    Я надеюсь, это поможет!