遇到个需求需要将app的使用手册能够在app中打开然后在线预览不用跳转其他第三方软件(WPS office)打开, 搜索一番后发现大部分用到的是PDF.js,也遇到了一些坑然后记录下来.
首先需要在xml中添加WebView
控件
然后在Activity中的onCreate()方法中调用控件
- 如何使用
方式一 :使用mozilla部署在github pages上的Viewer
这样的好处是不用添加多余的pdf.js文件 直接调用他们给定的路径传入地址即可打开,
缺点是 不能自定义
1.设置WebView:
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
- 打开pdf 传入pdf在服务器上的地址/ 也可传入pdf的本地路径
webView.loadUrl("http://mozilla.github.io/pdf.js/web/viewer.html?file=" + pdfUrl);
方式二: 下载PDF.js放到assets目录下
1,下载PDF.js, http://mozilla.github.io/pdf.js/getting_started/#download
进到页面后 反正我下载的是第一个
- 将解压出来的三个文件,放入到一个自定义名称的文件夹中,如文件夹命名为pdfjs
然后放到项目所在的assets资源文件夹下
然后按照方式一的设置, 只需修改一下路径即可, 这样就调用了刚才导入的文件
webView.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=" + pdfUrl);
但是这种方式默认只能打开本地的pdf路径
如果想预览服务器上的pdf文件需要自定义:
3. 打开assets->pdfjs->web->viewer.js文件
然后可以搜索"file origin does not match viewer's"
找到下面代码所在的位置 , 然后注释掉,就可以实现跨域访问了
方式二中pdf不可以双指放大和缩小 如果想实现需要添加下列代码
// 双指可以放大pdf
webView.setOnTouchListener(new View.OnTouchListener() {
private float OldX1, OldY1, OldX2, OldY2;
private float NewX1, NewY1, NewX2, NewY2;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_POINTER_2_DOWN:
if (event.getPointerCount() == 2) {
OldX1 = event.getX(0);
OldY1 = event.getY(0);
OldX2 = event.getX(1);
OldY2 = event.getY(1);
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 2) {
if (OldX1 == -1 && OldX2 == -1)
break;
NewX1 = event.getX(0);
NewY1 = event.getY(0);
NewX2 = event.getX(1);
NewY2 = event.getY(1);
float disOld = (float) Math.sqrt((Math.pow(OldX2
- OldX1, 2) + Math.pow(OldY2 - OldY1, 2)));
float disNew = (float) Math.sqrt((Math.pow(NewX2
- NewX1, 2) + Math.pow(NewY2 - NewY1, 2)));
Log.e("onTouch", "disOld=" + disOld + "|disNew="
+ disNew);
if (disOld - disNew >= 25) {
// 缩小
// wv.zoomOut();
webView.loadUrl("javascript:PDFViewerApplication.zoomOut()");
Log.e("onTouch", "zoomOut");
} else if (disNew - disOld >= 25) {
// 放大
// wv.zoomIn();
webView.loadUrl("javascript:PDFViewerApplication.zoomIn()");
Log.e("onTouch", "zoomIn");
}
OldX1 = NewX1;
OldX2 = NewX2;
OldY1 = NewY1;
OldY2 = NewY2;
}
break;
case MotionEvent.ACTION_UP:
if (event.getPointerCount() < 2) {
OldX1 = -1;
OldY1 = -1;
OldX2 = -1;
OldY2 = -1;
}
break;
}
return false;
}
});
如果想要禁用pdf.js自带的下载和打印功能 点击pdf.js屏蔽复制、打印、下载功能并加水印
方式三 自定义预览界面,PDF.js使用cdn的方式导入 (目前没有尝试)
1.首先写一个预览的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<title>Document</title>
<style type="text/css">
canvas {
width: 100%;
height: 100%;
border: 1px solid black;
}
</style>
<script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
</body>
</html>
2.实现预览index.js
var url = location.search.substring(1);
PDFJS.cMapUrl = 'https://unpkg.com/pdfjs-dist@1.9.426/cmaps/';
PDFJS.cMapPacked = true;
var pdfDoc = null;
function createPage() {
var div = document.createElement("canvas");
document.body.appendChild(div);
return div;
}
function renderPage(num) {
pdfDoc.getPage(num).then(function (page) {
var viewport = page.getViewport(2.0);
var canvas = createPage();
var ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({
canvasContext: ctx,
viewport: viewport
});
});
}
PDFJS.getDocument(url).then(function (pdf) {
pdfDoc = pdf;
for (var i = 1; i <= pdfDoc.numPages; i++) {
renderPage(i)
}
});
3.WebView加载html
mWebView.loadUrl("file:///android_asset/index.html?" + pdfUrl);
这样我们最终放到assets目录下的就index.html和index.js两个文件,可以避免直接全部导入带来的apk体积增大的问题,如果我们对预览UI和交互有要求的话可以方便的通过修改html来实现。
遇到的问题
在直接实现预览的时候遇到显示模糊的问题,通过增大scale系数解决
var viewport = page.getViewport(2.0);//设置为2.0
pdf内容显示不完整,通过设置cMapUrl和cMapPacked解决
PDFJS.cMapUrl = 'https://unpkg.com/pdfjs-dist@1.9.426/cmaps/';
PDFJS.cMapPacked = true;
参考:https://blog.csdn.net/lh_android/article/details/91864908?