shouldOverrideUrlLoading loading internally and externally on SDK versions < 18 - android

I'm using a standard WebView implementation, and overriding the shouldOverrideUrlLoading method to catch request to external domains. The call is being captured on all of my tested versions (15-22); however,on 15-18, the WebView navigates to the requested URL before shouldOverrideUrlLoading is called to execute the External Browser request.
Example:
SDK >= 19
WebView -> Load URL -> shouldOverrideUrlLoading(TRUE) -> URL loaded in External Browser and WebView's state is retained.
SDK <= 18
WebView -> Load URL -> URL loaded in WebView -> shouldOverrideUrlLoading(TRUE) -> URL loaded in External Browser and WebView's state is lost.
WebView Override Code:
private void webViewClient() {
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(BASE_URL)) {
return false;
} else {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
}
});
}

One possible cause:
This behavior makes sense if the URL being loaded is "invalid" (like something other than "http://whatever.com/"), and is somehow also a "redirect".
If the invalid url being loaded is a "redirect"... >=19 will not call the shouldOverrideUrlLoading at all.
If the FINAL URL is valid, however, and doesn't start with BASE_URL, it would call shouldOverrideUrlLoading, then launch the new window, as your code says.
That said, I have no idea how you would get an invalid URL to be a redirect -- so without more information about the URLs (BASE_URL and the URL being requested), it's impossible to say.
Read more about the differences between the WebView in 19+... big changes were made at that time:
https://developer.android.com/guide/webapps/migrating.html

Related

Issue in loading URL in webview android

I need to show a login webpage link in webview and the link is something like below
url = "https://test-dev.test.com/as/authorization.oauth2?client_id=com.test.td&response=code&value=id test mail&redirect_uri=com.test.ap://oauth2/test";
[Modifed the actual URL with different names]
On this page, we have to enter username and password. Clicking on login will take you to OTP screen, after entering the OTP result will be a url response and from this I need to read the code. Using this code I have to make a request to get the authentication token for the session. For token request, response will be Json.
Now I need help in resolving the below:
Currently its opening in browser and not in webview. But other links are opening in webview within the app except the above link.
Which is the call back method for handling response from this transaction.
Below is my code:
private WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new MyWebViewClient());
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.loadUrl(getAuthorizationURL());
webView.setHorizontalScrollBarEnabled(false);
webView.setWebContentsDebuggingEnabled(true);
// webView.addJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");
}
private String getAuthURL() {
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("test-dev.test.com")
.appendPath("ta/authorization.oauth2")
.appendQueryParameter("client_id", "com.test.td")
.appendQueryParameter("response", "code")
.appendQueryParameter("value", "id test mail").appendQueryParameter("redirect_uri", "com.test.ap://oauth2/test")
String url = Uri.decode(builder.build().toString());
//url = "https://www.google.com/";
// url = "https://developers.google.com/webmaster-tools/search-console-api/about";
return url;
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
System.out.println(" shouldOverrideUrlLoading :============ " + Uri.parse(url).getHost() + " url " + url);
// if(url.contains("dev.test.com")){
// webView.loadUrl(url);
// return false;
// }
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
}
This sounds like you're doing an OpenID authentication. You're implementation of shouldOverrideUrlLoading() is both firing an intent which will most likely go to the default web browser, and returning true. The return value tells Android whether you're taking control of loading the page (true) or leaving it to the web view (false). If you don't take control of handling the URL, the web view will try to load it like a normal page.
You're also immediately directing the web view to your authorization URL in your onCreate code. I'm thinking this is part of the confusion over the navigation behavior you're seeing.
For this kind of authentication process, you don't want to override loading the OTP page. Let the web view handle that just like anything else. What you want to do is capture the URL response. Your if statement within shouldOverrideUrlLoading should trap the response URL, consume the contents, and respond true to let the web view know you've taken care of that URL. Everything else should be handled by the web view.
Finally, the commented version of the code looks to me like it would send you into an infinite loop, the way you have it written. You're telling the web view to load the authorization URL, which will lead back to your web client code, which will trap the URL, causing it to load the URL...

HTML link to local file in WebView with target API 24

How can one use HTML links to navigate to local files (HTML pages) in WebView if targeting API 24 or higher?
This has been discussed before and solutions use the file:// URI scheme.
What worked so far was using
Go to local page
in an HTML file that is displayed in a WebView and clicking the link would load the local page app/src/main/assets/my_page.html.
However, starting from API 24, a FileUriExposedException is raised when clicking such a link. From logcat:
mypackage.myapp W/System.err: android.os.FileUriExposedException: file:///android_asset/my_page.html exposed beyond app through Intent.getData()
...
mypackage.myapp W/System.err: at org.chromium.android_webview.ResourcesContextWrapperFactory$WebViewContextWrapper.startActivity(ResourcesContextWrapperFactory.java:121)
mypackage.myapp W/System.err: at org.chromium.android_webview.AwContentsClient.sendBrowsingIntent(AwContentsClient.java:203)
According to the documentation, this is thrown when "an application exposes a file:// Uri to another app.". I wonder why this is the case, because according to the log everything seems to happen inside mypackage.myapp.
The documentation suggests using the content:// URI scheme instead, but this does not work in HTML files.
The following workaround (based on this answer) intercepts the loading of a file:// URI in the WebView and then loads it directly by app code with WebView.loadUrl(...). This is possible by overriding WebView.shouldOverrideUrlLoading in a WebViewClient passed to the WebView, e.g. when initializing it.
As there was an API change for this method in API 24, for compatibility there are two versions in the code (technically in the API<24 case one could also do as before, letting WebView open the file:// URI because the exception is not raised on devices running API<24).
if (android.os.Build.VERSION.SDK_INT >= 24) {
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) {
if (webResourceRequest.getUrl().getScheme().equals("file")) {
webView.loadUrl(webResourceRequest.getUrl().toString());
} else {
// If the URI is not pointing to a local file, open with an ACTION_VIEW Intent
webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW, webResourceRequest.getUrl()));
}
return true; // in both cases we handle the link manually
}
});
} else {
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (Uri.parse(url).getScheme().equals("file")) {
webView.loadUrl(url);
} else {
// If the URI is not pointing to a local file, open with an ACTION_VIEW Intent
webView.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
return true; // in both cases we handle the link manually
}
});
}
The reason why there is an exception when letting the WebView open the link must have something to do with the Intent created by the WebView but I don't see whether or how it is exposed to another app.
That the workaround works is then because the WebView does not do anything with the link (no Intent is created), instead, when the link is clicked, the app gets control and opens the file:// URI direclty by passing it to WebView.loadUrl(...) - which seems to be fine.
I assume (but do not claim) that regarding security this is fine because the URI is only used to load the file it points to in this single WebView (and if this was problematic the system should throw the FileUriExposedException).
I never link in the HTML that way if you need to load an other page:
Go to local page
I link this way because my map struture look like this:
Go to local page
You just need that methode in your MainActivity.java and that will work:
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:") || url.startsWith("mailto:") || url.startsWith("mms:") || url.startsWith("mmsto:") || url.startsWith("market:")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
If you have any questions or It still don't work let me know

android how to download PDF fie in web view

i have to use webview to show asp.net rdlc report using http url.
now i can download PDF file in web view show option in bellow image
You should create WebViewClient and set it to your webview.
every time you click a link WebViewClient's shouldOverrideUrlLoading method will be called.
You can get the PDF url, now call async task and download the file in device.
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (url.endsWith(".pdf")) {
// call Asynctask and download pdf file
return true;
}
return false;
}
});

Denied starting an intent without a user gesture Webview Android

Trying to redirect local html page in android webview using Javascript redirect, gets denied starting an intent in Logcat:
Testing on android 5.1.1
document.location = "index.html";
Denied starting an intent without a user gesture, URI:
file:///android_asset/index.html
I read the documentation in 1,000 attempts Android.developer and this was my solution
I do not know if you understand, I speak Spanish
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
This worked for me:
webView.setWebViewClient(new WebViewClient());
There are few issues here.
From newest androids, the WebView and Chrome Client is separated application which can be automatically updated without user intention.
From Chrome x >= 25 version, they changed how loading url is working in android application which is using webview component. https://developer.chrome.com/multidevice/android/intents Looks like they are blocking changing url without user gesture and launched from JavaScript timers
Solution here is to force user to activate URL change, for example on button click.
Also, you can override method mentioned above "shouldOverrideUrlLoading" in WebView client.
As alternate, i figured out was to add addJavascriptInterface each button click event fire action to JavascriptInterface
webView.addJavascriptInterface(new java2JSAgent(), "java2JSAgentVar"); //webView webview object
public class java2JSAgent
{
#JavascriptInterface
public String getContacts()
{
String jsonResponse = "{result:'redirected'}";
runOnUiThread(new Runnable() {
#Override
public void run() {
webView.loadUrl("file:///android_asset/index.html");
}
});
return jsonResponse;
}
}
might not be a good approach but atleast its working :-)
Thanks

Create intent on click WebView link

Ok, there will be two types of links in the content of my WebView. The behavior will be defined by the format of the link.
(1) Open the link in a browser. (The url begins with "openbrowser:")
(2) According to the link, open another Activity in the same project.
(The url will be "openactivity")
I am not sure if it is possible to create a map for the WebView which maps from a url pattern to an intent. For example, by default, if the url begins with "mailto:" the WebView will create an intent to open the mailbox. Could I define other mappings for my WebView?
I know there is a way to set a WebViewClient and override the shouldOverrideUrlLoading() method. But in API level 19, the function is not guaranteed to be called:
shouldOverrideUrlLoading() not called
So is it possible to set this url pattern to intent mapping as a general settings of the WebView?
Using a WebViewClient should be enough. We've had no problems with API level 19. For example:
WebView webView = new WebView(this);
String html = "<html><body>Test it</body></html>";
webView.loadData(html, "text/html", "utf-8");
webView.setWebViewClient(new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (url.startsWith("showmessage"))
{
Toast.makeText(MainActivity.this, url, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});

Categories

Resources