Android 显示PDF格式的文件

转载请注明出处,侵权可耻!可耻!可耻!


公司项目需要用到在线显示PDF格式的文件,但是试了好多方法都达不到需求,无奈只能伪造成在线查看的假象了。

就是先将pdf格式的文件下载到手机本地,再显示,当用户离开查看页面的时候再将下载的文件删掉。

可以这么做要感谢科技的发展,感谢祖国,感谢党,现在手机内存大,网速快,所以用户体验上并没有很糟糕。如果真遇到没内存没网的情况,本人就要被祭天了。


清单文件的权限

<uses-permission android:name="android.permission.INTERNET" />


<!-- 外存储写权限 -->

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 外存储读权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

加入依赖

compile 'com.github.barteksc:android-pdf-viewer:2.8.2'

然后在布局文件中引用

<com.github.barteksc.pdfviewer.PDFView
        android:id="@+id/pdfView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

1.文件下载

后台给的接口返回的地址是以“.aspx”结尾的,ios那边直接一个webview就能加载出来(这也是爬了很久的坑之后发现的)。地址放在浏览器上也是可以直接打开的,然后右键另存为就会发现这是一个PDF格式的文件。

这里的文件地址不能直接下载文件,需要浏览器自动重定向到可下载的地址,所以用webview加载,等自动跳转到可下载的地址后再启用下载

直接上代码

webView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                // 监听下载功能,当用户点击下载链接的时候,直接调用系统的浏览器来下载
                downloadBySystem(url, contentDisposition, mimetype);
            }
        });
    @SuppressLint("NewApi")
    private void downloadBySystem(String url, String contentDisposition, String mimeType) {
        // 指定下载地址
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        // 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库
        request.allowScanningByMediaScanner();
        // 设置通知的显示类型,下载进行时和完成后显示通知
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
        // 设置通知栏的标题,如果不设置,默认使用文件名
//        request.setTitle("This is title");
        // 设置通知栏的描述
//        request.setDescription("This is description");
        // 允许在计费流量下下载
        request.setAllowedOverMetered(true);
        // 允许该记录在下载管理界面可见
        request.setVisibleInDownloadsUi(false);
        // 允许漫游时下载
        request.setAllowedOverRoaming(true);
        // 允许下载的网路类型,默认为所有网络都允许
//        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
//        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
        // 设置下载文件保存的路径和文件名
        fileName = UUID.randomUUID().toString() + URLUtil.guessFileName(url, contentDisposition, mimeType);

        if (fileName.endsWith("aspx")) {//修改文件后缀名
            fileName = fileName.subSequence(0, fileName.length() - 4) + "pdf";
        }

        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
//        另外可选一下方法,自定义下载路径
//        request.setDestinationUri()
//        request.setDestinationInExternalFilesDir()
        downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        // 添加一个下载任务
        downloadId = downloadManager.enqueue(request);
        Log.e("downloadId:{}", downloadId + "");

        DownloadObserver mDownloadObserver = new DownloadObserver(mHandler, MyWebActivity.this, downloadId);
        getContentResolver().registerContentObserver(Uri.parse("content://downloads/"), true, mDownloadObserver);

    }

2.那我们怎么知道下载什么时候完成呢?

当然是用广播,新建一个广播类

public class DownloadCompleteReceiver extends BroadcastReceiver {

    public static String complete = "DownLoadComplete";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("onReceive. intent:{}", intent != null ? intent.toUri(0) : null);
        if (intent != null) {
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
               //这里执行打开的操作
        }
    }

}

这样就完了?没有

在webview的那个activity中,定义个全局变量,全局,全局

private DownloadCompleteReceiver receiver;

在onCreate方法中注册广播(destroy方法中要解注册,所以广播类定义成全局),也可在清单文件中静态注册,根据自己需求

/**
     * 动态注册广播
     */
    private void initBroadCast() {
        receiver = new DownloadCompleteReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        registerReceiver(receiver, intentFilter);
    }

3.下载完成后打开文件

打开PDF文件要在类中implements OnPageChangeListener, OnLoadCompleteListener, OnDrawListener 这些接口,然后实现里面的方法

 public void openPdf(String fileName) {

        //从文件中读取pdf并显示
        String path = "/storage/emulated/0/Download/" + fileName;
        
        if (fileName.endsWith(".pdf")) {
            
            pdfFile = new File(path);
            displayFromFile(pdfFile);
           
        } 
    }
private void displayFromFile(File file) {
        if (file != null) {
            if (file.exists()) {
                //ToastUtil.showToast("加载完成");
                pdfView.fromFile(file)   //设置pdf文件地址
                        .defaultPage(0)         //设置默认显示第1页
                        .onPageChange(this)     //设置翻页监听
                        .onLoad(this)           //设置加载监听
                        .onDraw(this)            //绘图监听
                        .enableSwipe(true)   //是否允许翻页,默认是允许翻
                        .load();
            } else {
                Log.e(TAG, "displayFromFile: 文件不存在");
            }
        } else {
            Log.e(TAG, "displayFromFile: 文件null");
        }
    }

4.离开页面时删掉文件

在onDestroy方法中删除

if (pdfFile != null && pdfFile.isFile() && isDelete) {
            pdfFile.delete();
        }


最后,有一点需要说明,接收广播的广播类和要显示文件的页面通常不在一个类中,要实现的方法很多,用接口或者EventBus都可以,根据自己情况

到此全部结束,仅供学习参考(如有bug,深表惭愧)



猜你喜欢

转载自blog.csdn.net/qq_39761063/article/details/80771058