Android原生加载显示在线PDF链接

工作需求,需要加载一个在线pdf,链接以“.pdf"结尾。通过查找,大都需要先把pdf文件下载下来,然后再加载,有以下几种实现方式:

方法一 :参考谷歌demo(android-PdfRendererBasic)

这个方案的好处是对apk安装包的体积基本无影响;
缺点 ①遇到PDF文件过大的时候可能OOM ②只能查看PDF文件,无法拓展,如果后续出现Word文档则无法满足。

方法二:使用JS 处理支持webview阅读pdf

将https://github.com/mozilla/pdf.js/下下来放到项目的assets下面,然后将这些copy到data下或者sd卡中,pdf也下载到相对目录下,然后就可以同上一样作为本地服务器一样阅读pdf了
缺点:

  1. 包增大几兆。
  2. 展示出来的样式太复杂,类似pdf工具的界面,太丑了。
  3. 无法展示水印

方法三:使用第三方SDK(比如:PdfViewPager、AndroidPdfViewer、android-pdfview)

AndroidPdfViewer:
优点:完美展示
缺点:使用后apk包增大15兆(真心没法接受)

android-pdfview:
优点:正常展示
缺点:

  1. 包大小增加三、四兆(勉强可以接受)。
  2. 水印无法展示出来(硬伤啊)

方法四:使用腾讯浏览服务

优点:

  1. 完美展示,水印也可以展示出来
  2. 包大小增加只有几十K

经过多次尝试,选择了方法四的解决方案:
代码如下

 /**
     * 使用x5内核加载pdf
     */
    private void loadPdf() {
        tbsReaderView = new TbsReaderView(this, this);
        LinearLayout rootRl = (LinearLayout) findViewById(R.id.root);
        rootRl.addView(tbsReaderView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));


        new LoadPDFAsyncTask(pdfName, new LoadPDFAsyncTask.OnLoadPDFListener() {
            @Override
            public void onCompleteListener(File file) {

                Bundle bundle = new Bundle();
                bundle.putString("filePath", file.getPath());
                bundle.putString("tempPath", Environment.getExternalStorageDirectory().getPath());
                boolean result = tbsReaderView.preOpen("pdf", false);
                if (result) {
                    tbsReaderView.openFile(bundle);
                    mLoadingDialog.dismiss();
                }

            }

            @Override
            public void onFailureListener() {
                ToastUtil.showToast(mContext, "加载失败");
                mLoadingDialog.dismiss();
            }

            @Override
            public void onProgressListener(Integer curPro, Integer maxPro) {

            }
        }).execute(webUrl);
    }

下载工具类

public class LoadPDFAsyncTask extends AsyncTask {
    private OnLoadPDFListener onLoadPDFListener;
    private String filePath = Environment.getExternalStorageDirectory().getAbsolutePath()
            + File.separator + "zxp" + File.separator + "pdf";
    private String fileName;

    public LoadPDFAsyncTask(String fileName) {
        this.fileName = fileName;
    }

    public LoadPDFAsyncTask(String fileName, OnLoadPDFListener onLoadPDFListener){
        this.fileName = fileName;
        this.onLoadPDFListener = onLoadPDFListener;
    }

    public void setOnLoadPDFListener(OnLoadPDFListener onLoadPDFListener) {
        this.onLoadPDFListener = onLoadPDFListener;
    }

    //这里是开始线程之前执行的,是在UI线程
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    //当任务被取消时回调
    @Override
    protected void onCancelled() {
        super.onCancelled();
        if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
    }

    //当任务被取消时回调
    @Override
    protected void onCancelled(File file) {
        super.onCancelled(file);
    }

    //子线程中执行
    @Override
    protected File doInBackground(String... strings) {
        String httpUrl = strings[0];
        if (TextUtils.isEmpty(httpUrl)) {
            if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
        }

        File pathFile = new File(filePath);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }

        File pdfFile = new File(filePath + File.separator + fileName);
        if (pdfFile.exists()) {
            return pdfFile;
        }
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(10000);
            conn.setReadTimeout(10000);
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.connect();
            int count = conn.getContentLength(); //文件总大小 字节
            int curCount = 0; // 累计下载大小 字节
            int curRead = -1;// 每次读取大小 字节
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                FileOutputStream fos = new FileOutputStream(pdfFile);
                byte[] buf = new byte[1024];
                while ((curRead = is.read(buf)) != -1) {
                    curCount += curRead;
                    fos.write(buf, 0, curRead);
                    publishProgress(curCount, count);
                }

                fos.close();
                is.close();
                conn.disconnect();
            }


        } catch (Exception e) {
            e.printStackTrace();
            if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
            return null;
        }

        return pdfFile;
    }

    //更新进度
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        if (onLoadPDFListener != null) {
            onLoadPDFListener.onProgressListener(values[0], values[1]);
        }
    }

    //当任务执行完成是调用,在UI线程
    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);
        if (onLoadPDFListener != null) {
            if (file != null && file.exists()) {
                onLoadPDFListener.onCompleteListener(file);
            } else {
                onLoadPDFListener.onFailureListener();
            }
        }

    }


    //下载PDF文件时的回调接口
    public interface OnLoadPDFListener {
        //下载完成
        void onCompleteListener(File file);
        //下载失败
        void onFailureListener();
        //下载进度 字节
        void onProgressListener(Integer curPro, Integer maxPro);
    }

需要注意的地方:

使用腾讯浏览服务,需要载加载界面退出的时候调用一个方法,否则下次加载时会一直提示”加载中“

 @Override
    protected void onDestroy() {
        super.onDestroy();
        if (tbsReaderView != null) {
            tbsReaderView.onStop();
        }
    }

你可能感兴趣的:(功能实现)