I'm using an Android Webview in Java to load my webpages on my node server.
My node server requires me to login. After that, it creates an httpOnly cookie with the access token and sends it back which I then store manually in Java on Android.
Something is causing my cookie to be either destroyed or lost, causing me to constantly have to relogin, but it's random. Sometimes it stays logged in, other times I'll resume the app and it'll switch to the login page.
The cookie is not expiring either. I've set it to expire 30 days. It's also working just fine on browsers. It's just..being deleted from my phone automatically at random times.
I'm manually saving and loading the cookie too so how could this be?
Should I only save it after the login page finished? Am I flushing it at incorrect times?
public class MainActivity extends AppCompatActivity {
private WebView webView;
private String websiteDomain = "https://10.0.4.12";
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize WebView
webView = findViewById(R.id.webView);
webView.setWebContentsDebuggingEnabled(true);
WebSettings webSettings = webView.getSettings();
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
if (Build.VERSION.SDK_INT >= 21) {
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
} else {
CookieManager.getInstance().setAcceptCookie(true);
}
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
loadCookiesFromSharedPreferences();
// Set WebViewClient to handle redirects and other events
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError error) {
handler.proceed(); // Ignore SSL certificate errors
}
@Override
public void onPageFinished(WebView view, String url) {
saveCookiesToSharedPreferences(url);
printCookies(url);
}
});
// When we first start the webview, load the route that takes us to the last page we were on previously
webView.loadUrl(websiteDomain + "/auth/last");
}
// Save cookie retrieved from webview manually to shared preferences
private void saveCookiesToSharedPreferences(String url) {
CookieManager cookieManager = CookieManager.getInstance();
String cookies = cookieManager.getCookie(url);
// Save cookies to shared preferences
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("saved_cookies", cookies);
editor.apply();
}
// Load cookie retrieved from webview manually from shared preferences into the cookie manager
private void loadCookiesFromSharedPreferences() {
// Load cookies from shared preferences
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
String cookies = preferences.getString("saved_cookies", "");
// Set cookies in CookieManager
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setCookie(websiteDomain, cookies);
}
// Print the cookie for debugging
private void printCookies(String url) {
Log.d("COOKIE", "Has cookies: " + String.valueOf(CookieManager.getInstance().hasCookies()) );
String currentCookie = CookieManager.getInstance().getCookie(url);
Log.d("COOKIE", "Current cookie in webView:" + currentCookie);
}
@Override
protected void onPause() {
super.onPause();
CookieManager.getInstance().flush();
webView.onPause();
}
@Override
protected void onResume() {
super.onResume();
loadCookiesFromSharedPreferences();
webView.onResume();
}
}
EDIT 2024-03-05
We must persist cookies manually somerhere. Cookie manager is not properly work when open webview again...
Call function like this before load login page:
This code will load cookies from local storage and set to page and flush it to CookieManager for later use (until app is killed).
And persist cookies (before exit app - I still keep code in onPageLoaded to be sure)
Old answer
Have same issue for long time (4 years) without properly fix :(. I call
CookieManager.getInstance().flush()after every single page load finishand in
onPuaseon fragment as well, but nothing help.We have reproducible use case:
When user don't kill app and use back button to close it, everything work as expected.
It looks, that flush in
onPauseis killed before it can store it. But why it didn't work as well, when we call it after every page load? No idea... it have bunch of time to persist cookies.