How to persist webview cookies between app executions? - android

It is possible to achieve this currently in Android? I only can find deprecated questions about old methods (CookieSynchManager) which not seems to work for this actually.
It is possible to achieve it? I can't find anything also on the Android Developers' Guide.

Having the same problem...I solved reading the doc here:
https://developer.android.com/reference/android/webkit/CookieSyncManager
For future readers: to force the Cookie sync process you can manually call the flush() method of CookieManager
I personally put in webview the following code:
public class MyWebViewClient extends WebViewClient {
public void onPageFinished(WebView view, String url) {
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().acceptCookie();
CookieManager.getInstance().flush();
}
}

Since CookieSynchManager is deprecated, CookieManager.getInstance() is the CookieManager instance for your entire application. Hence, you enable it by
CookieManager.getInstance().setAcceptCookie(true)
setAcceptCookie(boolean accept);
Sets whether the application's WebView instances should send and
accept cookies.
https://developer.android.com/reference/android/webkit/CookieManager.html

Related

Android Webview onReceivedTitle not called on page reload

I've been trying to inject some js into a webview in my app. Have been using
onReceivedTitle method of WebChromeClient since I want to execute the js while the page is loading.
This has been working until now. But recently, I observed that onReceivedTitle is not called we reload the webpage, similar to window.location.reload.
Firstly, I can't understand why it shouldn't be called. Or it should be and it's a bug?
Secondly, now that we know it's not called, where else can I inject by js?
Thanks.
Apparently, this is not considered an Android bug, but rather a Chrome or Chromium-based WebView bug. It should be reported to http://crbug.com/.
I'll suggest you to try a workaround with custom WebViewClient:
You'll have to use a custom WebViewClient to get this done. You will override the onPageFinished() method so when a new page finishes loading you can set the webview to the appropriate title.
Below is a sample implementation of the above:
WebView mWebView = (WebView) findViewById(R.id.mwebview);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
ExperimentingActivity.this.setTitle(view.getTitle());
}
});
This answer here will prove to be useful:https://stackoverflow.com/a/8193479/9080948
Seems like this is a bug in chromium. I worked around this by injecting my scripts on onPageFinished method of WebviewClient.

Listen for URL fragment id change in WebView

It seems that the WebViewClient methods such as shouldInterceptRequest(), onPageStarted(), and shouldOverrideUrlLoading() only listen for URL changes that cause the WebView to load a new page. Is there a way to detect URL changes for fragment IDs, i.e. index.html#fragment_id, on a WebView?
I know that this is a really old question but i found out a solution that isn't available anywhere in Stack Overflow. jpetitto's answer works but it messes up javascript if we use hash change for routing or other such features.
I found out that by overriding the method doUpdateVisitedHistory in WebViewClient we can catch url's on hash change. Do see below snippet for example.
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
super.doUpdateVisitedHistory(view, url, isReload);
// somecode to run on hash change.
}
}
Note: this method is fired on hash change and url change.
As mitvenkatesan described in his comment to the question, this can be achieved by overriding the window.onhashchange() event of the page inside the WebView.
It turns out that this solution has already been addressed in another question.

How to achieve multi-login for webviews in Android?

I want to make an app that allows users to log-in multiple accounts of same site using different webview.
For example, I have 2 WebView.
Each WebView will load the same site such as gmail.com.
And user can log-in using separate account in separate WebView.
But the problem I am facing is that the 2 WebView always log-in to same account.
I've googled a lot, and here are some related titles,
Facebook MultiLogin in Android Webview
Using WebView for multi-page login to website and fetch data
Multiple Log-Ins on Separate WebViews? (Android)
but still no acceptable answer is found.
Would it be possible in Android using WebView?
How can I achieve what I want?
The tricky part is android.webkit.CookieManager, used by WebView to keep cookies, is designed to be a singleton. This means there'll be only one CookieManager instance per Java/Dalvik process, and your multi WebView instances inside the same process share a same set of cookies.
Like #ToYonos proposed, you may try overriding certain hooks to work around this, but I don't think it will 100% work...Also think about android.webkit.WebStorage: it's another singleton!
That said, this might work a bit more reliably: duplicate your top level WebView activity in manifest and assign them to run in different processes:
<activity
android:name=".WebViewActivity" />
<activity
android:name=".WebView1Activity"
android:process=":web1" />
<activity
android:name=".WebView2Activity"
android:process=":web2" />
...
So that you'll have isolated processes and different CookieManager/WebStorage instances.
But be warned: different WebStorage instances still writes to same path(s) in your app data folder! This may be worked around by calling webView.getSettings().setDatabasePath() to use different db paths for different processes, but this API has been deprecated in API level 19 (KitKat). Well as long as the web page you're visiting doesn't use HTML5 local storage this should be fine...
I think that you'll have to implement your own system. You could try something like that :
private static final String DOMAIN = "http://cookiedomain.com";
private final Map<WebView, String> cookiesMap = new HashMap<WebView, String>();
// [...]
WebView w = new WebView(this);
// Loading url and stuff
w.setWebViewClient(new WebViewClient()
{
public void onLoadResource (WebView view, String url)
{
// If cookies have already been stored for this WebView
if (cookiesMap.get(view) != null)
{
CookieManager.getInstance().removeAllCookie();
CookieManager.getInstance().setCookie(DOMAIN, cookiesMap.get(view));
}
}
public void onPageFinished(WebView view, String url)
{
// Check if the url matches the after-login page or whatever you want
boolean condition = ...;
if(condition)
{
// Getting new cookies
String cookies = CookieManager.getInstance().getCookie(DOMAIN);
cookiesMap.put(view, cookies);
}
}
});
// Do the same for the 2nd WebView
This is a simple example, to be improved, but it could be a good start for a sustainable solution.
Limits :
It will only work if each WebView does not make request at the same time as others. Otherwise, it will surely tangle cookies.
This will work for one domain only

Button in a webview without Javascript

I have an android application that loads a webview from a server. I do not have the server code so I cannot change anything in Javascript. I want to figure out when a button is being clicked in a webview and what is the label in the button. I do not know the Id, I just want to get the label.
I tried searching for this but could not find an answer. I found solutions where you can work in the javascript but in my case I cannot.
This suggestion may help to find useful information that could lead to determination of your button label. Override shouldOverrideUrlLoading(), shouldInterceptRequest() and/or onLoadResource() for the WebViewClient so you can get at the URL of any redirects.
Example:
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Try to learn something useful from the 'url' here.
// Continue as normal, loading the 'url' within this WebView.
view.loadUrl(url);
return false; // Allow the WebView to handle the request.
}
// Optional: Add similar for "shouldInterceptRequest()" and/or "onLoadResource()".
});
Note: Overriding shouldOverrideUrlLoading() as above is the standard way to keep redirects within the same WebView rather than redirecting to the default browser application.
You might really want to check this page:
Building Web Apps in WebView (Google API Guides)
Specifically, it seems that addJavascriptInterface might be what you are looking for:
addJavascriptInterface(Object object, String name)
It allows you to execute your Java code from javascript and, paired with the ability to insert code in a page, it's an incredibly powerful tool for granting you a high level of coupling between your Activity and your page.
I think that at this point you will already know what to do, but I'll sketch a possible course of action anyway:
create a javascript interface with the callbacks you want executed in your activity when a button is pressed
as soon as your page loads, install the code to call your javascript interface in each button (or link) by injection
Hope this helps

PictureListener and onNewPicture() are deprecated - Alternatives?

The Android Developers reference says that both the WebView.PictureListener interface and its onNewPicture() method are deprecated.
Fine, but the need to know when WebView renders a picture is still there. Is there an alternative way to accomplishing this?
Ok after careful review of the APIs, it seems this cannot be done without using PictureListener. Obviously the person who deprecated this feature didn't provide an alternative.
I suggest you write a bug report http://code.google.com/p/android/issues and ask people here to star it.
Emmanuel
I submitted this Android issue to track the replacement for the PictureListener and onNewPicture() callback.
http://code.google.com/p/android/issues/detail?id=38646
Please star as necessary.
the closest thing you have is onPageFinished
wv.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
but it doesn't always trigger after the content is finished being drawn, hence not so much of a replacement. I suggest sticking to onNewPicture even if it is deprecated. after all, it still works.
Until there is an official replacement API for this functionality you can just change the
android:targetSdkVersion
in AndroidManifest.xml to anything <= 13.

Categories

Resources