For Android CookieManager class there is a method -- getCookie(String url).
For this we need to know correct url.
Is there a way to get all cookies in CookieManager and get the urls .
some thing like getCookies ??
This is just to double check if i am giving anything wrong in my url for getCookie(String url) call.
I am not getting the cookie when i call the same.
I am passing complete IP address here in url. Something like this : "xx.x.x.x"
Thanks
Mia
I used the CookieManager with the java.net package in my Android Application and it works like a charm. Here is a code snippet :
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.HttpCookie;
import java.util.List;
private class MyCookieManager
{
private CookieManager mCookieManager = null;
MyCookieManager() {
mCookieManager = new CookieManager();
mCookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(mCookieManager);
}
private List<HttpCookie> getCookies() {
if(mCookieManager == null)
return null;
else
return mCookieManager.getCookieStore().getCookies();
}
public void clearCookies() {
if(mCookieManager != null)
mCookieManager.getCookieStore().removeAll();
}
public boolean isCookieManagerEmpty() {
if(mCookieManager == null)
return true;
else
return mCookieManager.getCookieStore().getCookies().isEmpty();
}
public String getCookieValue() {
String cookieValue = new String();
if(!isCookieManagerEmpty()) {
for (HttpCookie eachCookie : getCookies())
cookieValue = cookieValue + String.format("%s=%s; ", eachCookie.getName(), eachCookie.getValue());
}
return cookieValue;
}
}
You can use reflection to see the cookie map. It's called mCookieMap in 4.0.3 (and probably in earlier releases as well). The type is Map>.
This isn't a great way of doing it because you'll risk breaking on different devices or OS versions if they don't use mCookieMap, but CookieManager doesn't offer a public way of knowing which URLs it's visited.
Related
I have searched through a lot of answers and implemented one which helped me with maintaining cookies in volley request.
Code which helped me is following
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
That code has helped me maintain same session with all volley request.
Right after this code I open a webview in onCreate method. Webview has different session and not shared with volley request.
How can I make sure that both has same session.
Following is my onCreate method
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
/* Dialog view */
LinearLayout linearLayoutProgressBar = findViewById(R.id.linearLayoutProgressBar);
// Creates instance of the manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setSaveFormData(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
WebViewClientImpl webViewClient = new WebViewClientImpl(this, linearLayoutProgressBar);
webView.setWebViewClient(webViewClient);
webAppInterface = new WebAppInterface(this, webView);
webView.addJavascriptInterface(webAppInterface, "Android");
webView.loadUrl(AppConstants.mobileUrl);
//GetLocation function fetches the location and sends it to server.
//So first webview is opened and then data is sent to server.
getLocation();
}
Thank you
Another solution is to use CookieManager. The issue is that there are many CoockieManager depending on the context used. With Volley it is java.net.CookieManager and with WebView it is android.webkit.CookieManager. Both are not compatible with each other.
The solution I found here is to create your own CookieManager extended from java.net.CookieManager. The goal is to send the request to the android.webkit.CookieManagerin the same time. Like this, both are synchronized.
Juste create the following class as is :
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 finally, call once only, early in your code and before any https request :
WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL);
java.net.CookieHandler.setDefault(coreCookieManager);
After looking for a solution for a long time, I found it here: Two way sync for cookies between HttpURLConnection (java.net.CookieManager) and WebView (android.webkit.CookieManager)
From Volley Request, you have to take a cookie and store in shared preference.
then you can set the same cookie with your web view settings.
To retrieve cookie details from volley refer this link
To set the cookie to web view URL like
CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setAcceptThirdPartyCookies(webView, true);
} else {
cookieManager.setAcceptCookie(true);
}
cookieManager.setCookie(url, ${cookie});
webView.load(url);
I am overriding this method for my WebView. And I am using the proper domain. When debugging using an Android simulator I only see a partial list of all of the cookies. The one in particular I'm requiring the value of isn't listed. Any suggestions? Source code below.
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
_cookieManager.Flush();
string customerId = null;
var cookies = _cookieManager.GetCookie(Constants.DCH_DOMAIN);
Log.Info(TAG, string.Format("Cookies retrieved as {0}.", cookies));
if (cookies != null)
{
string[] tempList = cookies.Split(';');
foreach (var pair in tempList)
{
if (pair.Contains("wishlist_customer_id"))
{
string[] tempPair = pair.Split('=');
customerId = tempPair[1];
if (customerId != null)
{
Log.Info(TAG, string.Format("Customer ID retrieved as {0}.", customerId));
PCLStorage(customerId);
}
}
}
}
UPDATE There is another domain that stores cookies as part of this web session. No different in path, HTML, same site, secure, etc. between the four cookies. I'll attach what Chrome on my workstation looks like, showing these four cookies. Then I'll attach what my Android simulator's device log looks like, where I output the cookie collection based on the subclassed WebViewClient. Only two of the four cookies appear to be there. I inserted a SystemClock.Sleep(5000) before retrieving the cookies, in order to give them a chance to fully populate as well.
Chrome session
WebViewClient session
you should do cookied synchronization before load url to ensure complete cookie data like :
_cookieManager.flush ();
webView.loadUrl(url);
then get cookies int the OnPageFinished method :
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
string customerId = null;
var cookies = _cookieManager.GetCookie(url);
Log.Info(TAG, string.Format("Cookies retrieved as {0}.", cookies));
if (cookies != null)
{
string[] tempList = cookies.Split(';');
foreach (var pair in tempList)
{
if (pair.Contains("wishlist_customer_id"))
{
string[] tempPair = pair.Split('=');
customerId = tempPair[1];
if (customerId != null)
{
Log.Info(TAG, string.Format("Customer ID retrieved as {0}.", customerId));
PCLStorage(customerId);
}
}
}
}
Thanks to Leo Zhu the issue has been resolved. Apparently before I load the WebView URL I needed to flush the CookieManager instance. This resulted in all of the cookies for this particular resource to appear and be available for querying. Hope that this might help anyone else who runs into a similar challenge!
Is there a way to block ads in an Android WebView? I am building app that lets users browse web pages, but need to block ads. Its basically a custom browser, but I need to get rid of ads.
What is my best option?
Based on: https://github.com/adblockplus/adblockplusandroid
saw this:
https://gist.github.com/rjeschke/eb1bb76128c5e9a9e7bc
import java.io.File;
import java.util.regex.Pattern;
import org.adblockplus.android.ABPEngine;
import org.adblockplus.libadblockplus.FilterEngine.ContentType;
import android.content.Context;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class BlockingWebViewClient extends WebViewClient
{
private ABPEngine engine;
private static final Pattern RE_JS = Pattern.compile("\\.js$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_CSS = Pattern.compile("\\.css$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_IMAGE = Pattern.compile("\\.(?:gif|png|jpe?g|bmp|ico)$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_FONT = Pattern.compile("\\.(?:ttf|woff)$", Pattern.CASE_INSENSITIVE);
private static final Pattern RE_HTML = Pattern.compile("\\.html?$", Pattern.CASE_INSENSITIVE);
public void start(Context context)
{
final File basePath = context.getFilesDir();
this.engine = ABPEngine.create(context, ABPEngine.generateAppInfo(context),
basePath.getAbsolutePath());
// Additional steps may be required here, i.e. :
// - subscription selection or updating
// - maybe also setting other options (like AcceptableAds)
// It might also be a good idea to delay the first calls until
// everything is loaded, have a look at AndroidFilterChangeCallback
// and ABPEngine.create()
}
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
// Determine the content
ContentType contentType = null;
if (RE_JS.matcher(url).find())
{
contentType = ContentType.SCRIPT;
}
else if (RE_CSS.matcher(url).find())
{
contentType = ContentType.STYLESHEET;
}
else if (RE_IMAGE.matcher(url).find())
{
contentType = ContentType.IMAGE;
}
else if (RE_FONT.matcher(url).find())
{
contentType = ContentType.FONT;
}
else if (RE_HTML.matcher(url).find())
{
contentType = ContentType.SUBDOCUMENT;
}
else
{
contentType = ContentType.OTHER;
}
// Check if we should block ... we sadly do not have the referrer chain here,
// might also be hard to get as we do not have HTTP headers here
if (engine.matches(url, contentType, new String[0]))
{
// If we should block, return empty response which results in a 404
return new WebResourceResponse("text/plain", "UTF-8", null);
}
// Otherwise, continue by returning null
return null;
}
}
It is done already:
https://github.com/adblockplus/libadblockplus-android
You can put it at xml:
<org.adblockplus.libadblockplus.android.webview.AdblockWebView
android:id="#+id/main_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
I am setting the cookie in headers and call WebView.loadUrl() with this header but it(Cookie in header) will not work on any android device except 4.4. I have test it on android versions 4.2, 4.3, 4.4, 5.0 and 5.1.
webView = (WebView) findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
HashMap <String, String> extraHeaders = new HashMap<String, String>();
extraHeaders.put("Cookie", "{cookie value}");
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url){
view.loadUrl(url, extraHeaders);
return false;
}
});
webView.loadUrl(url, extraHeaders);
Have you tried this
CookieManager.getInstance().setAcceptCookie(true);
if you are using Android Lollipop, then
CookieManager.getInstance().setAcceptCookie(true);
won't work. You need to use
CookieManager.getInstance().setAcceptThirdPartyCookies(true);
To set cookie use the following method
CookieManager.getInstance().setCookie(BuildConfig.BASE_SERVER_ENDPOINT,COOKIE_VAL);
Make sure the base endpoint matches the base url of the links opened in the webview.
To remove cookie
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().removeAllCookies(null);
} else {
CookieManager.getInstance().removeAllCookie();
}
This is just a quick post about adding cookies to a web view. If you’ve ever tried to do this the way most people have said that it should be done, you’ve failed miserably and found this post. :)
The way it’s supposed to work is you set the cookie on the CookieManager and then tell the CookieSyncManager to sync.
CookieManager.getInstance().setCookie(domain, value);
CookieSyncManager.getInstance().sync();
I’ve never got this to work as described. With or without async tasks waiting for the threads to catch up.
Instead, I just add the cookie in the header of all the loadUrl calls.
Map<String, String> headers = new HashMap<String, String>();
headers.put("Cookie", "cookieName=cookieValue;domain=domain.com;path=/;Expires=Thu, 2 Aug 2021 20:47:11 UTC;");
webView.loadUrl("myurl.com", headers );
Caveat: I only need to initially load the appropriate cookie for the request, if you want to cover nested calls from inside the browser, you need to override shouldOverrideUrlLoading.
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, headers);
return false;
}
});
If you need to inject the cookie for all requests(including images, js, etc), you’re going to need to override shouldInterceptRequest,
It's beceause of Cookie Policy, to fix it, you should add this :
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.init();
// Allow third party cookies for Android Lollipop
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WebView webView = (WebView)super.appView;
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView,true);
}
super.loadUrl(Config.getStartUrl());
}
I got the solution for the issue by creating the custom cookie manager:
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);
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 initialize the custom cookie manager in Application class or when application starts as:
android.webkit.CookieSyncManager.createInstance(this);
android.webkit.CookieManager.getInstance().setAcceptCookie(true);
WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL);
java.net.CookieHandler.setDefault(coreCookieManager);
If you are using Android Lollipop i.e. SDK 21, then:
CookieManager.getInstance().setAcceptCookie(true);
won't work. You need to use:
CookieManager.getInstance().setAcceptThirdPartyCookies(true);
I ran into same issue and the above line worked as a charm.
I have a cookie from the server and I save this cookie in a Shared Preference. When I send requests to the server from Ion library it goes right because I'm logged in the app and Ion has this cookie. And when I close the app and re-open, Ion has my cookie. The problem is when I destroyed the app, Ion doesn't have this cookie any more. And when I request a query to the server, it gives me a new one cookie and Ion has this new cookie. So, I need to establish the old cookie to the Ion library.
I've tried to set the cookie in the header:
String cookieString = ApiConstants.API_COOKIE_NAME + "=" + cookie;
headers.add(new BasicNameValuePair("Cookie", cookieString));
if (headers != null) {
for (int i = 0; i < headers.size(); i++) {
b = b.addHeader(headers.get(i).getName(), headers.get(i).getValue());
}
}
And I've tried to add this cookie to the CookieManager:
CookieManager cookieManager = CookieManager.getInstance();
CookieSyncManager.createInstance(context);
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(ApiConstants.BASIC_ROOT_URL, cookieString);
CookieSyncManager.getInstance().sync();
But, none of this tried have gone, someone can help me?
This is an oldish question but I figured I'd publish it if only for myself.
This is not as hard as it seems, but without documentation, you have to look in the test cases to figure it out. I've taken the code I've used and wrapped it in a helper class. There is definitely more you could do with it (setting expiry and what not), but this should be enough to satisfy the poster's requirements:
package com.example;
import android.content.Context;
import com.koushikdutta.async.http.Headers;
import com.koushikdutta.ion.Ion;
import java.io.IOException;
import java.net.CookieManager;
import java.net.URI;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/*
This is adapted from my own code... so I'm not sure this will work exactly like this but it'll give you a starting point
*/
public class IonCookieManager {
CookieManager manager;
public IonCookieManager(Context context) {
Ion ion = Ion.getDefault(context);
manager = ion.getCookieMiddleware().getCookieManager();
}
public void storeCookies(URLConnection conn) throws IOException {
List<String> cookies = conn.getHeaderFields().get("Set-Cookie");
URI uri = URI.create(conn.getURL().toString());
if(cookies != null) {
storeCookies(uri, cookies);
}
}
public void storeCookies(URI uri, List<String> cookies) throws IOException {
Headers headers = new Headers();
headers.addAll("Set-Cookie", cookies);
manager.put(uri, headers.getMultiMap());
}
public void storeCookie(URI uri, String cookieName, String cookieValue) throws IOException {
List<String> cookie = new ArrayList<String>();
cookie.add(String.format("%s=%s", cookieName, cookieValue));
storeCookies(uri, cookie);
}
}
Also as a gist.