Android端预览文件的痛点
Android中预览PDF文件看似一个很简单的需求,其实在Android碎片化的版本和众多品牌中实则很难统一,更是难兼容。
简单说一下Android中打开PDF文件的几种方式
-
通过外部应用打开项目内文件,如WPS。这种虽然开发省事但遇到一些不太熟悉手机的用户会经常打不开文件。Android开发总所周知,通过Intent打开外部应用。如果有相同功能的应用会有弹窗列表来选择其中某一个,通过仅一次或总是的方式打开。点击总是的话,当这个应用卸载就会出问题。点击仅一次的话,下次打开文件还会弹出这个列表,操作未免有些繁琐。
-
在项目内打开。相比通过外部应用打开这种方案在用户体验上更好一些,但要么需要收费要么需要集成到项目中做一系列开发,比较麻烦。一些开源的Android端的预览项目也好些年不更新了,出了问题看源码也费劲。
这我就要推荐只需要服务端简单部署,Android只需要拼接下Url,就能在项目内预览的终极方案KKFileView,且开源免费。官网kkFileView - 在线文件预览
KKFileView
这是Windows发布包解压后的文件,可用于Android端本地测试
双击bin目录下的startup.bat,无法运行常识管理员权限运行或者重启电脑
运行后会挂起一个cmd窗口
然后就可以在浏览器中访问这个本地的解析服务,地址 http://127.0.0.1:8012
在Android中通过WebView加载Url的方式去解析PDF做到项目内在线浏览
1.模拟器中访问本地服务
模拟器中需要使用 http://10.0.2.2:8012 这个地址去拼接,http://10.0.2.2:8012/onlinePreview?url= + 线上文件地址。如果线上地址是stream流需要增加 &fullfilename=文件名 , stream解析的完整地址为http://10.0.2.2:8012/onlinePreview?url= + 线上文件地址+?fullfilename=文件名。文件名必须是以pdf,docx等文档格式结尾的文件名。如果不是stream流的形式则不需要增加 ?fullfilename。地址需要用base64和Uri.encode编码。完整代码如下:
mBrowserView?.loadUrl("http://10.0.2.2:8012/onlinePreview?url=${encodeFileUrl("http://****.***.**:*****/download/$id/stream",file.name)}")
fun encodeFileUrl(baseUrl: String,fullfilename: String=""): String {
val base64 = "${baseUrl}?fullfilename=$fullfilename"
return Uri.encode(Base64.encodeToString(base64.toByteArray(), Base64.NO_WRAP))
}
2.真机访问本地服务
代码都一样只是需要更换IP地址,打开cmd命令窗口输入命令ipconfig查看ipv4的地址,再确保手机Wifi的IP地址和电脑的ipv4地址相同,处于同一网络环境下。将解析地址更换为ipv4地址即可。
兼容性问题
Android端通过WebView加载出来的PDF默认是图片样式,图片会大于屏幕无法完整显示。需要加入head meate 的 viewport。具体代码:
/**
* 完成加载网页
*/
override fun onPageFinished(view: WebView, url: String) {
val js = "javascript:(function(){" +
"var meta = document.createElement('meta');" +
"meta.name='viewport';" +
"meta.content='width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes';" +
"document.getElementsByTagName('head')[0].appendChild(meta);" +
"})()"
view.evaluateJavascript(js, null)
// 同时强制图片自适应(针对 kkFileView 图片预览)
val imgCss = "javascript:(function(){" +
"var style = document.createElement('style');" +
"style.innerHTML = 'img, .picture-img { max-width:100% !important; height:auto !important; width:auto !important; } body{margin:0 !important;}';" +
"document.head.appendChild(style);" +
"})()"
view.evaluateJavascript(imgCss, null)
}