There is a WebView in my android app. It loads a webpage and user may click links to launch other apps by url scheme. Now I need to avoid this action.
For example, when user click a correct deeplink or applink in WeChat, WeChat will just say something like "sorry we can not launch xxx..." in its WebView, and user can open that page in browser to jump to the target app. I want to do the same thing.
I have seen this similar question how-can-i-disable-deeplinks in SO but there is no useful answer. And I have also tried to do something in shouldOverrideUrlLoading or shouldInterceptRequest but neither works. That means I can recognize the special url in shouldOverrideUrlLoading, but override its return to true or false can not stop launching app because the deeplink action is not an override in WebView.
url.startsWith("intent://")
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("intent://")) {
// This is a deeplink URL, return true to disable deeplinking
Toast.makeText(requireActivity(), "sorry we can not launch: "+url, Toast.LENGTH_SHORT).show();
return true;
} else {
// This is not a deeplink URL, let the WebView handle it
return super.shouldOverrideUrlLoading(view, url);
}
}
Add something like this to your WebViewClient:
/**
* The shouldOverrideUrlLoading(WebView view, String url) method is deprecated in API 24 and
* the shouldOverrideUrlLoading(WebView view, WebResourceRequest request) method is added in API 24.
* If you are targeting both older versions of Android and compiling with 24+, you need both methods.
* If not, you can delete the deprecated one
*/
#SuppressWarnings("deprecation") // Needs SDK 24 to be removed
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return handleUrl(Uri.parse(url));
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return handleUrl(request.getUrl());
}
private boolean handleUrl(Uri uri) {
// This can become more complex to support other url schemes like ftp
return !uri.getScheme().startsWith("http");
}
Related
In Android-WebView, I am trying to open the selected/touched link in external app by overriding shouldOverrideUrlLoading.
Window beforeunload event is triggered, regardless of return value of shouldOverrideUrlLoading.
My site according to current implementation is considering ("beforeunload event") as user navigating away from the page and marking the user as inactive, which is not correct.
Want to understand the behaviour of WebView, so that I can handle correctly.
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
{
if (request.getUrl().getHost().contains("mysite.com"))
{
// same site load in WebView itself.
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
startActivity(intent);
return true;
}
I think the method signature is should be next to override your desired action.
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Other possible updates might be
to ensure you do NOT have multi window settings mWebView.getSettings().setSupportMultipleWindows(true);
And sometimes you HAVE to set mixed content property webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);.
I am trying to parse every click event, intercept the http url that attempts to load into the webview, and decide if it should be shown depending on a set of logic as per how the url parses. I have followed the advice on these 3 StackOverflow links:
1) Intercept and override HTTP requests from WebView
2) Android Web-View shouldOverrideUrlLoading() Deprecated.(Alternative)
3) https://stackoverflow.com/a/32711309/2480714
without it fixing my issue. The main issue is that a user clicks on the webview to load a hyperlink and it is seems like the shouldOverrideUrlLoading method is not being called or is not intercepting the url properly every time.
I created my Custom WebViewClient and overrode it first with the intent of stopping all loads without my approval, but I have run into a snag; some urls are loading and bypassing my override methods and some are not. I have no clue why this is happening.
Here is my WebviewClient class:
public class CustomWebViewClient2 extends WebViewClient {
public CustomWebViewClient2(){
}
#Override
public void onPageFinished(WebView view, String url) {
Log.d("log", "(CustomWebViewClient) onPageFinished, URL == " + url);
}
#SuppressLint("NewApi")
#Nullable
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.d("log", "shouldInterceptRequest hit");
return null;
}
#Nullable
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Log.d("log", "shouldInterceptRequest hit");
return null;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Log.d("log", "(CustomWebViewClient) shouldOverrideUrlLoading");
return true;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("log", "(CustomWebViewClient) shouldOverrideUrlLoading");
return true;
}
#Override
public void onLoadResource(WebView view, String url) {
Log.d("log", "intercepting onLoadResource, url == " + url);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("log", "onPageStarted url == " + url);
}
}
As you can see, it is overriding the correct methods and should (in theory) never load a URL unless I pass it to the webview to load, but unfortunately some websites are loading, and others are not.
I also tried disabling the cache as per this comment in one of the answers:
"A word of CAUTION! If you intercept an attempt by the browser to
retrieve an image (or probably any resource) and then return null
(meaning let the WebView continue retrieving the image), any future
requests to this resource might just go to the cache and will NOT
trigger shouldInterceptRequest(). If you want to intercept EVERY image
request, you need to disable the cache or (what I did) call
WebView.clearCache(true)"
but to no avail. Why are some URLs loading in and bypassing the override, but others are not?
Update 1: Here is a sample URL https://cookpad.com/us that mirrors the issue I am referring to. It seems to be related to Turbolinks being implemented on the server-side.
I use a Android Webview and Override the Url Loading:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
On a Logout i have the following URL: https://someadress/logout?redirectURL=https%3A%2F%2Fsomeadress.de%2Flogout.html&skinID=no_scr
On some Devices, specially Samsung Devices, the redirect is not working and stops after calling this URL. But on the most Devices the redirect is working.
Anybody has some Idea why the redirect isn´t working on some Kind of Devices?
Try this on. This is working fine for me
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(i);
return true;
}
You are loading the same URL. That is not an override. If you are returning true, you need to load a different URL.
I have some logic I want my WebView to apply whenever I try to change its url. For links within loaded pages it's fine, I can just do it by using shouldOverrideUrlLoading method on my custom WebViewClient.
But when I explicitly call loadUrl on my WebView, shouldOverrideUrlLoading is not fired (obviously, or it would produce an endless loop when calling loadUrl from within this method).
Is there a way to "preload" a url manually so the shouldOverrideUrlLoading method is called?
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("myapp://")
{
//Do something
}
else {
view.loadUrl(url);
}
return true;
}
This works fine when I click a link from within the rendered page. But if I call:
mWebView.loadUrl("myapp://whatever");
shouldOverrideUrlLoading() is not called. What I am asking is whether there's a way that I can pass a url to my webView so it gets passed through to shouldOVerrideUrlLoading() before actually loading it. (i.e. shouldOVerrideUrlLoading() is called whenever a new url is about to be loaded. That's the event I want to fire)
REF: Android's official WebView documentation
if your app version greater then 'N' you should use this function
shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
check you function and version
If all you're trying to do is re-use your logic, just extract it into your WebViewClient and use that to load the url and then just delegate to this in shouldOverrideUrlLoading():
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return loadUrl(view, url);
}
public boolean loadUrl(WebView view, String url) {
if(url.startsWith("myapp://")
{
//Do something
}
else {
view.loadUrl(url);
}
return true;
}
Then instead of
mWebView.loadUrl("myapp://whatever");
You do:
mWebViewClient.loadUrl(mWebView, "myapp://whatever");
I have a WebView in which I load a page with a custom link (like app://action). I registered the url schemes in the manifest file and when I click on the link, the onResume() method of my Activity is called with the correct data and it works OK.
My problem is that the WebView still try to load the link and my WebView ends up to show a "Web page unavailable" message. I don't want that.
How can I prevent the WebView to load the url?
Here's my code :
WebView banner = ...
banner.setWebViewClient(new WebViewClient() {
#Override
public void onLoadResource(WebView view, String url) {
if (url.startsWith("app://")) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url), getContext(), Main.class);
//startActivity(i);
}
}
}
banner.loadUrl("url_to_the_banner");
Use WebViewClient.shouldOverrideUrlLoading instead.
public boolean shouldOverrideUrlLoading(WebView view, String url){
// handle by yourself
return true;
}
WebViewClient Reference
Updates: Method shouldOverrideUrlLoading(WebView, String) is deprecated in API level 24. Use shouldOverrideUrlLoading(WebView, WebResourceRequest) instead.
But it must return false otherwise, so:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
if(url.startsWith(myString){
// handle by yourself
return true;
}
// ...
return false;
}