Pass Cookies from Httpurlconnection (Java.Net.Cookiemanager) to Webview (Android.Webkit.Cookiemanager)

Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager)

As compared with DefaultHttpClient, there are a few extra steps. The key difference is how to access the existing cookies in HTTPURLConnection:

  1. Call CookieHandler.getDefault() and cast the result to java.net.CookieManager.
  2. With the cookie manager, call getCookieStore() to access the cookie store.
  3. With the cookie store, call get() to access the list of cookies for the given URI.

Here's a complete example:

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

Two way sync for cookies between HttpURLConnection (java.net.CookieManager) and WebView (android.webkit.CookieManager)

I've implemented my own idea. It's actually pretty cool. I've created my own implementation of java.net.CookieManager which forwards all requests to the WebViews' webkit android.webkit.CookieManager. This means no sync is required and HttpURLConnection uses the same cookie storage as the 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();
}
}

And use it by doing this on your application initialization:

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

Testing

My initial testing show this is working well. I see cookies shared between the WebViews and HttpURLConnection. I hope I'll not run into any issues. If you try this out and discover any problem, please comment.

How to get cookies out of the android.webkit.CookieManager on a non io thread?

See my reply on the bug: https://code.google.com/p/android/issues/detail?id=65786#c8. I'm curious to see if that helps.

OkHTTPClient pass cookies to Webview

With OkHttp 3.0, you can use a method similar to sharing with HttpURLConnection by making a WebkitCookieManagerProxy that uses the webkit cookie store. Adapted from Pass cookies from HttpURLConnection (java.net.CookieManager) to WebView (android.webkit.CookieManager) .

public class WebkitCookieManagerProxy extends CookieManager implements CookieJar {
private android.webkit.CookieManager webkitCookieManager;

private static final String TAG = WebkitCookieManagerProxy.class.getSimpleName();

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

@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
HashMap<String, List<String>> generatedResponseHeaders = new HashMap<>();
ArrayList<String> cookiesList = new ArrayList<>();
for(Cookie c: cookies) {
// toString correctly generates a normal cookie string
cookiesList.add(c.toString());
}

generatedResponseHeaders.put("Set-Cookie", cookiesList);
try {
put(url.uri(), generatedResponseHeaders);
} catch (IOException e) {
Log.e(TAG, "Error adding cookies through okhttp", e);
}
}

@Override
public List<Cookie> loadForRequest(HttpUrl url) {
ArrayList<Cookie> cookieArrayList = new ArrayList<>();
try {
Map<String, List<String>> cookieList = get(url.uri(), new HashMap<String, List<String>>());
// Format here looks like: "Cookie":["cookie1=val1;cookie2=val2;"]
for (List<String> ls : cookieList.values()) {
for (String s: ls) {
String[] cookies = s.split(";");
for (String cookie : cookies) {
Cookie c = Cookie.parse(url, cookie);
cookieArrayList.add(c);
}
}
}
} catch (IOException e) {
Log.e(TAG, "error making cookie!", e);
}
return cookieArrayList;
}

}

Then add an instance of the proxy as your cookieJar when building the OkHttpClient.

client = new OkHttpClient.Builder().cookieJar(proxy).build();

Share created session between HTTPURLCONNECTION and WebView

That's because the WebView has its own CookieStore called android.net.CookieManager. And you created an instance of java.net.Cookiemanager.
They do not know each other. You have to swap the cookies between those both.

1.) Create your own instance of java.net.CookieManager which gets a instance of android.net.CookieManager:

public class MyCookieManager extends CookieManager  {

private android.webkit.CookieManager webkitCookieManager = null;

/**
* Constructor
* @param cookieManager android.webkit.CookieManager
* @param cookiePolicy CookiePolicy
*/
public MyCookieManager (android.webkit.CookieManager cookieManager, CookiePolicy cookiePolicy) {

super(null, cookiePolicy);
this.webkitCookieManager = cookieManager;
//Cookies are allowed
this.webkitCookieManager.setAcceptCookie(true);
}

/**
* @param uri URI
* @param responseHeaders Map<String, List<String>>
*/
@Override
public void put(URI uri, Map<String, List<String>> responseHeaders) {

if (responseHeaders == null) {

return;
}

for (String headerKey : responseHeaders.keySet()) {

if ( headerKey == null || "Set-Cookie".equalsIgnoreCase(headerKey) == false) {

continue;
}

for (String headerValue : responseHeaders.get(headerKey)) {

webkitCookieManager.setCookie(uri.toString(), headerValue);
}
}

}

/**
* @param uri URI
* @param requestHeaders Map<String, List<String>>
* @return Map<String, List<String>>
*/
@Override
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) {

if (requestHeaders == null) {

return null;
}

Map<String, List<String>> res = new java.util.HashMap<String, List<String>>();

// get cookies from Webview CookieManager
String cookie = webkitCookieManager.getCookie(uri.toString());

if (cookie == null) {

cookie = "";
}
res.put("Cookie", Arrays.asList(cookie));

return res;
}
}

2.) And in your Application-Class something like this:

public class ApplicationWrapper extends Application {

private MyCookieManager manager = null;

@Override
public void onCreate() {

//some work...
this.initCookieManager();
//some more work...
}

private void initCookieManager () {

this.manager = new MyCookieManager(
CookieManager.getInstance(),
java.net.CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(this.manager);
}

}

Trying to load cookies with url in android webview

 WebView webview = (WebView) this.findViewById(R.id.webView);
final WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAppCacheEnabled(true);
settings.setBuiltInZoomControls(true);
settings.setPluginState(WebSettings.PluginState.ON);

webview.setWebChromeClient(new WebChromeClient());

CookieSyncManager.createInstance(YourClass.this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeSessionCookie();
cookieManager.setCookie("your domain name", cookie);
CookieSyncManager.getInstance().sync();

Map<String, String> header = new HashMap<String, String>();
header.put("Cookie", cookie);
if(isConnected()) {
webview.loadUrl(url, header);
}
else {
webview.setVisibility(View.GONE);
textView.setText("Your custom error message.");
textView.setVisibility(View.VISIBLE);
}

Android - extracting cookies after login in webview

You can extract all cookies current url by this way from webview as string:

@Override
public void onPageFinished(WebView view, String url){
String cookies = CookieManager.getInstance().getCookie(url);
Log.d(TAG, "All the cookies in a string:" + cookies);
}


Related Topics



Leave a reply



Submit