• 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一页的数据预览,额外提供上一页、下一页的方法使用

     这里只提供基本使用,可以自行拓展功能,不限于图片缩放,多页展示等

  • 相关阅读:
    02 小白新一天
    集合排序
    匿名内部类-Lambda表达式
    设计模式之适配器设计
    设计模式之代理设计
    设计模式之工厂设计
    依赖倒转原则
    多态及练习题
    在一个类中调用另外一个类
    对象的三大特性之封装
  • 原文地址:https://www.cnblogs.com/xqxacm/p/14148639.html
Copyright © 2020-2023  润新知