Android - Load PDF inside webview
Solution 1
This could be as simple as:
try
{
Intent intentUrl = new Intent(Intent.ACTION_VIEW);
intentUrl.setDataAndType(url, "application/pdf");
intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myActivity.startActivity(intentUrl);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(myActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
though I've not tried this.
In our apps, we DOWNLOAD the PDF to the apps file system, make it world readable, then pass the path in an Intent to open a PDF viewing app (e.g. Acrobat Reader). Please note that you'd also need to also be concerned with cleaning up these downloaded PDF's!
in your try block put
new DownloadPDFTask().execute(url);
DownloadPDFTask class:
public class DownloadPDFTask extends AsyncTask<String, Void, Integer>
{
protected ProgressDialog mWorkingDialog; // progress dialog
protected String mFileName; // downloaded file
protected String mError; // for errors
@Override
protected Integer doInBackground(String... urls)
{
try
{
byte[] dataBuffer = new byte[4096];
int nRead = 0;
// set local filename to last part of URL
String[] strURLParts = urls[0].split("/");
if (strURLParts.length > 0)
mFileName = strURLParts[strURLParts.length - 1];
else
mFileName = "REPORT.pdf";
// download URL and store to strFileName
// connection to url
java.net.URL urlReport = new java.net.URL(urls[0]);
URLConnection urlConn = urlReport.openConnection();
InputStream streamInput = urlConn.getInputStream();
BufferedInputStream bufferedStreamInput = new BufferedInputStream(streamInput);
FileOutputStream outputStream = myActivity.openFileOutput(mFileName,Context.MODE_WORLD_READABLE); // must be world readable so external Intent can open!
while ((nRead = bufferedStreamInput.read(dataBuffer)) > 0)
outputStream.write(dataBuffer, 0, nRead);
streamInput.close();
outputStream.close();
}
catch (Exception e)
{
Log.e("myApp", e.getMessage());
mError = e.getMessage();
return (1);
}
return (0);
}
//-------------------------------------------------------------------------
// PreExecute - UI thread setup
//-------------------------------------------------------------------------
@Override
protected void onPreExecute()
{
// show "Downloading, Please Wait" dialog
mWorkingDialog = ProgressDialog.show(myActivity, "", "Downloading PDF Document, Please Wait...", true);
return;
}
//-------------------------------------------------------------------------
// PostExecute - UI thread finish
//-------------------------------------------------------------------------
@Override
protected void onPostExecute (Integer result)
{
if (mWorkingDialog != null)
{
mWorkingDialog.dismiss();
mWorkingDialog = null;
}
switch (result)
{
case 0: // a URL
// Intent to view download PDF
Uri uri = Uri.fromFile(myActivity.getFileStreamPath(mFileName));
try
{
Intent intentUrl = new Intent(Intent.ACTION_VIEW);
intentUrl.setDataAndType(uri, "application/pdf");
intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myActivity.startActivity(intentUrl);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(myActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
break;
case 1: // Error
Toast.makeText(myActivity, mError, Toast.LENGTH_LONG).show();
break;
}
}
}
any reference to "myActivity" must be replaced with a reference to your Activity class
Solution 2
Please checkout the example for handling redirect urls and 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;
}
}
Solution 3
Loading pdf within a webview:
WebView wv = (WebView) view.findViewById(R.id.webPage);
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebViewClient(new WebClient());
wv.loadUrl("http://drive.google.com/viewerng/viewer?embedded=true&url=" + mUrl);
wv.getSettings().setBuiltInZoomControls(true);
mUrl - will be your pdf link
Solution 4
I was trying to handle this exact same scenario. The solution I came up with is below.
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String cleanUrl = url;
if (url.contains("?")) {
// remove the query string
cleanUrl = url.substring(0,url.indexOf("?"));
}
if (cleanUrl.endsWith("pdf")) {
try {
Uri uriUrl = Uri.parse(cleanUrl);
Intent intentUrl = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intentUrl);
return true;
} catch (Exception e) {
System.out.println(e);
Toast.makeText(context,"No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
}
return false;
}
I needed to make sure it would handle pdf links, even if there was a query string. Still a bit hacky as the cleanUrl needs to end in "pdf", but so long as that is true, this should work. If you're serving up pdf's through a php script or something, you might want to dig a little deeper, handle things based on MIME type or something.
user1363871
Updated on June 09, 2020Comments
-
user1363871 almost 4 years
I have this webview code and I want to make it possible to have the PDF files opened when a user clicks on a PDF link. Here is the code, can you tell me what I have to put inside the PDF area of this? I've tried many different ways and I cannot get the PDF to view at all. Thanks for the help.
webview.setWebViewClient ( new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { // do your handling codes here, which url is the requested url // probably you need to open that url rather than redirect: if (url.startsWith("tel:")) { startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url))); } else if (url.startsWith("mailto:")) { url = url.replaceFirst("mailto:", ""); url = url.trim(); Intent i = new Intent(Intent.ACTION_SEND); i.setType("plain/text").putExtra(Intent.EXTRA_EMAIL, new String[]{url}); startActivity(i); } else if (url.startsWith("geo:")) { try { } catch (Exception e) { System.out.println(e); } } else if (url.endsWith("pdf")) { try { } catch (Exception e) { System.out.println(e); } } else { view.loadUrl(url); } return true; // then it is not handled by default action } });
-
user1363871 almost 12 yearsIs it possible to just show the PDF file form the webview without running a async download task?
-
CSmith almost 12 yearsNo, unlike UIWebView on iOS, the Android WebView does not display PDF content. You can try directly calling the intent (i.e. no AsyncDownloadTask), though you'll be leaving your activity no matter what.
-
user1363871 almost 12 yearsHmm, so the best way in android would be to call the async to download the file and save it. Do you know if the process can automatically find the filename and save as that name on the SD card? I always have specified the name when using this. Thanks!
-
CSmith almost 12 yearsI would try just handing your http://{file}.pdf url to the intent, I would think the PDF viewer program (e.g. Acrobat) will take care of the rest. If it doesn't, the downloader task should give you a good starting point. This part of the code handles the file naming, it extracts the filename from your URL: // set local filename to last part of URL String[] strURLParts = urls[0].split("/"); if (strURLParts.length > 0) mFileName = strURLParts[strURLParts.length - 1]; else mFileName = "REPORT.pdf";