How to open local PDF file in WebView in Android?
Solution 1
I know, this question is old.
But I really like the approach of Xamarin to make use of the pdf.js from Mozilla. It works on older Android versions, you don't need a special PDF Viewer app for this and you can easily display a PDF inside of your apps views hierarchy.
Git for this: https://mozilla.github.io/pdf.js/
Additional default options (like standard zoom): https://github.com/mozilla/pdf.js/wiki/Viewer-options
Just add the pdfjs files to your Assets directory:
And call it the following way:
// Assuming you got your pdf file:
File file = new File(Environment.getExternalStorageDirectory() + "/test.pdf");
webview = (WebView) findViewById(R.id.webview);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setBuiltInZoomControls(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=" + file.getAbsolutePath() + "#zoom=page-width");
Cool thing: If you want to reduce the amount of functionalities / controls. Go to the Assets/pdfjs/web/viewer.html file and mark certain controls as hidden. With
style="display: none;"
E.g. If you don't like the right toolbar:
<div id="toolbarViewerRight" style="display: none;">...</div>
Update
'URL scheme "file" is not supported'
Might occur for newer versions of pdfjs. With version 1.8.188
this error does not appear.
Solution 2
As @Sameer replied in your comment above, the only solution to view PDF in webview is through Google Docs' online viewer which will render and send back a readable version to your app.
Previously discussed here
Solution 3
You cannot. Using an Intent, you can open the PDF in an external viewer application like Acrobat Reader:
try
{
Intent intentUrl = new Intent(Intent.ACTION_VIEW);
intentUrl.setDataAndType(uri, "application/pdf");
intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mActivity.startActivity(intentUrl);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(mActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
Solution 4
After going through several posts I came across this simple answer on Quora which pretty much do the work. Following are steps:-
Add this dependency in your gradle file:
compile 'com.github.barteksc:android-pdf-viewer:2.0.3'
activity_main.xml
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
MainActivity.java
package pdfviewer.pdfviewer;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.shockwave.pdfium.PdfDocument;
import java.util.List;
public class MainActivity extends Activity implements OnPageChangeListener,OnLoadCompleteListener{
private static final String TAG = MainActivity.class.getSimpleName();
public static final String SAMPLE_FILE = "sample_pdf.pdf";
PDFView pdfView;
Integer pageNumber = 0;
String pdfFileName;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView= (PDFView)findViewById(R.id.pdfView);
displayFromAsset(SAMPLE_FILE);
}
private void displayFromAsset(String assetFileName) {
pdfFileName = assetFileName;
pdfView.fromAsset(SAMPLE_FILE)
.defaultPage(pageNumber)
.enableSwipe(true)
.swipeHorizontal(false)
.onPageChange(this)
.enableAnnotationRendering(true)
.onLoad(this)
.scrollHandle(new DefaultScrollHandle(this))
.load();
}
@Override public void onPageChanged(int page, int pageCount) {
pageNumber = page;
setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount));
}
@Override public void loadComplete(int nbPages) {
PdfDocument.Meta meta = pdfView.getDocumentMeta();
printBookmarksTree(pdfView.getTableOfContents(), "-");
}
public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
for (PdfDocument.Bookmark b : tree) {
Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx()));
if (b.hasChildren()) {
printBookmarksTree(b.getChildren(), sep + "-");
}
}
}
}
You have to make sure that your asset folder contains sample_pdf.pdf (Library also support opening pdf from Uri and SDCard)
Happy coding :)
Solution 5
From android OS 5.0(lollipop) on-wards you can use PdfRenderer instead of webview/library.
You can use this class to show pdf's within the app.
If you want to support OS lower than that you can use a library/other approach mentioned in other answer as there is no native support.
Read more about it from the docs, you can also refer this example
Girish Patel
Updated on July 09, 2022Comments
-
Girish Patel almost 2 years
I want to open local (SD card) PDF file in a WebView.
I already tried this:
webview = (WebView) findViewById(R.id.webview); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setPluginsEnabled(true); webview.getSettings().setAllowFileAccess(true); File file = new File(Environment.getExternalStorageDirectory() + "/test.pdf"); final Uri uri = Uri.fromFile(file); webview.loadUrl(uri.toString());
But it's still not opening it, so let me know how I can open a PDF in WebView?
-
James Wong about 10 years@androidsanta nop, it was to be loaded from web.
-
tryp about 8 yearsThis work only with a remote PDF. If you want to open a local file like @girishce26, you have to use the CSmith's solution or this external plugin github.com/JoanZapata/android-pdfview
-
Ely Dantas about 7 yearsAwesome answer :)
-
CGR almost 7 yearsCan pdf inside Android Project assets folder be opnened?
-
Lepidopteron almost 7 years@CGR You will need a file‘s reference, which also needs to be available for the script, so maybe you need to copy the file locally from the assets folder first: stackoverflow.com/a/38504987
-
Boris Gafurov over 6 yearsLepidopteron thanks a lot, it worked great. I have pdf in assets, I copied it in private folder inside my app and opened it from there - no problems, no permissions mess. Used latest pdfjs 1.8.188
-
Lepidopteron over 6 years@BorisGafurov Glad it helped you! :-)
-
Lepidopteron over 6 years@Pihu Yes, it will
-
Pihu over 6 yearsBut i am unable to run this on Nougat Devices
-
Pihu over 6 yearsYeah, it runs finally now.. But it is very slow.
-
pallav bohara about 6 yearspdf.js zip file is around 40MB....I have to increase my app size by this much amout?
-
Lepidopteron about 6 years@pallavbohara the apk zips the files once again, so it will not increase the apk size of 40MB, but rather a smaller value. I did not validate the impact on the apk's size, tho.
-
Lepidopteron over 5 years@NiyasNazar it should, so far I did not stumble over an API, which did not work anymore. If you do, please do edit my answer and add your observations made.
-
Android developer almost 5 years@Lepidopteron How would you make it work that way, while on the internet you can find so many threads about pdf.js not supporting the
file:///
fetching? Exact err message is 'URL scheme "file" is not supported' and you can find lots of threads about it. How does this work for you? -
Lepidopteron almost 5 years@RadekKłos this approach renders the PDF with the framework - this requires some work if you‘d like to implement it yourself. Whilst the „file:///„ approach would make use of the system rendering.
-
DSoldo over 4 years@RadekKłos I was wondering the same and so I tried an older version of pdfjs, 1.8.188 version, mentioned in a comment above. And it worked. Instead it doesn't work with the latest version 2.1.266. So the URL scheme "file" not supported is a recent change.
-
niall8s almost 4 years@Lepidopteron - I'm hoping you or someone is still keeping an eye on this. I'm still having issues getting this to work in a native Android app. Using 1.8.188 version. Initially I was getting issues about SystemJS not being defined, however I npm install systemjs to the pdfjs package in my Android project. However now I'm getitng a different error: Failed to load file:///android_asset/pdfjs/web/app.js: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.", source: file:///android_asset/pdfjs/node_modules/systemjs/dist/system.js (4)
-
niall8s almost 4 yearsAh now this issue is back to the unsupported file protocol scheme regarding trying to access the l10n.js stuff for localisation. Did anyone exclude this somehow?