前言:
Android不支援pdf的線上預覽,網上有多種預覽pdf的實作方式,點此檢視總結
這裡實作一種先下載下傳pdf檔案到本地,再将檔案轉成圖檔顯示的的操作
一個工具類:
import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.graphics.Bitmap;
import android.graphics.pdf.PdfRenderer;
import android.os.ParcelFileDescriptor;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.widget.ImageView;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import info.ecloud.core.util.ToastUtils;
import info.ecloud.merchant.app.BaseObserve;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class PdfRendererBasicViewModel extends AndroidViewModel {
private static final String TAG = "PdfRendererBasic";
/**
* The filename of the PDF.
*/
private static final String FILENAME = "sample.pdf";
private final MutableLiveData<PageInfo> mPageInfo = new MutableLiveData<>();
private final MutableLiveData<Bitmap> mPageBitmap = new MutableLiveData<>();
private final MutableLiveData<Boolean> mPreviousEnabled = new MutableLiveData<>();
private final MutableLiveData<Boolean> mNextEnabled = new MutableLiveData<>();
private final Executor mExecutor;
private ParcelFileDescriptor mFileDescriptor;
private PdfRenderer mPdfRenderer;
private PdfRenderer.Page mCurrentPage;
private boolean mCleared;
public File pdfFile ;
public ImageView pdfView ;
@SuppressWarnings("unused")
public PdfRendererBasicViewModel(Application application , File pdfFile , ImageView pdfView) {
this(application, false);
this.pdfFile = pdfFile;
this.pdfView = pdfView;
}
PdfRendererBasicViewModel(Application application, boolean useInstantExecutor) {
super(application);
if (useInstantExecutor) {
mExecutor = Runnable::run;
} else {
mExecutor = Executors.newSingleThreadExecutor();
}
mExecutor.execute(() -> {
try {
openPdfRenderer();
showPage(0);
if (mCleared) {
closePdfRenderer();
}
} catch (IOException e) {
Log.e(TAG, "Failed to open PdfRenderer", e);
}
});
}
@Override
protected void onCleared() {
super.onCleared();
mExecutor.execute(() -> {
try {
closePdfRenderer();
mCleared = true;
} catch (IOException e) {
Log.i(TAG, "Failed to close PdfRenderer", e);
}
});
}
public LiveData<PageInfo> getPageInfo() {
return mPageInfo;
}
public LiveData<Bitmap> getPageBitmap() {
Log.i("xqxinfo","bitmap==>"+(mPageBitmap==null));
return mPageBitmap;
}
public LiveData<Boolean> getPreviousEnabled() {
return mPreviousEnabled;
}
public LiveData<Boolean> getNextEnabled() {
return mNextEnabled;
}
void showPrevious() {
if (mPdfRenderer == null || mCurrentPage == null) {
return;
}
final int index = mCurrentPage.getIndex();
if (index > 0) {
mExecutor.execute(() -> showPage(index - 1));
}
}
public void showNext() {
if (mPdfRenderer == null || mCurrentPage == null) {
return;
}
final int index = mCurrentPage.getIndex();
if (index + 1 < mPdfRenderer.getPageCount()) {
mExecutor.execute(() -> showPage(index + 1));
}
}
public void showLast() {
if (mPdfRenderer == null || mCurrentPage == null) {
return;
}
final int index = mCurrentPage.getIndex();
if (index - 1 >=0) {
mExecutor.execute(() -> showPage(index - 1));
}
}
@WorkerThread
private void openPdfRenderer() throws IOException {
final File file = pdfFile;
if (!file.exists()) {
ToastUtils.showLong("檔案預覽失敗");
return;
}
Log.i("xqxinfo","file->"+file.getAbsolutePath());
mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
if (mFileDescriptor != null) {
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
}
@WorkerThread
private void closePdfRenderer() throws IOException {
if (mCurrentPage != null) {
mCurrentPage.close();
}
if (mPdfRenderer != null) {
mPdfRenderer.close();
}
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
}
@WorkerThread
private void showPage(int index) {
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
mPageBitmap.postValue(bitmap);
Observable.timer(10, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserve<Long>() {
@Override
public void onNext(Long aLong) {
pdfView.setImageBitmap(bitmap);
}
});
final int count = mPdfRenderer.getPageCount();
mPageInfo.postValue(new PageInfo(index, count));
mPreviousEnabled.postValue(index > 0);
mNextEnabled.postValue(index + 1 < count);
}
static class PageInfo {
final int index;
final int count;
PageInfo(int index, int count) {
this.index = index;
this.count = count;
}
}
}
使用方法:
public PdfRendererBasicViewModel(Application application , File pdfFile , ImageView pdfView)
注意,因為是圖檔方式顯示,依賴于一個ImageView , 每次隻顯示pdf一頁的資料預覽,額外提供上一頁、下一頁的方法使用

這裡隻提供基本使用,可以自行拓展功能,不限于圖檔縮放,多頁展示等
作者:聽着music睡
出處:http://www.cnblogs.com/xqxacm/
Android交流群:38197636
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。