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;
}
});
Related
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...
so I just started with Android programming and I am trying to make a little app using WebView. There is a url that redirects you to a pdf, I know WebView does not render pdf. So I want to use intent and display the pdf in Google Docs. However, the pdf address is randomly generated so I cant link it with
WebView.loadUrl("http://docs.google.com/gview?embedded=true&url=" + pdfURL);
How can I send an intent to Google Docs without using the exact pdf address?
I don't know what "randomly generated" means.
But the first thing that comes to my mind is to set a WebViewClient and override shouldOverrideUrlLoading:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".pdf") == true) {
view.loadUrl("http://docs.google.com/gview?embedded=true&url=" + url);
return true;
}
return false;
}
});
Some more info in this thread.
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
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
I have a WebViewClient attached to my WebView like so:
webView.setWebViewClient(new MyWebViewClient());
Here is my implementation of MyWebViewClient:
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webView.loadUrl(url);
return true;
}
}
I give the WebView a URL to load via loadUrl(). If I have a link (a href...) in the page, my shouldOverrideUrlLoading method is called and I can intercept the link click.
However, if I have a form whose method is POST, the shouldOverrideUrlLoading method is not called.
I noticed a similar issue here: http://code.google.com/p/android/issues/detail?id=9122 which seems to suggest overriding postUrl in my WebView. However, this API is only available starting from API level 5.
What can I do if I'm on API level 4? Is there any other way to intercept form posts?
This is known issue, that shouldOverrideUrlLoading don't catch POST. See http://code.google.com/p/android/issues/detail?id=9122 for details.
Use GET! I personally tried using POST, because I expected some limitation of GET parameters (i.e. length of URL), but I just successfully passed 32000 bytes through GET locally without any problems.
Do you really need to use a POST? If you want to handle formdata locally, why not have a piece of javascript handle your form and interface with "native" java code using addJavascriptInterface. E.g.
WebView engine = (WebView) findViewById(R.id.web_engine);
engine.getSettings().setJavaScriptEnabled(true);
engine.addJavascriptInterface(new MyBridge(this), "bridge");
engine.loadUrl(...)
Your bridge can be any class basically and you should be able to access its methods directly from javascript. E.g.
public class MyBridge {
public MyBridge(Context context) {
// ...
}
public String doIt(String a, String b) {
JSONArray result = new JSONArray();
result.put("Hello " + a);
result.put("Hello " + b);
return result.toString();
}
Your html / javascript could look like:
<script type="text/javascript">
$("#button").click(function() {
var a = $("#a").val();
var b = $("#b").val();
var result=JSON.parse(bridge.doIt(a, b));
// ...
}
</script>
<input id="a"><input id="b"><button id="button">click</button>
I think you can override onLoadResource(WebView view, String url) from WebViewClient. This function is Added in API LEVEL 1.
This function is called when WebView will load the resource specified by the given url. Resource include js, css, iframe embeded url. Code example like this:
#Override
public void onLoadResource(WebView view, String url) {
if (url.indexOf("http://www.example.com") != -1 && view != null) {
// open url in default browser
view.stopLoading();
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
}