PRDeving PRDeving - 6 months ago 59
HTTP Question

Set-Cookie header in Ajax response doesn't work with android webView

I've been reading answers, questions, forums and blogs for 2 days now but can't fix my issue.

I've an AngularJS webApp working in a Native (SDK) Android App with a WebView.

Everything seems to work but when my application calls services that responds with the "Set-Cookie" header those cookies are not setted in the webview and, of course are neither sent in the next calls, so my app explodes.

The app works flawlessly in browser and cordova and "document.cookie" returns an empty string, so i know this is where it fails.

My webview is initialized like this:

public class Main extends AppCompatActivity {
...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new mWebViewClient());

webview.getSettings().setAppCacheEnabled(true);
webview.getSettings().setDomStorageEnabled(true);
webview.getSettings().setSavePassword(true);
webview.getSettings().setAllowFileAccessFromFileURLs(true);
webview.getSettings().setAllowContentAccess(true);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setUserAgentString(...);
webview.loadUrl("file:///android_asset/www/index.html");

javascriptAPI = new JavascriptAPI(this);
webview.addJavascriptInterface(javascriptAPI, "jsAPI");
...
}
...
}


I've tried also with chunks of code from here and there like:

CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().run();
CookieManager.getInstance().setAcceptCookie(true);


But it doesn't work neither.

My app is calling to some services that use redirect, so fetching the cookies from JS and setting them is not an option, i need the webview to work like a browser would.

This is my first SDK Android App and i'm not sure at all what info could be relevant to answer the question (manifest, jsAPI, etc) so don't hessitate to say and i'll post whatever else is needed

SOLVED

Thank you @Mark, this fixed my code:

(inside Activity onCreate)

...
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this);
}
^^^^^^^
THIS


WebView webview = (WebView) findViewById(R.id.webview);

CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().run();
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().setAcceptFileSchemeCookies(true); <- THIS
CookieManager.getInstance().setAcceptThirdPartyCookies(webview, true); <- THIS

webview.setWebViewClient(new mWebViewClient());
webview.getSettings().setAppCacheEnabled(true);
...

Answer Source

There are three acceptCookie methods you need to worry about, and different behavior across several versions of Android to take into consideration.

1) I noticed your initial url is a file:// url. You may need to call CookieManager.getInstance().setAcceptFileSchemeCookies(true);.

2) In Android Lollipop and greater, you may need to call CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);

3) For Android versions < Lollipop, if you want cookies to be persisted (e.g., survive rotation), you have to take some steps to manually manage syncing.

First, to ensure that CookieSyncManager is initialized during application startup by adding it your appplication class' onCreate(), or extend this one.

public class CookieApplication extends Application {
   @Override
   public void onCreate() {
      super.onCreate();
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
         CookieSyncManager.createInstance(this);
      }
   }
}

Second, you need to setup syncing for pre-lollipop devices, and finally to enable cookies. Here's an example activity that you could extend that sets up all the syncing for pre-Lollipop devices, and provides an enablesCookies(webView) that should turn on all cookie types regardless of Android version (be advised there are security considerations to be made when calling these methods!). Note that all of the CookieManager.getInstance().set*Cookie*() methods must be called after the webView is initialized.

public class AppCompatCookieActivity extends AppCompatActivity {

   @Override
   public void onResume() {
      super.onResume();
      // start cookie syncing for pre-lollipop devices
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
         CookieSyncManager.getInstance().startSync();
      }
   }

   @Override
   public void onPause() {
      // stop cookie syncing for pre-lollipop devices
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
         CookieSyncManager.getInstance().sync();
      }
      super.onPause();
   }

   public final void enableCookies(WebView webView) {
      // enable javascript (has security implications!)
      webView.getSettings().setJavaScriptEnabled(true);

      // enable cookies.
      CookieManager.getInstance().setAcceptCookie(true);

      // enable fileScheme cookies (has security implications!)
      // it is recommended to comment this out should you find it not necessary
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
         CookieManager.getInstance().setAcceptFileSchemeCookies(true);
      }

      // enable third party cookies
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
      }
   }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download