Android Webview : detecting when page has rendered - android

I am writing a highbred Android app that uses a lot of webviews. The problem is that the onPageFinished event for a webview is fired when a page is loaded but may not be rendered yet.
I believe there was a onNewPicture but has been removed since version 12.
Has anyone come across the same issue, my spinner basically disappears about 3-4 seconds before the page is actually rendered.

Rendering of a WebView can take a long time for long documents, and indeed onNewPicture has been deprecated since API 12 (Honeycomb 3.1) and returns a null picture since API level 18 (Jellybean 4.3).
I have tested for API level 17 (JB 4.2), and it still works fine. Probably works fine in API 18 too if you don't need the actual Picture details.
Please this issue on the issue tracker so we can get a non-deprecated replacement.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
PictureListener pictureListener = new PictureListener() {
#Override
#Deprecated
public void onNewPicture(WebView view, Picture picture) {
Log.i(TAG, "Picture changed!");
}
};
webView.setPictureListener(pictureListener);
}

Related

WebView findall doesen't work with android api 15

I'm using the following code to find and highlight text in a webView:
int API = android.os.Build.VERSION.SDK_INT;
if(API < 16) {
wv.findAll(findBox.getText().toString());
} else {
wv.findAllAsync(findBox.getText().toString());
}
However, it fails on api 15 only. It finds the word but doesen't highlight it. Do you have a solution?
This is a known problem without a solution that I know of. This occurs on the following:
Platform Version API Level VERSION_CODE
Android 4.0.3, 4.0.4 15 ICE_CREAM_SANDWICH_MR1
This problem is discussed: Here and Here.

Setting a button background resource with a .png from internal storage

I have a button that I want to set the background of using a png file from internal storage. For android api 16 and up, this works fine:
filePath = getActivity().getFileStreamPath(colorCodes.get(i-1));
temp.setBackground(Drawable.createFromPath(filePath.toString()));
When running on an android tablet with 4.0.4, this part crashes the app with a nosuchmethod error (setBackground). After a little research, I see that setBackground is only available for api 16+. After looking around on SO and a few other places, it looks like I need to use setBackgroundDrawable (deprecated) or setBackgroundResource. I tried this:
filePath = getActivity().getFileStreamPath(colorCodes.get(i-1));
if (android.os.Build.VERSION.SDK_INT < 16) {
temp.setBackgroundDrawable(Drawable.createFromPath(filePath.toString()));
} else {
temp.setBackground(Drawable.createFromPath(filePath.toString()));
}
When logging it out, it shows that setBackgroundDrawable is running and not setBackground, but I get the same nosuchmethod error (setBackground).
The other option is setBackgroundResource, but it accepts an int and not a drawable. Can I convert from drawable to int for this purpose?
What can I do here to set the background of the button to a file in internal storage for APIs < 16?
Thanks.
***EDIT - ok, this is working. just missed a little part elsewhere in the code that had the same problem. However, is using a deprecated method really the only way?
Deprecation is a status applied to a computer software feature,
characteristic, or practice indicating it should be avoided, typically
because of it being superseded. The term is also sometimes used for a
feature, design, or practice that is permitted but no longer
recommended in other areas, such as hardware design or compliance to
building codes. (source link)
Now we can answer your question.
Before API level 16 there is a method named setBackgroundDrawable. After API Level 16 google decided to write a new method setBackground for same purpose and recommend us to use new method. (Reason of this may be found by googling.)
You can use setBackgroundDrawable method for all api levels. There aren't any constraint for this. But using new method setBackground is recommended after API Level 16.
But you can only use setBackground method for devices which is running on API Level 16 or higher. So if you only implement setBackground method in your code, you are going to get MethodNotFoundException for devices which run below API Level 16.
To sum up; it is a best practice(for me it is a must) to use new methods then deprecated ones with supportted api version check such as;
if (android.os.Build.VERSION.SDK_INT < 16) {
temp.setBackgroundDrawable(Drawable.createFromPath(filePath.toString()));
} else {
temp.setBackground(Drawable.createFromPath(filePath.toString()));
}
I am not quite sure whether it is the only way to achieve this but in my opinion it is the correct one. Because the annotation #Deprecated defines the method to be superseded (in most cases) it automatically implies you can (I would even say should) use it to address older versions which are the targeted versions of this method.

Android webview fixed background

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

Conditional compiling in Android?

Is there any kind of conditional compiling for Android?
I had to make my project for Android 3 (API 11) just because ExifInterface has almost no useful attributes in Android 2.3 (API 10), despite the fact that it appeared in API 5 (!!??). I don't want to restrict my app to ICS users.
Thanks!
You can check dynamically the current API version of the device and do different stuff depending on that:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
}
But be careful that if you need to instantiate classes that are not available for all APIs then you should do it in a runnable or in a separate wrapper class, e.g:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
new Runnable() {
new AmazingClassAvailableOnICS();
(...)
}.run();
}
import android.annotation.TargetApi;
and then use annotations:
#TargetApi(11)
public void methodUsesAPI11()
{
...
Using this trick does a very simple thing: it allows compiling some code which contains API level 11 calls (classes, methods, etc) and still set android:minSdkVersion="8" in the manifest. Nothing more, nothing else.
The rest is up to you. You must check platform version before you call methodUsesAPI11() or you handle exceptions in order to prevent app crash and perform other action on older platforms.
Checking Build.VERSION.SDK_INT or using annotations should suffice, however, this link I'd bookmarked might be relevant to your case:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html?m=1
You can use what they describe there to have classes that may not be compatible, but will never be loaded. It's not conditional compilation, but it may be what you need, however, it is a bit more complex.

Inconsistent behaviour in WebView loadUrl() using local html file and #tags - API 7 and API 10

Summary:
Problem whilst trying use a webview to open a standard html file located in the “assets” directory. The html document contains location anchors throughout, and I try to navigate directly to these when opening the document by supplying a #tag in the URL supplied to the .loadUrl() method of a “WebView” object. This works correctly and consistently in an emulator with API level 7 ( Android 2.1 Updated), but shows inconsistent behaviour with an emulator with API level 10 ( Android 2.3.3 Updated). These inconsistencies have also been observed on a real device Samsung Galaxy S2 with Android 2.3.3.
Observations:
With API level 7, each time the .loadUrl() method is called, the page opens and the document is positioned at the correct anchor location as supplied in the URL#Tag string.
With API level 10, the first time the application is loaded into the emulator or the real device, the behaviour of the .loadUrl() method is as expected. The document opens at the correct anchor position. But in every subsequent call where a URL#tag string is supplied in the URL, the document opens and appears to scroll to the very bottom of the text on the page, ignoring the #tag. The exception to this is when a document is opened with only a standard URL without the #tag suffix attached.
Relevant code portions:
a) OnCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.help_viewer);
engine = (WebView) findViewById(R.id.id_web_engine);
// note the “engine” is defined globally to the activity
}
b) OnResume:
protected void onResume() {
super.onResume();
//
//
engine.loadUrl("file:///android_asset/Simple_help_en.html#about_this_app”);
// works in API 7, inconsistencies with API 10
//
//
}
c) OnStop
OnStop () { //added in desperation - but made no difference
protected void onStop() {
super.onStop();
engine.clearCache(true);
engine.clearHistory();
engine = null;
}
I'm very new to Android and feel that I've missed something as the balance of probability would suggest that its more likely to be an error in coding rather than an error in the API. I've searched through the questions/answers online but was unable to find a relevant answer. Can someone please point out my mistake and a way to resolve this problem?

Categories

Resources