Передать файлы cookie из HttpURLConnection (java.net.CookieManager) в WebView (android.webkit.CookieManager)
Я видел ответы о том, как это должно работать со старым
DefaultHttpClient
но нет хорошего примера дляHttpURLConnection
я использую HttpURLConnection
делать запросы к веб-приложению. В начале моего приложения для Android я использую CookieHandler.setDefault(new CookieManager())
автоматически обрабатывать сеансовые куки, и это работает нормально.
В какой-то момент после входа в систему я хочу показать живые страницы из веб-приложения пользователю с WebView
вместо загрузки данных за кулисами с HttpURLConnection
, Однако я хочу использовать тот же сеанс, который я установил ранее, чтобы предотвратить повторный вход пользователя в систему.
Как мне скопировать куки с java.net.CookieManager
использован HttpURLConnection
в android.webkit.CookieManager
использован WebView
чтобы я мог поделиться сессией?
4 ответа
По сравнению с DefaultHttpClient
Есть несколько дополнительных шагов. Основное отличие состоит в том, как получить доступ к существующим файлам cookie в HTTPURLConnection
:
- Вызов
CookieHandler.getDefault()
и привести результат кjava.net.CookieManager
, - С менеджером печенья звоните
getCookieStore()
чтобы получить доступ к магазину печенья. - С магазином печенья звоните
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
...
}
Я хотел бы предложить совершенно другой подход к вашей проблеме. Вместо того, чтобы копировать куки из одного места в другое (ручная синхронизация), давайте заставим HttpURLConnection и WebViews использовать одно и то же хранилище куки.
Это полностью исключает необходимость синхронизации. Любой файл cookie, обновленный в одном из них, будет немедленно и автоматически отражен в другом.
Для этого создайте свою собственную реализацию java.net.CookieManager, которая перенаправляет все запросы в webkit android.webkit.CookieManager WebViews.
Реализация:
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);
Я волшебным образом решил все свои проблемы с 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 = getArguments().getString(COOKIE);
и в моей MainActivity я отправляю это:
Bundle arg = new Bundle();
arg.putString(Fragment_Cameras.COOKIE, cookie);
fragment.setArguments(arg);
Я надеюсь, что это может помочь!