Async Task, Webview, Cookies - Android - android

I have a "native" login screen which sets a static cookie and then this activity gets the cookie from LoginWebView.
I'm doing this in an async task.
The problem now is that the async task contains 3 very ugly hacks which makes the code very unreliable (the hacks are marked out in the code below).
The question is, do you have any idea on how to get rid of one or more of these ugly hacks?
Hack nr 1 -
This is taken from an example that someone posted here on stack overflow, the cookie needs to wait a bit before it actually works and loads in the webview, I have no idea why but without it it just does not work. This is not the biggest problem though.
Hack nr 2 -
I don't know why but if I want to be able to load another page I have to first load the page that I got the cookie from. When this is loaded I simply wait a small bit and then load another url. Do anyone have any idea why?
If I don't do this the webview recognizes that the cookie is there but won't finish loading any pages at all, it just stucks on loading and never finishes.
Hack nr 3 -
It's just to remedy hack nr 2.
private class WebViewTask extends AsyncTask<Void, Void, Boolean> {
String cookieString1;
CookieManager cookieManager;
#Override
protected void onPreExecute() {
Cookie sessionCookie = LoginWebView.cookie1;
CookieSyncManager.createInstance(WebViewActivity.this);
cookieManager = CookieManager.getInstance();
cookieString1 = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; " +
"domain=" + sessionCookie.getDomain();
CookieSyncManager.getInstance();
//cookieManager.removeSessionCookie();
super.onPreExecute();
}
protected Boolean doInBackground(Void... param) {
// HACK NR.1
SystemClock.sleep(600);
return false;
}
#Override
protected void onPostExecute(Boolean result) {
Log.v(TAG, "COOKIE SYNC 1: " + cookieString1);
Log.v(TAG, "COOKIE SYNC 1: " + domain);
cookieManager.setCookie(domain, cookieString1);
CookieSyncManager.getInstance().sync();
WebSettings webSettings = webView.getSettings();
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "Loading...");
view.loadUrl(url);
return true;
}
});
//HACK NR 2
webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
webView.loadUrl(domain);
Log.v(TAG, "PROGRESS " + webView.getProgress());
button1.setChecked(true);
if(webView.getProgress() == 100) {
//HACK NR. 3
SystemClock.sleep(80);
webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);
clickButtonOne();
}
}
}

Could you perhaps try a connecting thread solution I have proposed in
android session management
A login activity could utilise that.
And as for the WebView, you can pass the cookie with (sCookie is the static cookie string already set by the login activity):
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
String cookieString = sCookie+"; domain="+sDOMAIN;
cookieManager.setCookie(sDOMAIN, cookieString);
CookieSyncManager.getInstance().sync();

Related

How to set cookie in android WebView client

I want to call one specific url via WebView. The page can only be called after user already logged in. I use AsyncHttpClient library to perform login call. Once after successfully logged in , loading url via WebView doesn't seem recognise the proper headers esp cookie. My suspect is that cookies are not sync correctly between HttpClient and WebView's HttpClient . Any idea why ? . Here is how i use WebView
final WebView webView = (WebView) content.findViewById(R.id.web_travel_advisory);
String url = "http://mydomainurl.com/get_data_after_login";
webView.setWebViewClient(new WebViewClient());
CookieSyncManager.createInstance(getActivity());
CookieSyncManager.getInstance().startSync();
CookieManager.getInstance().setAcceptCookie(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(url);
Appreciate ur help .
Ohh after several hours, i finally figured it out to get it worked. Firstly CookieSyncManager is deprecated on later version of android since api 21 according to doc. So decided not to use it anymore. Secondly CookieManager is used to store cookie for WebView.
Final code
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
List<Cookie> cookies = WSHelper.cookieStore.getCookies();
cookieManager.removeAllCookie();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().contains("session")){
String cookieString = cookie.getName() + "=" + cookie.getValue() + "; Domain=" + cookie.getDomain();
cookieManager.setCookie(cookie.getDomain(), cookieString);
Log.d("CookieUrl",cookieString + " ");
}
}
}
webView.loadUrl(url);
The key changes to solution is: use cookie.getDomain() instead of explicit domain.
cookieManager.setCookie(cookie.getDomain(), cookieString);
Try this code, after few changes works for me:
public class WebViewActivity extends Activity{
private SharedPreferences mPreferences;
String token="";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webviewpage);
mPreferences = getSharedPreferences("CurrentUser", MODE_PRIVATE);
}
public void LaunchWebView(View view) {
WebView myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setSaveFormData(false);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
CookieManager.getInstance().setAcceptThirdPartyCookies(myWebView, true);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String token2= mPreferences.getString("auth_token","");
HashMap<String, String> map = new HashMap<String, String>();
map.put("x-auth-token", token);
myWebView.getSettings().setAppCacheEnabled(true);
myWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view,String url) {
view.loadUrl(url);
return true;
}
});
myWebView.loadUrl("YOUR_URL", map);
}
}
My problem was slightly different, but answer from #Tixeon gave me the key to solve it. I was composing my Cookie and adding it to the WebView request, but I discovered that Android was overriding my Cookie and sending its own Cookie.
So first of all, I had to remove all cookies from the array, then compose my own Cookie. This is the sample code:
// Note that my project has minSdkVersion 21, so I can directly use methods only available in Lollipop
private fun loadUrlInWebView(url: String) {
webView.settings.apply {
builtInZoomControls = false
javaScriptEnabled = true
useWideViewPort = true
loadWithOverviewMode = true
setSupportMultipleWindows(false)
}
CookieManager.getInstance().apply {
setAcceptThirdPartyCookies(webView, true) // My minSdkVersion is 21
removeAllCookies { value ->
Log.d("Cookies", "Removed all cookies from CookieManager")
}
}
webView.apply {
isVerticalScrollBarEnabled = true
isHorizontalScrollBarEnabled = true
loadUrl(
url,
mutableMapOf(
"Cookie" to "ThisIsMyCookieWithMyValues",
"Accept" to "*/*",
"Accept-Encoding" to "gzip, deflate",
"Cache-Control" to "no-cache",
"Content-type" to "application/x-www-form-urlencoded"
)
)
}
}
Now the request contains my Cookie and not the default one provided by Android, and my session in WebView is working. Hope this helps someone else
Latest way to set cookies using cookieManager
val siteCookies = CookieManager.getInstance().getCookie(“https://www.dummyurl.com”)
cookieManager.removeSessionCookies {
if (! siteCookies.isNullOrEmpty()) {
val cookie = siteCookies.split("; ".toRegex())
.dropLastWhile { it.isEmpty() } as ArrayList<String>
val iterator = cookie.iterator()
while (iterator.hasNext()) {
val cookie = iterator.next()
if (cookie.isNullOrEmpty()) continue
cookieManager.setCookie(“https://www.dummyurl.com”, cookie)
}
}
}
posting this if this helps someone.

WebView not posting/loading correctly

I have this piece of WebView code which should login to a website and then load a certain page of that website.
webView = (WebView) findViewById(R.id.recording_web_view);
Bundle b = getIntent().getExtras();
String filename = b.getString("filename");
SettingsManager setman = SettingsManager.getInstance(getBaseContext());
//Login to webinterface before we can watch the recording
String postData = "username=" + setman.getUserName() + "&password=" + setman.getPassword();
//This is the section of code that fixes redirects to external apps
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
return false;
}
});
//Post login to get session
webView.postUrl("http://" + setman.getIp() + "/login", EncodingUtils.getBytes(postData, "BASE64"));
//Load actual recording
webView.loadUrl("http://" + setman.getIp() + "/movies/" + filename);
And when I run this I just get the login page, and the server says it received no postdata. However, when I remove the loadUrl line it does receive the login data and load the page after the login.
Can anyone tell me what I am doing wrong? Thanks
Try use in WebViewClient:
#Override
public void onPageFinished( WebView view, String url)
{
view.loadUrl( "http://" + setman.getIp() + "/movies/" + filename);
}
Also you can check error of request:
#Override
public void onReceivedError( WebView view, int errorCode, String description, String failingUrl)
Enable the the JavaScript
webView.getSettings().setJavaScriptEnabled(
true);

Strange Cookie Issue in Android WebView?

I have native application in Andriod and Iphone with ASP.NET as a back-end. I am sending request to my ASP.NET server API by appending Session_Id cookie using HttpClient classes which works great. But I also need to send the same session in WebView. The problem is that some times WebView send the Session_Id cookie and sometimes doesn't. It strange for me. I am not able to find why sometimes webview send the cookie and sometimes doesn't. Here is my code,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myapp = ((....) getApplicationContext());
setTimeout(true);
try {
getActionBarHelper().setupHomeActivity();
} catch (Exception e) {
e.printStackTrace();
}
cm = (ConnectivityManager) this.getSystemService(Activity.CONNECTIVITY_SERVICE);
webView = new CustomWebView(this, this);
webView.getWebView().addJavascriptInterface(new MyJavaScriptInterface(), "android");
getTimeDiff();
if(MyApplication.INSTANCE.isLoggedin()){
Cookie sessionCookie = MyApplication.INSTANCE.getCookie();
List<Cookie> cookies = MyApplication.INSTANCE.getClient().getCookieStore().getCookies();
for (int i = 0; i < cookies.size(); i++) {
sessionCookie = cookies.get(i);
}
try{
if(sessionCookie!=null){
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
if (sessionCookie != null) {
cookieManager.removeSessionCookie();
String cookieString = sessionCookie.getName() + "="
+ sessionCookie.getValue() + "; domain="
+ sessionCookie.getDomain();
if (MyApplication.isDebug())
cookieManager.setCookie(sessionCookie.getDomain(),(sessionCookie.getName() + "=" + sessionCookie.getValue()));
CookieSyncManager.getInstance().sync();
}else{
if (MyApplication.isDebug())
Log.d("WebView", " Cookie is null: " );
}
}else{
if (MyApplication.isDebug())
Log.d("WebView", " Cookie is null: " );
}
}catch (Exception e) {
e.printStackTrace();
}
Log.e("WenView", "============================ ");
}
}
Your for loop appears to only include the single line that retrieves the cookie... so your logic that's setting the cookie below only gets called once, with whatever the last cookie happened to be. Since the cookies aren't ordered in the list, this probably explains why sometimes it works and sometimes it doesn't; it's working when your cookie is last, and failing otherwise.
The answer is to just expand your for loop to include ALL the logic underneath as well. Your copying code looks fine, and I expect it is if you can get it to work sometimes.

Android WebView not extracting all cookies on different devices

I'm trying to extract the value of a cookie from a webpage after logging in. I am using a cookie helper class and the android.webkit.CookieManager to retreive cookies once the webpage has finished loading i.e. onPageFinished()
This all works fine and I can see the cookie names and values on my test devices, Galaxy S2 (4.0.4), Galaxy S3 (4.1.1) and a HTC Explorer (2.3). However, the same code is not functioning on a Sony Xperia (2.3)?
I have logged out the url to make sure I'm working from the correct page and for some reason I only get 3 cookies from the site on the Xperia, where I should be getting 7 (roughly).
Below is a simplified version of the code I'm running. Appreciate any responses. Thanks in advance!
WebViewActivity
#Override
public void onPageFinished(WebView view, String url) {
if(!cookieCreated){
CookieHelper cookieHelper = new CookieHelper(getApplicationContext());
if(cookieHelper.processCookie(url)){
cookieCreated = true;
}
}
}
CookieHelper
public CookieHelper(Context cont){
this.cookieManager = CookieManager.getInstance();
}
public void processCookie(String url){
if(manager.getCookie(url).contains("cookie_name_required")){
Log.d(TAG, "Got cookie");
}
else{
Log.d(TAG, "No cookie");
}
}
public static void setCookies(Context context) {
//gets all cookies from the HttpClient's cookie jar
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
if (! cookies.isEmpty()) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
//sync all the cookies in the httpclient with the webview by generating cookie string
for (Cookie cookie : cookies) {
Cookie sessionInfo = cookie;
String cookieString = sessionInfo.getName() + "=" + sessionInfo.getValue() + "; domain=" + sessionInfo.getDomain();
cookieManager.setCookie("zoboon.com", cookieString);
CookieSyncManager.getInstance().sync();
}
} else {
Log.i("httpclient","has no cookies");
}
}

Getting Facebook login OAuth to work with Dailymile in an Android app

I've been working on a Android app that posts workouts to Dailymile.com.
To authorise the app you need to log into dailymile via the web to retrieve an OAUth 2.0 token.
I do this by embedding a Android WebViewActivity
This all works fine if the user logs in to dailymile directly.
If the user logs in using the "Login with Facebook" button then there are problems.
The user is asked for their facebook username
& password
Then to enter a name for the device (if not used before)
At this point the browser redirects to a blank page
I'm using the following code to set up the WebView.
WebView webView = new WebView(this);
final Activity activity = this;
getWindow().setFeatureInt( Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgent(0);
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if (progress == 100) {
activity.setTitle(R.string.app_name);
}
}
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d("Tracks2Miles", consoleMessage.message() + " -- From line "
+ consoleMessage.lineNumber() + " of "
+ consoleMessage.sourceId() );
return true;
}
#Override
public void onConsoleMessage(String message, int lineNumber,
String sourceID) {
Log.d("Tracks2Miles", message + " -- From line "
+ lineNumber + " of "
+ sourceID);
}
});
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, url);
if (url.startsWith("dm://")) {
String summary = "<html><body>" + getResources().getString(R.string.auth_message) + "</body></html>";
view.loadData(summary, "text/html", "utf-8");
String token = url.substring(url.lastIndexOf("=")+1);
Log.i(TAG,token);
User user = Utilities.getAccountDetails(token, AuthenticatorActivity.this, handler);
if (user != null) {
user.setToken(token);
finishLogin(user);
}
return false;
}
view.loadUrl(url);
return true;
}
});
setContentView(webView);
webView.loadUrl(AUTH_URL);
The blank page seams to be the point where facebook would ask the user to actually grant permission to Dailymile.
Anybody got any ideas what I'm missing?
Having spent some more time looking into this last night it turns out it is because dailymile.com are returning a page with the wrong host/certificate pair.
After the user logs in Facebook is redirecting to a page hosted on www.dailymile.com and the certificate being presented is for api.dailymile.com.
I found the following blog post explains how to get the Android WebView to ignore the error.
http://damianflannery.wordpress.com/2010/09/28/android-webview-with-https-loadurl-shows-blankempty-page/

Categories

Resources