android WebView shouldOverrideUrlLoading() - java

Hi this doesnt work for me:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
s="url clicked: "+url;
view.loadDataWithBaseURL(null, s, "text/html", "utf-8", null);
return true;
}
});
I have links in my html, it shows during loading in main activity,
but when I click them I get a white blank screen
I want to be able to read what those urls are, in the program, and I assume this url override function is the purpose for this.
I have tried with loadData() as well.
Thank you

You're not passing the new url to the WebView.
Should be
view.loadDataWithBaseURL(url, null, "text/html", "utf-8", null);
Edit: This also gives me a blank screen because loadDataWithBaseUrl expects you to provide some text or html as the data parameter yourself. Just use
view.loadUrl(url);

I didn't write http:// in my links, and wrote only x. This was the problem, it works now.

Related

Android Webview cannot render the pdf sometimes and shows blank/white page instead

Open the pdf in the webview using google docs
Open the same pdf or different pdf again and again.
Sometimes it will show the blank/white page in the android untill we refresh the webpage again for 1 or 2 times.
I have made the sample on the pdf. The link for the project is shown below:
https://github.com/gopalawasthi123/PdfWebView
Hope this will help you Better.
public void SetWebView(WebView webview,string externalUrl){
webview.Tag = "webview";
webview.Settings.JavaScriptEnabled = true;
webview.Settings.SupportZoom ();
webview.Settings.SetAppCacheEnabled(true);
webview.Settings.DomStorageEnabled = true;
webview.ZoomOut ();
webview.ZoomIn ();
webview.Settings.BuiltInZoomControls = true;
webview.Settings.LoadWithOverviewMode = true;
webview.Settings.UseWideViewPort = true;
//webview.Settings.SetSupportZoom (true);
webview.Settings.SetPluginState (WebSettings.PluginState.On);
webview.Settings.GetPluginState ();
if (externalUrl.StartsWith("http://") || externalUrl.StartsWith("https://"))
webview.LoadUrl (externalUrl);
webview.SetWebViewClient (new MonkeyWebViewClient (imgViewBack, imgViewForward, imgRefresh));
webview.SetWebChromeClient (new WebChromeClient ());
}
You can reload the page until it displays the pdf in this way:
public void onPageFinished(WebView view, String url) {
if (view.getTitle().equals(""))
view.reload();
}
After testing second PDF URL file, WebView seems like that can not load large PDF file.
Reason:
WebView display HTML. The fact that this works at all is by a hack- google will convert simple PDFs into HTML. It doesn't seem like they support anything that big. Even if they did, I would expect loading a large page PDF converted to HTML would be so large I highly doubt you'd be able to load it without going OOM. Use an appropriate PDF library, make a real PDF rendering view, and make sure not to render more of the PDF at a time than you need (or else you'll go OOM anyway). In other words, don't rely on hacky solutions you never should have relied on in the first place.
Solution:
You should try alternatives like PDF.js running locally in your device, instead of a service like Google Docs preview.(Or download PDF first to local file path)
Put it in your assets folder and tweak the example:
wv.loadUrl("file:///android_asset/web/viewer.html");
Also, you can have Out Of Memory situations. An alternative to try is a native viewer like AndroidPdfViewer.
We can solve the Problem in the two ways.
1. One is to use the Js.Pdf Plugin on the server end. It surely solve the problem but if we have multiple pdf's in the Fragment then it may cause the out of memory situations
and app can crash.
2. Second option is we can recursively called the function to load webview. This will also cause the issue but with less frequency Below is the code:
private void showPdf(final String imageString) {
pdfView.invalidate();
pdfView.getSettings().setJavaScriptEnabled(true);
pdfView.getSettings().setSupportZoom(true);
pdfView.loadUrl("http://docs.google.com/gview?embedded=true&url=" + imageString);
pdfView.setWebViewClient(new WebViewClient() {
boolean checkhasOnPageStarted = false;
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
checkhasOnPageStarted = true;
}
#Override
public void onPageFinished(WebView view, String url) {
if (checkhasOnPageStarted ) {
pdfView.loadUrl(removePdfTopIcon);
} else {
showPdf(imageString);
}
}
});
}
I was having the exact same issue and found that there was always a chance the WebView would not load on the first load attempt, especially if the pdf was on the larger side. The code I put together below works 100% of the time. From my beginner's understanding, it safely utilizes a separate thread to loop through and test the load status of the WebView, re-attempting a load of the view until successful. As this question was posted a year ago, I have generalized my solution to best benefit new viewers.
public class WebViewActivity extends AppCompatActivity {
String PDFView;
WebView webView;
String PDFBrowserView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get the intended "PDFView"
PDFView = getIntent().getExtras().get("PDFView").toString();
//Have to manually encode (?) the url to display it
try {
PDFView = URLEncoder.encode(PDFView, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//Full display url
PDFBrowserView = "https://docs.google.com/gview?embedded=true&url=" + PDFView;
//Initialize a new "WebView" instance
webView = new WebView(WebViewActivity.this);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccessFromFileURLs(true);
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
//This handles callbacks (?)
webView.setWebChromeClient(new WebChromeClient());
//Call this to load page if page is blank with pdf url until page is not blank
checkPageFinished();
}
public void checkPageFinished() {
//If view is blank:
if (webView.getContentHeight() == 0) {
//Run off main thread to control delay
webView.postDelayed(new Runnable() {
#Override
public void run() {
//Load url into the "WebView"
webView.loadUrl(PDFBrowserView);
}
//Set 1s delay to give the view a longer chance to load before
// setting the view (or more likely to display blank)
}, 1000);
//Set the view with the selected pdf
setContentView(webView);
webView.postDelayed(new Runnable() {
#Override
public void run() {
//If view is still blank:
if (webView.getContentHeight() == 0) {
//Loop until it works
checkPageFinished();
}
}
//Safely loop this function after 1.5s delay if page is not loaded
}, 1500);
}
}
}
There are some ways through which we can identify whether a Page/URL is loaded properly or not from onPageFinished() method of the Webview and based on that reload() url.
Option 1 : To check with contentHeight of the webview.
override fun onPageFinished(view: WebView?, url: String?) {
if(view?.contentHeight == 0){
view?.reload()
return
}
super.onPageFinished(view, url)
}
Option 2 : To check with title of the webview.
override fun onPageFinished(view: WebView?, url: String?) {
if(view?.title.isNullOrEmpty()){
view?.reload()
return
}
super.onPageFinished(view, url)
}
Tested in multiple devices and working within API 29
in Kotlin
val webSettings: WebSettings = webview.settings
webSettings.javaScriptEnabled = true
webSettings.useWideViewPort = true
webSettings.loadWithOverviewMode = true
webSettings.domStorageEnabled = true
webview.webViewClient = AppWebViewClients()
// val TERM_CONDITION_URL = "http://docs.google.com/gview?embedded=true&url="
// + "YOUR_DOC_URL_HERE"
bindind?.webview?.loadUrl(TERM_CONDITION_URL)
and here AppWebViewClients class
class AppWebViewClients : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
view.loadUrl(url)
return true
}
override fun onPageFinished(view: WebView?, url: String?) {
if (view?.contentHeight == 0)
view?.reload();
else {
super.onPageFinished(view, url)
}
}
}
I think you should do as below:
public void onPageFinished(WebView view, String url) {
if (!view.getUrl().equals(url)) {
view.loadUrl(url);
return;
}
}

How to send only a page of website to default browser and load rest of the website pages in webview?

I'm working on webview in android studio where I need to load a website but I also don't want to load some specific pages of that website in webview.
Let's assume I load https://stackoverflow.com/questions/ in my webview but I want to send https://stackoverflow.com/questions/ask this url to default browser whenever user wants to visit this url.
for doing this, I've tried this code in my webViewClient() but it doesn't work!
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("https://stackoverflow.com/questions/ask")){
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
return false;
}
as mentioned in the comments: If the Problem is, that this method never triggers I suspect the URL to be in another form than you expect it to be.
Try logging passed URL's like this:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i("WebView", "shouldOverrideUrlLoading called with URL=" + url);
if(url.contains("questions/ask")){
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
return false;
}
I suspect that there isn't a https but a http in front or that is is omitted completely or just a relative path to the one were you are (i.e. just "questions/ask")

Show office document in android

I am developing an android blog app with Firebase Firestore. I want to show a Microsoft Office Word document in the app (because I want to add multiple styled texts).
When the user clicks on an article in the app, an activity will show the specified data. What I mean is that there will be different texts, so each article will have different content. What I want is to show styled text like the ones available in Microsoft Word (bullets and numbering, bold, italic... these stuff) in the content of the article.
I thought of uploading a word.docx document into the storage in Firebase and adding the link of it in the content field in Firestore. But I am sure that it will not work.
Does anyone know what should I do?
I have similar thing the only difference is I have shown pdf, but I am sure it can be done for doc also, you will need webView to make it work, I am providing you method that will open the file in webview by google docs, have a look:
private void setUpWebView() {
setWebviewSettings();
mwebView.clearHistory();
mwebView.clearFormData();
mwebView.clearCache(false);
mwebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mwebView.setScrollbarFadingEnabled(true);
mwebView.getSettings().setSupportZoom(true);
mwebView.setWebChromeClient(new CustomWebChromeClient(this));
mwebView.setWebViewClient(new WebViewClient());
mwebView.getSettings().setJavaScriptEnabled(true);
mwebView.getSettings().setPluginState(WebSettings.PluginState.ON);
String url = AppConstants.FULL_TANDC_URL;
if (NetworkUtil.isNetworkAvailable(this)) {
if (url != null && !TextUtils.isEmpty(url) && URLUtil.isValidUrl(url)) {
textNoData.setVisibility(View.GONE);
if (url.contains(".pdf")) {
mwebView.loadUrl("http://docs.google.com/gview?embedded=true&url=" + url);
mprogressBar.setVisibility(View.GONE);
} else {
mwebView.loadUrl(url);
mprogressBar.setVisibility(View.VISIBLE);
}
} else {
textNoData.setVisibility(View.VISIBLE);
mprogressBar.setVisibility(View.GONE);
}
} else {
mprogressBar.setVisibility(View.GONE);
textNoData.setVisibility(View.VISIBLE);
}
}
I hope this will help you.
Happy coding :)

Android WebView onPageFinished BUG

After update API (27) in Android OREO this code is no longer working:
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() {document.getElementById(\"imPage\").style.display='none';})()");
}
I have also tried with:
webView.loadUrl(
"javascript:(function() { " +
"document.addEventListener(\"DOMContentLoaded\", function(event) {" +
"document.getElementById(\"imPage\").style.display='none';" +
"});" +
"})()");
Element not hiding and debug return:
I/chromium: [INFO:CONSOLE(1)] "Uncaught TypeError: Cannot read property 'style' of null", source: mywebsite/ (1)
So I think the javascript is injected before loading page, this explains why the line is 1, because I have other code called after loading page is finished but this code is called when page is white, not loaded.
In my own project I have been using evaluateJavascript(script,null) in onPageFinished to hide html elements. view.loadUrl() Should work the same way.
If you don't need the function be called at later time you could simplify your JS string and instead of \" try using '.
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:document.getElementById('imPage').style.display='none';");}
document.getElementById(\"imPage\") must be returning null.
So there is either no imPageelement or you haven't loaded the page at the time.
I would suggest moving your entire js code into
document.addEventListener("DOMContentLoaded", function(event) {
//insert here
});
You have to enable Javascript Seetings like below :-
view.getSettings().setJavaScriptEnabled(true); //Yes you have to do it

Load all resources through a proxy in webview android

How can i load resources dynamically from an android webview using onLoadResource() callback from a webviewClient?
Below is the code i have written so far. when i get new resources, it loads for example, the whole page of one single imagine instead of updating and displaying the image on the same original url of the webpage.
If a webpage has 5 images and text, my current code will load 5 pages each time onLoadResource tries to load an image.
what i want it to do is to load the images in the same page and any other resources as well such as JS, jquery's etc.
#Override
public void onLoadResource(WebView view, String url) {
addRequestToProxy(url);
}
public void addRequestToProxy(String url){
//pass url to proxy and wait for respoonse
String response;
//handle response
if(mime-type == IMAGE){
String urlStr = "http://example.com/my.jpg";
String pageData = "<img src=\"data:" + contentResponse.getMimeType()
+ ";base64," + contentResponse.getContent() + "\" />";
mWebView.loadDataWithBaseURL(urlStr, pageData, "text/html", null,
urlStr);
}else{
mWebView.loadDataWithBaseURL(null, response, "text/html", null,
null);
}
Instead of overriding onLoadResource() it's better to do it this way - shouldInterceptRequest()
webview shouldInterceptRequest example

Categories