Android 开发之多种方案PDF阅读

最近开发中涉及到阅读港股公告,但是HK股票的公告都是坑,居然是pdf的,所以没办法,就要研究安卓pdf阅读,期间踩了点坑……

安卓的webview与ios 的UIWebView不一样,不能够支持在线阅读pdf,其实PC端的浏览器大部分也不支持pdf预览,虽然谷歌官方给了个“http //docs google com/gviewembedded=true&url=”这样的解决方案(将pdf、doc当成图片来看),但是在天朝有一堵墙,所以这个方案直接被抛弃。PC端的Chrome与火狐都是使用js处理才实现了pdf预览,所以在安卓端现有阅读并实现兼容性的解决方案有两种:一、使用webview,但本地添加js库处理(火狐提供了开源的pdf.js),二、修改安卓底层库,使用自定义view进行pdf预览。

一、使用JS 处理支持webview阅读pdf(同样适用于web前端)

1.服务器解决

此处将使用到pdf.js(火狐的解决方案)
服务端
//安装pdf.js

$ npm install -g gulp-cli

//构建

$gulp generic

构建完成后,把generic拷贝服务器相对目录下,就完成了。
启动服务,使用如下地址预览

http://localhost:8080/generic/web/viewer.html

最后,如果你要打开指定的pdf,这样就可以了

http://localhost:8080/generic/web/viewer.html?file=aaa.pdf
是不是很简单啊。

2.客户端解决

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

二、修改安卓底层库,使用自定义view进行pdf预览

1.官方simple PdfRendererBasic

  • pdf开发三部曲

打开初始化Pdf读取器PdfRenderer
如果你是在Fragment里面使用,最好在onAttach方法初始化

    /*** Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources.*/private void openRenderer(Context context) throws IOException {// In this sample, we read a PDF from the assets directory.mFileDescriptor = context.getAssets().openFd("sample.pdf").getParcelFileDescriptor();// This is the PdfRenderer we use to render the PDF.mPdfRenderer = new PdfRenderer(mFileDescriptor);}

读取内容
传入指定页码,读取内容转换成bitmap图片设置到ImageView

   private void showPage(int index) {if (mPdfRenderer.getPageCount() <= index) {return;}// 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);// Important: the destination bitmap must be ARGB (not RGB).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_DISPLAY);// We are ready to show the Bitmap to user.mImageView.setImageBitmap(bitmap);updateUi();}

关闭Pdf读取器PdfRenderer
PdfRenderer.Page提供了几个方法方便与我们使用,例如getIndex(获取当前页码)、getPageCount(总页码)等。在我们离开pdf展示页面时需要对资源进行释放,关闭Pdf读取器(fragment在生命周期onDetach调用释放关闭),如果你想做的像小说阅读一样,可以记录当前的index方便下次进入直接跳转到指定位置,书签就这个原理

  private void closeRenderer() throws IOException {if (null != mCurrentPage) {mCurrentPage.close();}mPdfRenderer.close();mFileDescriptor.close();}

如果你需要这个simple可以选择官网simple下面下载,如果你不能访问可以选择github上面下载:https://github.com/googlesamples/android-PdfRendererBasic,当然这个simple功能简单并不完善,仅仅实现了pdf简单展示,跟为高级功能我们接着往下看。

2、PdfViewPager


首先添加项目依赖

compile 'es.voghdev.pdfviewpager:library:0.2.1'

读写网络权限肯定需要的(本地pdf不需要网络),如果是网络pdf文件需要通过RemotePDFViewPager现在远程文件,DownloadFile.Listener回调下载结果,下载成功了需要为RemotePDFViewPager绑定适配器PDFPagerAdapter,在Activity销毁时需要释放PDFPagerAdapter

public class RemotePDFActivity extends AppCompatActivity implements DownloadFile.Listener {public void initPdfView(){RemotePDFViewPager remotePDFViewPager =new RemotePDFViewPager(context, "http://partners.adobe.com/public/developer/en/xml/AdobeXMLFormsSamples.pdf", this);}@Overridepublic void onSuccess(String url, String destinationPath) {// That's the positive case. PDF Download went fineadapter = new PDFPagerAdapter(this, "AdobeXMLFormsSamples.pdf");remotePDFViewPager.setAdapter(adapter);setContentView(remotePDFViewPager);}@Overridepublic void onFailure(Exception e) {// This will be called if download fails}@Overridepublic void onProgressUpdate(int progress, int total) {// You will get download progress here// Always on UI Thread so feel free to update your views here}@Overrideprotected void onDestroy() {super.onDestroy();adapter.close();}
}

根据github上面资料介绍,该库支持网络pdf、assets文件下的pdf、SDcard缓存的pdf文件,看上去挺不错的,但是,但是还是有版本要求

3、android-pdfview

持多种方式加载pdf,向下兼容到API8,Configurator提供了builder的方式配置属性,让代码更简洁了,使用时Gradle依赖

compile 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'

xml布局

<com.joanzapata.pdfview.PDFViewandroid:id="@+id/pdfview"android:layout_width="match_parent"android:layout_height="match_parent"/>

代码调用实例

pdfView.fromAsset(pdfName).pages(0, 2, 1, 3, 3, 3).defaultPage(1).showMinimap(false).enableSwipe(true).onDraw(onDrawListener).onLoad(onLoadCompleteListener).onPageChange(onPageChangeListener).load();

pages和onDraw是可选项,pages:它可以让你过滤和你需要的PDF页面顺序,onDraw:允许您在当前页面画布上画上一个的东西

但是,在使用上面这个库时以为就ok了,但是pdf有多种标准(按理说是统一了的SO/DIS19005-1),但在我使用中确实有些不行,不过上面这个库已经满足了大部分的需求。

3、AndroidPdfViewer

这个处理掉了上面哪个库部分格式不支持导致崩溃的问题,也是我现在在使用的库,效果图如下:

工程于API 11及更高版本。根据Apache许可证授权2.0。
加入的build.gradle:

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

PDFView在布局

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

加载PDF文件

pdfView.fromUri(Uri)
or
pdfView.fromFile(File)
or
pdfView.fromAsset(String).pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default.enableSwipe(true).swipeHorizontal(false).enableDoubletap(true).defaultPage(0).onDraw(onDrawListener).onLoad(onLoadCompleteListener).onPageChange(onPageChangeListener).onPageScroll(onPageScrollListener).onError(onErrorListener).enableAnnotationRendering(false).password(null).scrollHandle(null).load();

enableSwipe 是可选的,它可以让你改变阻止使用刷卡页面
pages 是可选的,它可以让你筛选并定向PDF的页面,看你需要
onDraw 也是可选的,并允许你画的东西提供的画布上,在当前页面上方

源码地址:https://github.com/barteksc/AndroidPdfViewer

但是就是有点大,一集成,包就增大16MB.Android的PDF查看器取决于PdfiumAndroid,这是许多体系的设置本机库(将近16 MB)的。APK必须包含所有此库的每一个市场可用的设备上运行。幸运的是,谷歌Play可让我们上传多个APK,每每建筑如之一。有自动拆分您的应用程序分成多个APK。

Android 开发之多种方案PDF阅读相关推荐

  1. 【备忘】Google Android开发入门与实战 PDF 下载

    内容简介: 本书内容上覆盖了用Android开发的大部分场景,从Android基础介绍.环境搭建.SDK介绍.Market使用,到应用剖析.组件介绍.实例演 示等方面.从技术实现上,讲解了5个Andr ...

  2. android 使用mupdf,如何在android上嵌入mupdf作为pdf阅读器

    android 阅读器 调研pdf阅读器效果对比阅读器:有道词典网易云阅读多看阅读iReader智器阅读PDF专业阅读器Foxit PDFFBreader android 阅读器 调研 pdf阅读器效 ...

  3. javafx 订单项目源码_终于找到一个JavaFx开发的东西,pdf阅读器。包括源代码

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 imageView = new ImageView(); AnchorPane.setLeftAnchor(imageView, 0.0); Anchor ...

  4. Android开发教程PDF,安卓开发教程PDF免费版

    2019独角兽企业重金招聘Python工程师标准>>> Android开发教程(完全免费版).pdf 某500强android的内部学习资料.pdf Cocos2d-x高级开发教程. ...

  5. Android开发环境搭建与入门Hello World

    一直没机会接触手机开发,很想开发一款手机围棋软件,今天先学习一下环境搭建与Hello World吧. 环境配置对于没入门的很麻烦,谁如果有需要留下QQ邮箱,我发给你.不客气,呵呵. 推荐一本书: Go ...

  6. 最新网易微专业 Android开发系列

    目录 ├─1.Android应用界面开发 │  ├─001 Android开发简介.flv │  ├─002 开始第一个应用.flv │  ├─003 Activity你必须知道的那些事(上).flv ...

  7. android开发新浪微博客户端 完整攻略 [新手必读][转]

    开始接触学习android已经有3个礼拜了,一直都是对着android的sdk文档写Tutorials从Hello World到Notepad Tutorial算是初步入门了吧,刚好最近对微博感兴趣就 ...

  8. Android 开发:由模块化到组件化(一)

    在Android SDK一文中,我们谈到模块化和组件化,现在我们来聊聊组件化开发背后的哪些事.最早是在广告SDK中应用组件化,但是同样适用于普通应用开发 以下高能,请做好心理准备,看不懂请发私信来交流 ...

  9. android开发新浪微博客户端 完整攻略

    http://www.eoeandroid.com/forum-viewthread-tid-67298-fromuid-106432.html 开始接触学习android已经有3个礼拜了,一直都是对 ...

最新文章

  1. 完全理解 Python 迭代对象、迭代器、生成器(转)
  2. python零基础怎么学-零基础如何入门Python
  3. 使用ORM Profiler分析数据访问性能
  4. Java I/O之字节流与字符流的区别
  5. 欧科云链OKLink:以太坊上借贷协议借款量突破百亿美元
  6. 500 Internal Server Error
  7. 总结一下SQL语句中引号(')、quotedstr()、('')、format()在SQL语句中的用法
  8. 酷站欣赏:12个漂亮的国外单页网站设计案例
  9. (day 29 - 二叉树的先序遍历 )剑指 Offer 34. 二叉树中和为某一值的路径
  10. 从键盘输入一个字符串a,并在串a中的最大元素后面插入字符串b(b[]=“ab”),输出字符串a。
  11. 基于MAE的人脸素描图像属性识别和分类
  12. java nio wakeup_Java NIO wakeup实现原理
  13. 电脑上不了网,网络协商速率只有10M?
  14. 微服务:高性能网关 ShenYu简介
  15. WPS表格-快速展开全部隐藏行
  16. 手把手教大家在自己的Windows电脑上搭建一个视频电话系统(基于开源项目FreeSwitch+Linphone)
  17. 【微信小程序】如何搭积木式开发?
  18. MySQL数据库(三):数据库设计与查询语句
  19. 计算机不识别lacie硬盘,如何从LaCie Rugged 外置硬盘上恢复丢失的数据
  20. 微信小程序 实现点击按钮选择图片后显示图片并且可以预览该图片

热门文章

  1. 京东软件测试岗:惨不忍睹的三面,幸好做足了准备,月薪17k,已拿offer
  2. Microsoft Ignite China, Shenyang After Party - Power Pages Web 开发介绍 直播预告
  3. 根除任务栏天猫618超级狂欢红包广告方法,亲测有用
  4. 普京称:一旦美国向乌提供爱国者防空系统,俄罗斯将100% 摧毁它们,如何解读其表态?...
  5. php 判断是几进制,PHP取二进制文件头快速判断文件类型
  6. redis单线程理解
  7. 打新盛宴结束,HT未来之路如何?
  8. 4款令人骄傲的国产软件,每回买新电脑必装
  9. 如何登陆中继路由器进行配置管理
  10. 7月10日服务器例行维护公告,7月10日维护公告