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.
Related
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
Would like to ask for some advice on what's best way to implement on enabling and disabling the web view on Android?
I have this app wherein it can open urls within (by using web views) which then popups up and covers 80% of the UI, when the user navigates to another page of the app it should hide/close the web view but can be re-opened again when needed.
Here's a snippet of the code
private WebViewInterface webViewInterface = new WebViewInterface() {
#Override
public void onOpenURL(String url) {
navBrowserWV.setVisibility(View.VISIBLE);
navBrowserWV.getSettings().setJavaScriptEnabled(true);
navBrowserWV.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){
handler.proceed();
}
});
navBrowserWV.loadUrl(url);
}
};
then this is how I close it
private void closeWebView() {
Log.d(LOGTAG, "closing webview...");
// Destroy WebView if it exists
if (this.navBrowserWV != null) {
this.navBrowserWV.stopLoading();
this.navBrowserWV.loadUrl("about:blank");
this.navBrowserWV.clearHistory();
this.navBrowserWV.clearCache(true);
this.navBrowserWV.pauseTimers();
this.navBrowserWV.setVisibility(View.GONE);
}
}
The problem with this implementation is that it displays the page properly at first but when I close it and then open the web view again with a url, it does not load the page anymore just a white background (no errors on the logger btw).
Would like to ask for help on how to resolve this one. Thanks
Finally, after a long time of digging up answers on the internet I found this old post regarding killing Android webview [link].
There's no real way to kill the WebView (it will always run in your process and you can't do anything about it ATM). So you only have to tell the WebView to load a bogus page, for me I did:
this.navBrowserWV.loadUrl("about:blank");
And it works now!
Quote from the website
4.1 .getSettings().setJavaScriptEnabled() Inhalt
Well, you would think that disabling JavaScript in the WebView’s settings would have an instant effect, in short: it does not. Only after reloading the page would there be no javascript any more, and this is not nice by design, since the page is still more or less well rendered.
4.2 .stopLoading() Inhalt
Since XHR „loads“ something from another server, you might think that calling „webview.stopLoading()“ would have an effect. In short: it does not. Works only on ressources contained within the HTML-file. Pity, is it not… Well, maybe not, since there is no „startLoading()“ method to resume XHR after resuming the activity anyway.
4.3 .destroy() Inhalt
As a last resort one might think about „destroy()“ing that thing, and true enough, the WebView itself is not accessible after that. Its threads however continue to exist as zombies somewhere in the vast RAM space and also continue to send XHR requests…
4.4 .pauseTimers() / resumeTimers() Inhalt
In short: Nope, does not work. I even don’t know what these methods are good for if not for controlling JavaScript timers. There aren’t any in plain HTML, AFAIK.
Update: When it comes to timers only, these functions seem to work on 2.3.5 and upwards, however, when there is no timer active at the time of calling the function, all in vain. With my use case: When pausing the app while there is an XHR active (instead of the running timer that schedules the next XHR call), nothing happens and the next timer continues unhindered.
I hope this will help someone who has the same problem as mine.
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
I struggled so much to have a fixed background inside the webview.
First I tried this using CSS, But I found out background-attachment:fixed doesn't work in android, at least till 4 (don't know about newer versions).
The other option was to have a scrollable DIV which android doesn't support either.
I didn't try iscroll for this problem, but earlier used it somewhere else and wasn't satisfied. I don't know if it's possible with an iframe.
The other option was to set the background using android. I read much about this and tried many thing, one for example was using a container layout with a background and setting webview background to transparent.
It worked in 2.2 with a delay, in 4 it didn't work at all.
I'm so tired wasting a lot of time to achieve this small thing.
Do you have any other idea to implement this?
I finally found a solution:
This is how you do it:
First make your project base on 11, but in AndroidManifest set minSdkVersion to 8
wv.setBackgroundColor(0x00000000);
if (Build.VERSION.SDK_INT >= 11) wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
this.wv.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
wv.setBackgroundColor(0x00000000);
if (Build.VERSION.SDK_INT >= 11) wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
});
For safety put this in your style:
BODY, HTML {background: transparent}
worked for me on 2.2 and 4
In my application I need to show a progress dialog when downloading and loading content to WebView. I know about the onPageStarted and onPageFinished methods, it works, however, there is a few seconds of delay between the onPageFinished call and the time the content is actually visible on the screen.
Is there a way to dismiss the progress dialog when the content is really visible, not only loaded?
You can do this by adding a PictureListener to your webview. Note that this is deprecated, but as far as I know there is no actual replacement provided by Android at this time.
From API level 23 you can use onPageCommitVisible.
#Override
public void onPageCommitVisible(WebView view, String url) {
super.onPageCommitVisible(view, url);
// There you go.
}
Unfortunately I have not found any way to use it on lower API levels.