I'm loading local html using loadDataWithBaseURL method.
I'm calling the meod setHTML with the source, and it's going well. the link is VALID, as i've seen in previous questions on stackoverflow, so everything is set.
When the user clicks on a link, it works and its opening the ArticleActivity, but when he clicks on an image (from the html), the method isn't called, even tho the image has a link.
What would be the problem here?
public void setHTML(String source) {
Document doc = Jsoup.parse(source);
String html = WebHelper.docToBetterHTML(doc, this);
mHTMLWebView.loadDataWithBaseURL(mLink, html, "text/html", "UTF-8", "");
mHTMLWebView.setVisibility(View.VISIBLE);
}
mHTMLWebView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Animation fade = AnimationUtils.loadAnimation(mLoadingLayout.getContext(), android.R.anim.fade_out);
mLoadingLayout.startAnimation(fade);
mLoadingLayout.setVisibility(View.GONE);
}
},500);
}
public boolean shouldOverrideUrlLoading(WebView view, String url){
//super.shouldOverrideUrlLoading(view,url);
if(url != null
&& (url.endsWith(".png") || url
.endsWith(".jpg") || url
.endsWith(".jpeg"))){
// Launch imageviewer
ArrayList<String> list = new ArrayList<>();
list.add(url);
try{
new ImageViewer.Builder(view.getContext(), list)
.setStartPosition(0)
.show();
} catch (Exception e){
e.printStackTrace();
}
} else if (url != null
&& url.contains("dkhlak.com")){
Intent intent = new Intent(view.getContext(),ArticleActivity.class);
intent.putExtra("link",url);
view.getContext().startActivity(intent);
} else {
Intent ViewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
try{
view.getContext().startActivity(ViewIntent);
} catch (Exception e){
e.printStackTrace();
}
}
return true;
}
});
Example:
<p>\u0625\u0646 \u0639\u0627\u0644\u0645\u0646\u0627 \u0645\u0643\u0627\u0646\u064c \u063a\u0631\u064a\u0628\u064c \u062c\u062f\u0627\u064b\u060c \u0641\u0641\u064a \u0628\u0639\u0636 \u0627\u0644\u0623\u062d\u064a\u0627\u0646 \u064a\u0648\u062c\u062f \u0623\u0634\u064a\u0627\u0621\u064c \u0643\u062b\u064a\u0631\u0629 \u0646\u0638\u0646\u0647\u0627 \u0639\u0627\u062f\u064a\u0629\u060c \u0644\u0643\u0646\u0647\u0627 \u0642\u062f \u062a\u0643\u0648\u0646 \u0641\u064a \u0646\u0638\u0631 \u063a\u064a\u0631\u0646\u0627 \u0645\u0646 \u0627\u0644\u0646\u0627\u0633 \u063a\u064a\u0631 \u0639\u0627\u062f\u064a\u0629\u060c \u0628\u0644 \u0623\u0646\u0647\u0645 \u0642\u062f \u064a\u0631\u0648\u0646\u0647\u0627 \u0642\u0628\u064a\u062d\u0629. \u0644\u0643\u0646 \u0641\u064a \u0627\u0644\u0646\u0647\u0627\u064a\u0629 \u064a\u0648\u062c\u062f \u0623\u0634\u064a\u0627\u0621 \u0646\u062c\u0645\u0639 \u0643\u0644\u0646\u0627 \u0639\u0644\u0649 \u0642\u0628\u062d\u0647\u0627 \u0648\u0628\u063a\u0636\u0647\u0627\u060c \u0648\u0630\u0644\u0643 \u0644\u0623\u0646\u0647\u0627 \u063a\u064a\u0631 \u0625\u0646\u0633\u0627\u0646\u064a\u0629 \u0648\u0638\u0627\u0644\u0645\u0629 \u0644\u062f\u0631\u062c\u0629 \u063a\u064a\u0631 \u0642\u0627\u0628\u0644\u0629 \u0644\u0644\u062a\u0635\u0648\u0631.<\/p>\n<p>\u0648\u0645\u0647\u0645\u0627 \u0643\u0627\u0646 \u0642\u0628\u062d \u062a\u0644\u0643 \u0627\u0644\u0623\u0634\u064a\u0627\u0621 \u0643\u0628\u064a\u0631\u0627\u064b\u061b \u064a\u0628\u0642\u0649 \u0644\u062f\u064a\u0646\u0627 \u0641\u0636\u0648\u0644 \u0643\u0628\u064a\u0631 \u0644\u0645\u0639\u0631\u0641\u0629 \u0645\u0627\u0647\u064a\u062a\u0647\u0627\u060c \u0641\u0641\u064a \u0627\u0644\u0645\u0642\u0627\u0644 \u0627\u0644\u062a\u0627\u0644\u064a \u0633\u0646\u0639\u0631\u0636 \u0644\u0643\u0645 \u0633\u062a \u0639\u0634\u0631\u0629 \u062d\u0642\u064a\u0642\u0629 \u0635\u0627\u0631\u062e\u0629 \u062c\u0627\u0648\u0632\u062a \u0641\u064a \u0642\u0628\u062d\u0647\u0627 \u0623\u0628\u0639\u062f \u0627\u0644\u062d\u062f\u0648\u062f:<\/p>\n<p><strong>1. \u0641\u064a \u0645\u0637\u0644\u0639 \u0627\u0644\u0642\u0631\u0646 \u0627\u0644\u0639\u0634\u0631\u064a\u0646\u060c \u0639\u064f\u0631\u0636 \u0627\u0644\u0631\u062c\u0644 \u0627\u0644\u0643\u0648\u0646\u063a\u0648\u0644\u064a Ota Benga \u0641\u064a \u0623\u062d\u062f \u0623\u0642\u0641\u0627\u0635 \u0627\u0644\u0642\u0631\u062f\u0629 \u0641\u064a \u062d\u062f\u064a\u0642\u0629 Bronx \u0643\u0646\u0645\u0648\u0630\u062c \u062d\u064a \u0644\u0645\u0631\u0627\u062d\u0644 \u0627\u0644\u062a\u0637\u0648\u0631 \u0627\u0644\u0628\u0634\u0631\u064a\u0629 \u0627\u0644\u0645\u0628\u0643\u0631\u0629. \u0645\u0635\u064a\u0631 Benga \u0625\u0646\u062a\u0647\u0649 \u0628\u0625\u0642\u062f\u0627\u0645\u0647 \u0639\u0644\u0649 \u0627\u0644\u0625\u0646\u062a\u062d\u0627\u0631 \u0646\u062a\u064a\u062c\u0629 \u0644\u0633\u0648\u0621 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u064a \u062a\u0639\u0631\u0636 \u0625\u0644\u064a\u0647\u0627\u060c \u0648\u0627\u0644\u0625\u0643\u062a\u0626\u0627\u0628 \u0627\u0644\u0630\u064a \u0623\u0635\u0627\u0628\u0647 \u0644\u0627\u062d\u0642\u0627\u064b.<\/strong><em>\u00a0\u2014<a href=\"https:\/\/en.wikipedia.org\/wiki\/Ota_Benga\" rel=\"nofollow\">\u0627\u0644\u0645\u0635\u062f\u0631<\/a><\/em><\/p>\n<div id=\"attachment_15079\" style=\"width: 1034px\" class=\"wp-caption aligncenter\"><img class=\"size-full wp-image-15079\" src=\"https:\/\/dkhlak.com\/wp-content\/uploads\/2017\/06\/15071-1.jpg\" alt=\"\u0627\u0644\u0631\u062c\u0644 \u0627\u0644\u0643\u0648\u0646\u063a\u0648\u0644\u064a Ota Benga\" width=\"1024\" height=\"580\" srcset=\"https:\/\/dkhlak.com\/wp-content\/uploads\/2017\/06\/15071-1.jpg 1024w, https:\/\/dkhlak.com\/wp-content\/uploads\/2017\/06\/15071-1-400x227.jpg 400w, https:\/\/dkhlak.com\/wp-content\/uploads\/2017\/06\/15071-1-768x435.jpg 768w, https:\/\/dkhlak.com\/wp-content\/uploads\/2017\/06\/15071-1-810x459.jpg 810w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>
Related
I'm trying to display a PDF on Android in a Xamarin.Forms project and it works fine, except for the first time it's loaded where just one blank page appears 9 times out of 10.
The first call is to this function, located in the Android project:
public string HTMLToPDF(string html, string filename) {
//html param is a full html description of the pdf
//filename param is something like "example.pdf"
try {
var dir = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/folder/");
var file = new Java.IO.File(dir + "/" + filename);
if (!dir.Exists())
dir.Mkdirs();
int x = 0;
while (file.Exists())
{
x++;
file = new Java.IO.File(dir + "/" + filename + "( " + x + " )");
}
if (webpage == null)
webpage = new Android.Webkit.WebView(Android.App.Application.Context);
else
webpage.RemoveAllViews();
int width = 2100;
int height = 2970;
webpage.Layout(0, 0, width, height);
webpage.LoadData(html, "text/html", "UTF-8");
webpage.SetWebViewClient(new WebViewCallBack(file.ToString()));
this.Print(webpage, file.ToString(), filename);
return file.ToString();
}
catch (Java.Lang.Exception e)
{
App._mainPage.DisplayAlert("Error", e.Message, "Ok");
}
return "";
}
This is what the WebViewCallBack class looks like:
class WebViewCallBack : Android.Webkit.WebViewClient
{
string fileNameWithPath = null;
public WebViewCallBack(string path)
{
this.fileNameWithPath = path;
}
public override void OnPageFinished(Android.Webkit.WebView view, string url)
{
view.SetInitialScale(1);
view.Settings.LoadWithOverviewMode = true;
view.Settings.UseWideViewPort = true;
PdfDocument document = new Android.Graphics.Pdf.PdfDocument();
Android.Graphics.Pdf.PdfDocument.Page page = document.StartPage(new Android.Graphics.Pdf.PdfDocument.PageInfo.Builder(2100, 2970, 1).Create());
view.Draw(page.Canvas);
document.FinishPage(page);
Stream filestream = new MemoryStream();
Java.IO.FileOutputStream fos = new Java.IO.FileOutputStream(fileNameWithPath, false);
try
{
document.WriteTo(filestream);
fos.Write(((MemoryStream)filestream).ToArray(), 0, (int)filestream.Length);
fos.Close();
}
catch (Java.Lang.Exception e)
{
App._mainPage.DisplayAlert("Erreur", e.Message, "Ok");
}
}
}
And the method Print called at the end:
public void Print(Android.Webkit.WebView webView, string filename, string onlyFileName)
{
try
{
PrintAttributes.Builder builder = new PrintAttributes.Builder();
PrintAttributes.Margins margins = new PrintAttributes.Margins(0, 0, 0, 80);
builder.SetMinMargins(margins);
builder.SetMediaSize(PrintAttributes.MediaSize.IsoA4);
builder.SetColorMode(PrintColorMode.Color);
PrintAttributes attr = builder.Build();
PrintManager printManager = (PrintManager)Forms.Context.GetSystemService(Android.Content.Context.PrintService);
var printAdapter = new GenericPrintAdapter(Forms.Context, webView, filename, onlyFileName);
printAdapter.OnEnded += PrintAdapter_OnEnded;
printAdapter.OnError += PrintAdapter_OnError;
printManager.Print(filename, printAdapter, attr);
}
catch (Java.Lang.Exception e)
{
App._mainPage.DisplayAlert("Erreur", e.Message, "Ok");
}
}
When I put a breakpoint on the first line of the OnPageFinished callback of the WebViewCallBack class, I see two different things at this point:
either the PDF interface is up but it's still loading the PDF. In that case, the PDF loads fine once I click on "play" again.
either the PDF has already loaded, as a single blank page. This only happens when it's the first try at loading this particular PDF.
Thus I guess I have to find a way to force the loader to wait for the OnPageFinished method to run first? But that seems wrong.
I can also add that the original HTML contains images, which are all appearing as base64 string in the html string I'm feeding to HTMLToPDF. I noticed that the PDF loads well even on the first try if there are no images in the HTML, so I thought the problem might be that the PDF loads before it's ready on the first try only, maybe because of the images. I couldn't find a fix for that though.
Can anybody shed some light on this for me?
So there are a couple of ways to handle the flow, but I would go with just an event or an Observable.
So lets convert your WebViewCallBack to something that actually performs a callback when its OnPageFinished is called. This is using System.Reactive but you could also use an EventHandler...
// a few class level variables
bool busy;
WebView webView;
IDisposable WhenPageIsLoadedSubscription;
public class WebViewObservable : WebViewClient
{
Subject<string> pageLoaded = new Subject<string>();
public IObservable<string> WhenPageIsLoaded
{
get { return pageLoaded.AsObservable(); }
}
public override void OnPageFinished(WebView view, string url)
{
pageLoaded.OnNext(url);
}
}
Now define your print routine (the calls in your original OnPageFinished and Print method). This will automatically be called when the webpage is finished loading.
void PrintWebPage(WebView webView, string url)
{
Log.Debug("SO", $"Page: {url} loaded, lets print it now" );
// Perform the work that you used to do in OnPageFinished
// Perform the work in your Print method
// Now turn off a Progress indictor if desired
busy = false;
}
Setup your WebView with the observable that calls the PrintWebPage action every time a page is loaded...
void LoadAndPrintWebPage(string html))
{
busy = true;
if (webView == null)
{
int width = 2100;
int height = 2970;
webView = new WebView(this);
var client = new WebViewObservable();
WhenPageIsLoadedSubscription = client.WhenPageIsLoaded.Subscribe((url) => { PrintWebPage(webView, url); });
webView.SetWebViewClient(client);
webView.Layout(0, 0, width, height);
}
webView.LoadData(html, "text/html", "UTF-8");
}
Now call LoadWebPage with your html content and it will be automatically printed after the page is finished loading...
LoadAndPrintWebPage(html);
When you are done, clean up your observable and webview to avoid memory leaks...
void CleanupWebView()
{
WhenPageIsLoadedSubscription?.Dispose();
webView?.Dispose();
webView = null;
}
I had similar problem with blank page. But I used google doc for displaying it. http://docs.google.com/gview?embedded=true&url=
I could solved my problem only by checking operation time between OnPageStarted and OnPageFinished. If it took short time, then something go wrong and page is blank.
here is my webClient.
Every time then page is blank I just reload it. Also add simple circuit breaker just in case
public class MyWebViewClient : WebViewClient
{
private readonly WebView _webView;
private DateTime _dateTime = DateTime.Now;
private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1);
private int _breakerHits;
private const int _BreakerCount = 2;
public MyWebViewClient(WebView webView)
{
_webView = webView;
}
public override async void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon)
{
await _semaphoreSlim.WaitAsync();
_dateTime = DateTime.Now;
base.OnPageStarted(view, url, favicon);
_webView.SendNavigating(new WebNavigatingEventArgs(WebNavigationEvent.NewPage, null, url));
_semaphoreSlim.Release();
}
public override async void OnPageFinished(Android.Webkit.WebView view, string url)
{
await _semaphoreSlim.WaitAsync();
base.OnPageFinished(view, url);
if (url.Contains(".pdf"))
{
var diff = DateTime.Now - _dateTime;
if (diff > TimeSpan.FromMilliseconds(700) || _breakerHits > _BreakerCount)
{
_breakerHits = 0;
_webView.SendNavigated(new WebNavigatedEventArgs(WebNavigationEvent.NewPage, null, url,
WebNavigationResult.Success));
}
else
{
_breakerHits++;
view.Reload();
}
}
else
{
_webView.SendNavigated(new WebNavigatedEventArgs(WebNavigationEvent.NewPage, null, url,
WebNavigationResult.Success));
}
_semaphoreSlim.Release();
}
}
I've seen several questions on this but all of the solutions didn't work for me. For a client we have to develop an app that actually does nothing except of showing a WebView and a native DrawerLayout. However, we only have their mobile webpage (with a menu, etc.). So we have to hide some elements. It is very important that the existing stylesheets stay the same, just some other CSS rules are added.
What I've tried so far:
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!mErrorOccured && !noConnectionAvailable) {
injectCSS();
}
mainActivity.hideLoadingScreen();
}
With this Injection:
// Inject CSS method: read style.css/readmode.css from assets folder
// Append stylesheet to document head
private void injectCSS() {
try {
Activity activity = (Activity) mContext;
SharedPreferences sharPref = activity.getSharedPreferences(Constants.PREFERENCE_NAME, Context.MODE_PRIVATE);
Boolean isReadMode = sharPref.getBoolean(Constants.READMODE_KEY, false);
InputStream inputStream;
if (isReadMode) {
inputStream = activity.getAssets().open("readmode.css");
} else {
inputStream = activity.getAssets().open("style.css");
}
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
// Tell the browser to BASE64-decode the string into your script !!!
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style);" +
"Android.injectCSS('Works!');})()");
} catch (Exception e) {
e.printStackTrace();
}
}
I've also tried to add a JavaScript Interface that uses the Android.injectCSS('Works!'); of the JavaScript above combined with:
#JavascriptInterface
public void injectCSS(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();
mMainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mMainFragment.unhideWebView();
}
});
}
And:
public void unhideWebView() {
webView.setVisibility(View.VISIBLE);
}
However, there is always a delay before the elements of the web page are hidden. I've also tried to use Jsoup. First this threw an NetworkOnMainThreadException. After I've tried to use it with an AsyncTask, it was not possible to change the WebView on onPostExecute() because this handling must be on the main thread. Even using a runOnUiThrad() did not help calling loadData() on the WebView with the new loaded data.
Is there any way to inject CSS/JS before the WebView shows up?
I am trying to load PDF files in Android Webview. when i Googled it. the best answer what i found is to use Google Docs. Now What i did is append the PDF file URL at the end of this url
https://docs.google.com/gview?embedded=true&url=
and then load this complete URL in the android WebView. it loads the PDF successfully. But there is one PDF file on the following URL that is not loading in WebView as well as in Chrome browser (on my system). The PDF URL is
http://www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf
and When i try to load the PDF as
https://docs.google.com/gview?embedded=true&url=www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf
then it says No Preview Available. can anyone please tell me whats wrong Here.
This is not a complete answer. I investigated several possibilities but still do not have a convincing explanation for this behavior.
Theory A: URL encoding ... no
My first thought was the same as #gn1 - the curly brackets needed URL encoding. Unfortunately, encoding the url parameter doesn't change the result.
Theory B: Bad PDF file ... no
Next I thought that perhaps Google Docs can't handle this particular PDF file - it's an unsupported version or uses optional features or even has errors that other viewers tolerate. I downloaded a copy and hosted it on another site. When I pointed Google Docs to the new location, it previewed fine.
Theory C: Uncooperative site ... no
Next I thought that maybe this site doesn't cooperate with Google Docs for some reason - perhaps it is blocking Google from indexing it. I found another PDF link on the same site with the same scheme:
http://www.expertagent.co.uk/asp/in4glestates/%7B6dad6f28-a59d-4b54-b277-52f077f4927f%7D/%7Be3a6d17c-d6a8-4e92-8f52-09c6721515fc%7D/External.pdf
When I pointed Google Docs to this link, it previewed fine.
Theory D: Different metadata ... no
Now I had one link that worked and one that didn't. Maybe their metadata was different - e.g. perhaps the one that worked was tagged application/pdf and the other one wasn't. So I looked at the HTTP headers.
Working URL:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Content-Length: 1767120
Content-Type: application/pdf
Last-Modified: Fri, 02 Nov 2007 12:45:00 GMT
Accept-Ranges: bytes
ETag: "46b1592e4e1dc81:13e6"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 03 Jun 2015 23:25:23 GMT
Not working URL:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Content-Length: 4623702
Content-Type: application/pdf
Last-Modified: Mon, 11 May 2015 15:53:16 GMT
Accept-Ranges: bytes
ETag: "acac5d9828cd01:13e6"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 03 Jun 2015 23:25:42 GMT
I see no apparent significant differences in metadata.
Theory E: Weird request from Google ... no
I'm admittedly grasping at straws at this point. I wondered if the request from Google was different somehow - maybe it asked for a byte range or obscure compression or something, and the target server didn't handle it consistently well. So I pointed Google Docs at a site I control to see what the HTTP request looked like:
GET /asp/in4glestates/%7B16D968D6-198E-4E33-88F4-8A85731CE605%7D/%7B05c36123-4df0-4d7d-811c-8b6686fdd526%7D/External.pdf HTTP/1.1
Host: www.example.com:55555
Connection: Keep-alive
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (compatible; Google AppsViewer; http://drive.google.com)
That isn't weird at all. I did verify that the target site ignores compression requests so it isn't a case of buggy compression. I also tried accessing the target site with that User-Agent header and it didn't seem to matter.
So I've found clues that help tell us what isn't the problem but nothing yet that explains what is. I'm posting in hopes that these negative results will still be useful to someone.
I'm using this and works for me: http://weimenglee.blogspot.com/2013/05/android-tip-displaying-pdf-document.html
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView=new WebView(MainActivity.this);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
//---you need this to prevent the webview from
// launching another browser when a url
// redirection occurs---
webView.setWebViewClient(new Callback());
String pdfURL = "http://www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf";
webView.loadUrl(
"http://docs.google.com/gview?embedded=true&url=" + pdfURL);
setContentView(webView);
}
private class Callback extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(
WebView view, String url) {
return(false);
}
}
Checkout the example code for open PDF without download, in webview
.
private void init()
{
WebView webview = (WebView) findViewById(R.id.webview);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
PdfWebViewClient pdfWebViewClient = new PdfWebViewClient(this, webview);
pdfWebViewClient.loadPdfUrl(
"https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjgwIfp3KXSAhXrhFQKHQqEDHYQFggZMAA&url=http%3A%2F%2Fwww.orimi.com%2Fpdf-test.pdf&usg=AFQjCNERYYcSfMLS5ukBcT2Qy11YxEhXqw&cad=rja");
}
private class PdfWebViewClient extends WebViewClient
{
private static final String TAG = "PdfWebViewClient";
private static final String PDF_EXTENSION = ".pdf";
private static final String PDF_VIEWER_URL = "http://docs.google.com/gview?embedded=true&url=";
private Context mContext;
private WebView mWebView;
private ProgressDialog mProgressDialog;
private boolean isLoadingPdfUrl;
public PdfWebViewClient(Context context, WebView webView)
{
mContext = context;
mWebView = webView;
mWebView.setWebViewClient(this);
}
public void loadPdfUrl(String url)
{
mWebView.stopLoading();
if (!TextUtils.isEmpty(url))
{
isLoadingPdfUrl = isPdfUrl(url);
if (isLoadingPdfUrl)
{
mWebView.clearHistory();
}
showProgressDialog();
}
mWebView.loadUrl(url);
}
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
return shouldOverrideUrlLoading(url);
}
#SuppressWarnings("deprecation")
#Override
public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl)
{
handleError(errorCode, description.toString(), failingUrl);
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
final Uri uri = request.getUrl();
return shouldOverrideUrlLoading(webView, uri.toString());
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public void onReceivedError(final WebView webView, final WebResourceRequest request, final WebResourceError error)
{
final Uri uri = request.getUrl();
handleError(error.getErrorCode(), error.getDescription().toString(), uri.toString());
}
#Override
public void onPageFinished(final WebView view, final String url)
{
Log.i(TAG, "Finished loading. URL : " + url);
dismissProgressDialog();
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
if (!isLoadingPdfUrl && isPdfUrl(url))
{
mWebView.stopLoading();
final String pdfUrl = PDF_VIEWER_URL + url;
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
loadPdfUrl(pdfUrl);
}
}, 300);
return true;
}
return false; // Load url in the webView itself
}
private void handleError(final int errorCode, final String description, final String failingUrl)
{
Log.e(TAG, "Error : " + errorCode + ", " + description + " URL : " + failingUrl);
}
private void showProgressDialog()
{
dismissProgressDialog();
mProgressDialog = ProgressDialog.show(mContext, "", "Loading...");
}
private void dismissProgressDialog()
{
if (mProgressDialog != null && mProgressDialog.isShowing())
{
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
private boolean isPdfUrl(String url)
{
if (!TextUtils.isEmpty(url))
{
url = url.trim();
int lastIndex = url.toLowerCase().lastIndexOf(PDF_EXTENSION);
if (lastIndex != -1)
{
return url.substring(lastIndex).equalsIgnoreCase(PDF_EXTENSION);
}
}
return false;
}
}
Here is working solution for 'No Preview Available' issue.. Exact Problem is in URL encoding which we concat with "http://docs.google.com/gview?url=". This means we have to replace all special character(:, /, & etc) of url with unicode. Uri.encode("") do the trick for us.
String url = Uri.encode("your link");
String finalUrl = "http://docs.google.com/viewer?url=" + url + "&embedded=true";
WebSettings webSettings = webView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptEnabled(true);
webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
progressView.setVisibility(View.VISIBLE);
webView.loadUrl(finalUrl);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.getSettings().setLoadsImagesAutomatically(true);
webView.setVisibility(View.VISIBLE);
//progressView.setVisibility(View.VISIBLE);
if (progressView != null && progressView.isShown()) {
progressView.setVisibility(View.GONE);
}
Log.v("after load", view.getUrl());
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
Log.e("error", description);
}
});
I put the file on my server and it works fine. This is a Google Docs problem encountered in the URL or the robots.txt. The document is fine. You can use URL rewrite to make Google Docs be fooled into thinking that it is from another folder. Those weird characters in the path could be the problem.
Clearly either a timing or browser issue the OP URL works perfectly via google as per given link (no need to convert or use any fancy coding) just retry with any other browser.
By the looks of things the URL you're pointing to includes some device specific location references.
You could look at downloading the file to internal store and then using an intent to load the PDF with any app installed.
From How to open a PDF via Intent from SD card
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/example.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
Alternatively you could instantiate the file with the web url
Download the source code from here(Open pdf in webview android);
activity_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<WebView
android:layout_width="match_parent"
android:background="#ffffff"
android:layout_height="match_parent"
android:id="#+id/webview"></WebView>
</RelativeLayout>
MainActivity.java
package com.pdfwebview;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
WebView webview;
ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
listener();
}
private void init() {
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setTitle("PDF");
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
webview.loadUrl("https://drive.google.com/file/d/0B534aayZ5j7Yc3RhcnRlcl9maWxl/view");
}
private void listener() {
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
pDialog.show();
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
pDialog.dismiss();
}
});
}
}
Set the URL in the webview to this.
https://docs.google.com/viewer?url=<pdf-url>
I am loading string value in my web view and i need when i click on the link shown in web view should open in other web browser of phone.
I want like this - String s = "hello read more.... www.google.com"
String html = "<html><body>+s+</body></html>"
webview.loaddata(html);
Try this:
webView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url != null && (url.startsWith("http://") || url.startsWith("https://"))) {
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
} else {
return false;
}
}
});
You can do something like this:
String s = "<a href='http://www.google.com' target='_blank'>Read more over here</a>";
webview.loaddata(s);
You will need to add other html content by yourself.
So basically, you can use target='_blank' which will open it in a new browser, not in webview.
Hope it helps.
I use phonegap 1.3.0 to develop mobile application.
when i click one button that will invoke my plugin to invoke a js function, after about 20s, countered the error: "E/DroidGap(21383): DroidGap: TIMEOUT ERROR! - calling webViewClient" in eclipse log console.
and the emulator alert a dialog, show error message : The connection to the server was unsuccessful.(javascript:showProcessBar(1))
How can I fix the error? thanks!
There are some details below to complement my question.
when I invoke js function in phonegap plugin. there must will show error message in logcat:"E/DroidGap(21383): DroidGap: TIMEOUT ERROR! - calling webViewClient" .
I find the code that generate the error. just below:
private void loadUrlIntoView(final String url) {
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap.loadUrl(%s)", url);
}
this.url = url;
if (this.baseUrl == null) {
int i = url.lastIndexOf('/');
if (i > 0) {
this.baseUrl = url.substring(0, i+1);
}
else {
this.baseUrl = this.url + "/";
}
}
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap: url=%s baseUrl=%s", url, baseUrl);
}
// Load URL on UI thread
final DroidGap me = this;
this.runOnUiThread(new Runnable() {
public void run() {
// Init web view if not already done
if (me.appView == null) {
me.init();
}
// Handle activity parameters
me.handleActivityParameters();
// Track URLs loaded instead of using appView history
me.urls.push(url);
me.appView.clearHistory();
// Create callback server and plugin manager
if (me.callbackServer == null) {
me.callbackServer = new CallbackServer();
me.callbackServer.init(url);
}
else {
me.callbackServer.reinit(url);
}
if (me.pluginManager == null) {
me.pluginManager = new PluginManager(me.appView, me);
}
else {
me.pluginManager.reinit();
}
// If loadingDialog property, then show the App loading dialog for first page of app
String loading = null;
if (me.urls.size() == 1) {
loading = me.getStringProperty("loadingDialog", null);
}
else {
loading = me.getStringProperty("loadingPageDialog", null);
}
if (loading != null) {
String title = "";
String message = "Loading Application...";
if (loading.length() > 0) {
int comma = loading.indexOf(',');
if (comma > 0) {
title = loading.substring(0, comma);
message = loading.substring(comma+1);
}
else {
title = "";
message = loading;
}
}
me.spinnerStart(title, message);
}
// Create a timeout timer for loadUrl
final int currentLoadUrlTimeout = me.loadUrlTimeout;
Runnable runnable = new Runnable() {
public void run() {
try {
synchronized(this) {
wait(me.loadUrlTimeoutValue);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
me.appView.stopLoading();
LOG.e(TAG, "DroidGap: TIMEOUT ERROR! - calling webViewClient");
//me.webViewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
me.appView.loadUrl(url);
}
});
}
I comment the line : me.webViewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url); because it will alert a dialog to terminate my program.
Android enforces a timeout when loading URLs in a webview.
check out this link, (it doesn't really pertain to JQM) , but phonegap android
http://jquerymobile.com/test/docs/pages/phonegap.html
The problem explains itself.. when there's a time out response in any PhoneGap call to an external URL it throws that error.
You can you this HTML5 feature to check the internet connection:
navigator.onLine;
You can see it working here: http://html5demos.com/nav-online
super.setIntegerProperty("loadUrlTimeoutValue",60000);
Place this line in java code in Activity