How to handle shouldInterceptRequest parameter change in API21? - android

In API21 Google modified shouldInterceptRequest method to use WebResourceRequest request instead of String url.
Is there any way I could write a generic class extending WebViewClient and handle both methods?
My minimum API version is 18.
Thanks
Krystian

Google modified shouldInterceptRequest method to use WebResourceRequest request instead of String url
No, they added a second shouldInterceptRequest() method. Both are available in API Level 21+; the String variant is available on API Level 11+. While the String one is marked as deprecated, the String variant should be supported for quite some time, for backwards compatibility.
Is there any way I could write a generic class extending WebViewClient and handle both methods?
The built-in implementation of the WebResourceRequest version of shouldInterceptRequest() simply calls the String implementation of shouldInterceptRequest():
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return shouldInterceptRequest(view, request.getUrl().toString());
}
(from the source code as of right now)
So, you have two choices:
Just override the String edition, if you do not need the WebResourceRequest, and it will be used on all relevant API levels.
Override both, knowing that the WebResourceRequest one will be used on API Level 21+ and the String edition will be used on API Levels 11-20.

Related

Android 4.2.2 signal 11 SIGSEGV: Unable to match class WebResourceRequest and WebResourceError

I'm working on an app that works perfectly fine when running on Android 6.0. When I try to run it on 4.2.2, it crashes completely with Signal 11 SIGSEGV.
Just before this crash, the logical shows this error:
dalvikvm: Unable to match class for part: Landroid/webkit/WebResourceRequest;Landroid/webkit/WebResourceError
This tells me that I'm using two classes that aren't available in 4.2.2. Besides the fact that none of the tools caught this, I made sure that it wouldn't happen because every place where I use those classes I put the correct #TargetApi annotation before the methods that use these classes. For example:
#RequiresApi(android.os.Build.VERSION_CODES.M)
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
...
}
and
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
...
}
I don't know what I'm doing wrong. Or maybe these two errors aren't related to each other?
#TargetApi just an annotation and suppress the Lint error. You need to manualy check build version and use allowed classes and methods
For example
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return super.shouldInterceptRequest(view, request);
}
added in Api level 21 but there are deprecated method added in Api level 11
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return super.shouldInterceptRequest(view, url);
}
You can create several instance of WebViewClient with build version depending or simply override deprecated methods

Handle deprecated overrides in android

I am updating my Android App to work with the latest version (it was developed with Lollipop). On inspecting the code I see several deprecated methods. Thanks to previous questions I have understood how to handle calls to depercated methods (check for targetSdkVersion > Build.VERSION_CODES.. etc)
However there are several overrodes to deprecated methods. How do I handle this?
for e.g. I use a WebViewClient() in which i override the onReceivedError(..) method
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
...
super.onReceivedError(view, errorCode, description, failingUrl);
}
The documentation says tis method was deprecated in API23, and I now need to use onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
My question is, how do I go about writing the check for the deprecated method?
Could I simply do:
#TargetApi(Build.VERSION_CODES.M)
#Override
onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){...}
#SuppressWarnings("deprecation")
onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){..}
Is there any additional check I need?
You can check it by similar statement as this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
do some work for LOLLIPOP
} else {
do some work for older versions
}
My question is, how do I go about writing the check for the deprecated method?
For callbacks? You don't. If your minSdkVersion is high enough, just use the newer callback. Otherwise, just use the older callback. The exception would be if the documentation tells you to do otherwise, perhaps based on targetSdkVersion, though I cannot think of any scenarios where this happens.
For backwards compatibility, the old callbacks still work. On newer devices, they automatically "fall back" to using the old callbacks if the newer one is not implemented.

How to catch Android WebView HTTP 500 error code covering all Android versions (4 - 7)

I have an android WebView set up with a WebViewClient as suggested by other threads to cover e.G. a 500 HTTP error from android 6 and above by using onHttpErrorReceived as follows:
webview.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Log.d("FREEBROWSER", "----------------- ERROR deprecated ---------------");
}
#Override
#TargetApi(android.os.Build.VERSION_CODES.M)
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
Log.d("FREEBROWSER", "----------------- ERROR " + rerr.getDescription() + " ---------------");
// Redirect to deprecated method, so you can use it in all SDK versions
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
}
#Override
#TargetApi(android.os.Build.VERSION_CODES.M)
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
onReceivedError(view, errorResponse.getStatusCode(), errorResponse.getReasonPhrase(), request.getUrl().toString());
}
});
This works perfectly fine for devices running API level 23 and above (as it was also mentioned by the docs and other threads here, but this is of course unsatisfying if you want to catch a 500 error also for devices below API Level 23.
I get absolutely NO error callback with my android 4.4.2 device. Neither the version
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
nor the version
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr)
is beeing called on a 500 error.
By looking at possible solutions for devices lower than API 23 I basically found 2 solutions in many variants (I don't want to explain them here again):
Catch "shouldOverrideUrlLoading" and/or other callbacks and perform a kind of "HEAD" request in advance to see if the webpage is reachable or not, then display custom error page.
Use JavaScript injection and ajax to determine reachability
Also as far as i could read there are no plans to release a supportlib version of this callback so that it could be used in older versions.
My question is: Are there other clean ways to support catching HTTP error status codes with devices running Android versions lower than API Level 23? Has anybody implemented a suitable solution for customers which at best exclude an additional request or JavaScript injection?
You can try to download HTML String and check the response header with this initial request. Use e.g. HttpURLConnection (or OkHttpClient) to do that. There you can check response with HttpURLConnection.getResponseCode(). If response code is good for you, load downloaded string with WebView.loadDataWithBaseURL(), see https://developer.android.com/reference/android/webkit/WebView.html#loadDataWithBaseURL

Use shouldOverrideUrlLoading to handle commands on Android WebView

I'm new to Android, and I'm working on a simple WebView app.
I'm using shouldOverrideUrlLoading to handle some commands from my remote HTML to Android.
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(!url.startsWith("https://www.mywebsite.com)) {
switch (url) {
case "mycmd://app_logoff":
Toast.makeText(context, getString(R.string.logoff_ok), Toast.LENGTH_SHORT).show();
appLogoff();
break;
default:
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(urlWeb)));
}
}
return true;
I tested on my Android device (Motorola X Play) and it worked good! Is it safe to say that this will work on all android devices that matches the app minimum API level? Is this a good practice?
Since you are using shouldOverrideUrlLoading means you are implementing the custom WebViewClient and shouldOverrideUrlLoading should give your app a chance to take over the control when a new url is about to be loaded in the current WebView.
As per the developer documentation this API is added in API Level 1 so that basically means it is supported since long and should not be a concern as far as minimum API level.
I guess no one can surely say that it will work or not work on ALL devices unless actually tested on them. You may want to test them using Android emulators with different configurations such as different SDK/Platforms, API Level etc. to be double sure.
As a side note and caution, This method is not called for requests using the POST "method".
from webview android exapmle, shouldOverrideUrlLoading is used.
However, it is deprecated since api 24.
boolean shouldOverrideUrlLoading (WebView view, String url)
New replacement API with new parameter is here.
boolean shouldOverrideUrlLoading (WebView view, WebResourceRequest request)

shouldInterceptRequest is not called when running Android 4.3 or lower

I'm using a simple WebViewClient in a WebView in Android. I want to intercept requests when loading resources and thus I have overridden shouldInterceptRequest like this:
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Log.d(TAG, "onInterceptRequest: " + url);
// Do something important if needed
//...
// else go on...
return super.shouldInterceptRequest(view,url);
}
The problem is that this doesn't work on all of my devices. On my Galaxy S4 with Android 4.4 it works all the time. On my Galaxy S2 with Android 4.1.2 it doesn't work at all. Any suggestions about this? The function shouldInterceptRequest is flagged as API level 11, so it should be safe on Android 3.0+
Update: I have now tested this on Android 4.3 and shouldInterceptRequest is not called on that device either. My targetSdkVersion is set to 19.
Update 2: More tests. It seems that shouldInterceptRequest is called when I'm using WebView::loadUrl, but not when I'm passing the html as a string using WebView::loadDataWithBaseURL.

Categories

Resources