Cookie on Android 2.2 is not available in WebView - android

I made a Android App with minimum required API 8.
The users are authenticated on my backend with a cookie. This works on every device that has an api level 9 or higher.
The Cookie is saved with CookieManager:
CookieManager cManager = CookieManager.getInstance();
CookieSyncManager.createInstance(LauncherApplication.getAppContext());
cManager.setAcceptCookie(true);
cManager.setCookie(".xxxxxxxx.xx", "MobileGuid=" + guid);
CookieSyncManager.getInstance().sync();
I check if this Cookie is available also with CookieManager:
public static boolean hasCookie(){
CookieManager cManager = CookieManager.getInstance();
String cookieString = cManager.getCookie(".xxxxxxx.xx");
if(cookieString != null && cookieString.contains("MobileGuid")){
return true;
}
return false;
}
This returns always true, but the Cookie is just available in the WebView if the Android Version is higher then 2.2. (I checked this with phpinfo)
My WebView configuration looks like this:
String databasePath = LauncherApplication.getAppContext().getApplicationContext().getDir("database",
Context.MODE_PRIVATE).getPath();
WebSettings mainWebSettings = mainWebView.getSettings();
mainWebSettings.setJavaScriptEnabled(true);
mainWebSettings.setAppCacheEnabled(true);
mainWebSettings.setDatabaseEnabled(true);
mainWebSettings.setDomStorageEnabled(true);
mainWebSettings.setDatabasePath(databasePath);

When you call cManager.setCookie(), try passing
cManager.setCookie("a.xxxxxxxx.xx", "MobileGuid=" + guid + "; domain=xxxxxxx.xx");
So I've added an "a" to the first parameter (literally the character 'a'), and added "domain=xxxxxxx.xx" to the cookie itself.
Your code as written seems to be all correct, and I had a similar struggle with API 9 devices not sending cookies while API 14 devices did. I'm afraid I don't know exactly why it works, but it was the only thing that helped me.

Like the answer of Hylianpuffball the idea is to add a character below your domain name. I think that the CookieManager is looking for something like .domain.com and kind of substring is done to get the domain name.
Just add a dot or any character and it will be working

Related

How to set android backend minSdk

im working on an android app with some server-side business logic. Im using android studio and im creating that kind of app for a first time.
I am trying to use server-side application to login to a different system and return me a cookie, so my android application can tell, whether the set credentials are correct.
Here's my endpoint provided method.
/** Returns user with cookie set either to null or actual cookie from AIS */
#ApiMethod(name = "login")
public User login(#Named("loginName") String name, #Named("password") String password) {
AISCommunicator aisCommunicator = new AISCommunicator();
String cookieVal = aisCommunicator.login(password,name);
User user = new User();
user.setCookie(cookieVal);
//user.setCookie("asdasdasd");
return user;
}
AISCommunicator is a serverside bean. At the moment it's part of a code
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
is marked as incorrect by Android studio, which tells me, that to use it, i need to declare minSdk level 9, while currently i have 1. How can i do that? I have set minSdk in my client's app, but it seems like it does not influence the serverside bean.
Anyway, the code is still runnable for some reason and the endpoint Bean returns 404 not found error at the moment.
Ignore Android Studio's error. This is one of its known and unfixed bugs.

Set cookies programatically in Crosswalk WebView on Android

I need to make Crosswalk on Android (in a Cordova project) use some
cookies I gathered via an Apache HttpClient.
However I'm not sure how to achieve this. I tried experimenting with
the XWalkCookieManager but I think everything I do with the
XWalkCookieManager is ignored. Where would I initialize the cookie
manager? Is this even supported yet?
//cookieStore contains the cookies I got via a request from the Apache
// HttpClient.
List<Cookie> cookies = cookieStore.getCookies();
for (int i = 0; i < cookies.size(); i++) {
Cookie cookie = cookies.get(i);
String cookieString = buildCookieStringFromCookie(cookie);
// This is a XWalkCookieManager I initialized earlier but it doesn't do anything
//as far as I can tell.
cookieManager.setCookie(cookie.getDomain(),cookieString);
}
I would really appreciate any help, this is the only thing that
currently keeps me from using Crosswalk successfully.
I have also tried using the standard Android cookie Manager via CookieManager.getInstance().setCookie(cookie.getDomain(), cookieString); but this seems to be ignored by Crosswalk as well.
Best,
Andreas
//Edit for future reference:
The issue was that Crosswalk expects the cookie url to start with https:// and the native Android webview doesn't (or the other way around, I'm not sure anymore). Now what is working fine is to set the cookie twice, once without https and once with https:
mCookieManager.setCookie(cookie.getDomain(), cookieString);
mCookieManager.setCookie("https://" + cookie.getDomain(), cookieString);
You can create an instance of XWalkCookieManager and set the differents cookies in it.
It seems to be shared accross the XwalkViews.
// Your can use this inside the onCreate() method
private XWalkCookieManager mCookieManager;
mCookieManager = new XWalkCookieManager();
mCookieManager.setAcceptCookie(true);
mCookieManager.setAcceptFileSchemeCookies(true);
// Pass it to your request executor
httpRequestExecutor.setXWalkCookieManager(mCookieManager);
//You're now able to add your cookies to this manager rather than to your cookieManager
How we extract the cookies from the HttpResponse :
responseHeaders = response.getAllHeaders();
for (int i = 0; i < responseHeaders.length; i++)
{
Header header = responseHeaders[i];
if (header.getName().equalsIgnoreCase("set-cookie"))
{
mCookieManager.setCookie(request.getUrl(), header.getValue());
}
}
The implementation of XWalkCooikeManager is a little different with Android CookieManager.
You should add schemes(http|https) before cookie.getDomain().
This is because the implementation of CookieManager in Android WebView use WebAddress(url).toString(), which will add schemes (http|https) into the url.
As the explanation in CooieManagerAdapter:
WebAddress is a private API in the android framework and a "quirk" of the Classic WebView implementation that allowed embedders to be relaxed about what URLs they passed into the CookieManager, so we do the same normalisation before entering the chromium stack.

WebView unable to save cookie on Android 2.3.x

So I've been trying to get a WebView to work properly to authenticate a user session that is used in app. It works on all 4.0+ devices but when I try to use the same process on a 2.3.6 and 2.3.7 devices it throws this exception in the log:
com.myapp.WebActivity E/webkit﹕ parse cookie failed for: request_uri=xxxxxxxx; path=/; expires=Mon, 16-Jun-2014 00:00:00; domain=;
It doesn't crash the app but will not save this one cookie needed to properly authenticate the users session. I've looked into the Android Source code and it appears that when trying to save this specific cookie there is a RunTimeException that is happening. Here is the Android Source where the exception is thrown and caught. I'm not 100% sure where to look next since the cookies are saved properly on 4.0+ and it seems like a AOSP bug. Also, after the WebView loads the CookieManager doesn't have the cookie that it threw the exception on but has others.
So my real question is: Is there anyway to manually get a cookie returned from a WebView page load or can I get the cookie to be saved by the Android 2.3 WebView automatically somehow?
Thanks in advance.
Here is what I use to check and save a cookie that is picked up by a subsequent WebView. It works on Android 2.2 for sure, as well as Android 4.X.
Checking:
// see if the cookie is already set up
boolean cookieAlreadySetUp = false;
String cookie = cookieManager.getCookie(urlHost);
if ( cookie != null && cookie.length() > 0 ) {
String[] cookies = cookie.split(";");
for ( int i = 0; i < cookies.length; i++ ) {
String oneCookie = cookies[i];
if ( oneCookie.trim().equals(SharedData.COOKIE_STRING) ) {
cookieAlreadySetUp = true;
break;
}
}
}
Saving:
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(urlHost, myCookieString);
CookieSyncManager.getInstance().sync();
// give time for the cookie to become known since the save process is asynchronous to this thread
SystemClock.sleep(100);
Be aware of the asynchronous nature of the cookie manager, both for adding or removing a cookie, as well as testing its existence.

Get User Agent in my app which doesn't contain a webview

I can ask WebView.getWebSettings().getUserAgentString() to get the user
agent, but this doesn't work all that well for my app as I need to
instantiate a WebView first even though I don't need.
Is there another way to get to the User Agent without using a WebView.getSetting, because in my application, I don't need a webView?
Help me please
You either initialize a Webview and then destroy it, or just hardcode the user agent as a string (and replace at run-time language etc).
You can see how it's determined by looking at the source
http://www.google.com/codesearch/p?hl=en#uX1GffpyOZk/core/java/android/webkit/WebSettings.java&q=getCurrentUserAgent&sa=N&cd=1&ct=rc&l=370
According to the documentation, you can't get a WebSettings object without a WebView.
Do you need it to be exactly the one that the phone would send? If not, just pick up a standard Android User Agent (not build/version specific)
The information of user agent is obtained from the HTTP headers, which depends on what browser is used to initiate the WebView object. Therefore, it doesn't make sense if you only want to get the user agent string without creating a WebView.
A better way might be create a WebView and set its visibility to GONE. After getting the user agent string, destroy it.
From android Source code.
public static String getDefaultUserAgent() {
StringBuilder result = new StringBuilder(64);
result.append("Dalvik/");
result.append(System.getProperty("java.vm.version")); // such as 1.1.0
result.append(" (Linux; U; Android ");
String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
result.append(version.length() > 0 ? version : "1.0");
// add the model for the release build
if ("REL".equals(Build.VERSION.CODENAME)) {
String model = Build.MODEL;
if (model.length() > 0) {
result.append("; ");
result.append(model);
}
}
String id = Build.ID; // "MASTER" or "M4-rc20"
if (id.length() > 0) {
result.append(" Build/");
result.append(id);
}
result.append(")");
return result.toString();
}

WebView with Headers Connection Error

I am trying to open a Web view of a site (in Android) that needs token/Cookie in the headers for authentication.
I try to open the page using code below
HashMap<String,String> headers = new HashMap<String,String>();
headers.put("Cookie","MyToken");
MyWebView.loadUrl("https://myURL.com",headers);
I am hitting the onReceivedError with following values
errorCode: -6
*description: The connection to the server was unsuccessful.*
(PS: Since this site can be access from Intranet, using emulator I don't see this error the page loads correctly. Also HttpPost works fine with same token)
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,
That is not a valid cookie header. Try:
headers.put("Cookie", "foo=bar");

Categories

Resources