Android项目实战(六十一):pdf文件用图片方式预览
前言:
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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。