Android之预览PDF文件

     上周临时收到客户的说明书,说要放在应用里显示,本来觉得一个非常简单的事情没想到一波三折。

      第一波:我使用了pdfViewer控件:(相了解的可以查看:https://github.com/barteksc/AndroidPdfViewer)

      遇到的坑就是 因为设备是横屏的,这个控件在手机上预览pdf很不错,我一下子没有找到横向铺满的方法,因此显示起来页面显的非常小,由于时间比较急没有去细细研究所以弃用了。

      第二波:到这个时候我就立马换了一个思路。改用WebView,过程稍微复杂点 但是效果还是不错的 满足了需求。

      首先,下载PDF.js放到assets目录下。如下:  

         

 

         然后就是使用:布局文件就不贴出来了。

private void loadWebPdf() {webView = (WebView) findViewById(R.id.pdf_webView);WebSettings webSettings = webView.getSettings();webSettings.setJavaScriptEnabled(true);webSettings.setAllowFileAccess(true);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {webSettings.setAllowUniversalAccessFromFileURLs(true);webSettings.setAllowUniversalAccessFromFileURLs(true);}webView.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=" + "file:///android_asset/vehicle-help-chinese.pdf");}

感觉一切都是相当的完美。如果是一般应用到这里也就没什么问题了。

第三波: 运行的时候发现系统一直报 Error inflating class android.webkit.WebView.这就很尴尬了,然后查了下,试了几个方法都没有用,后面仔细看还有For security reasons, WebView is not allowed in privileged processesFor security reasons, WebView is not allowed in privileged processes(出于安全原因,特权进程中不允许使用WebView。出于安全原因,特权进程中不允许使用WebView)。这就很尴尬了,忘了说了应用是系统及应用系统版本7.1.2。(Android开发系统应用(android.uid.system)使用webview报错)。

 

查了下 谷歌不知道从啥时候开始全面禁止系统应用使用webview。查看源码获悉在WebviewFactory代码中某个静态实例初始化之前判断api版本并抛出错误。知道是这个原因后,心里有底了,方法总比困难多嘛,既然准备用WebView来预览pdf了就不要轻易放弃。方向如下:

在使用webview之前,使用hook(钩子)方法,给该变量赋值。哈哈 这样就可以避免这个问题了;代码如下:

/** * 使用WebView避免系统检查抛出异常 */public static void checkWebView() {LogUtils.d(TAG, "checkWebView()");int sdkInt = Build.VERSION.SDK_INT;try {//拿到 WebViewFactory 类Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");//拿到类对应的 fieldField field = factoryClass.getDeclaredField("sProviderInstance");//field为private,设置为可访问的field.setAccessible(true);//拿到 WebViewFactory 的 sProviderInstance 实例//sProviderInstance 是 static 类型,不需要传入具体对象Object sProviderInstance = field.get(null);if (sProviderInstance != null) {return;}Method getProviderClassMethod;if (sdkInt > 22) {getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");} else if (sdkInt == 22) {getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");} else {return;}getProviderClassMethod.setAccessible(true);Class<?> providerClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");Constructor<?> providerConstructor = providerClass.getConstructor(delegateClass);if (providerConstructor != null) {LogUtils.d(TAG, "providerConstructor != null");providerConstructor.setAccessible(true);Constructor<?> declaredConstructor = delegateClass.getDeclaredConstructor();declaredConstructor.setAccessible(true);//利用反射创建了 sProviderInstancesProviderInstance = providerConstructor.newInstance(declaredConstructor.newInstance());//完成 sProviderInstance 赋值field.set("sProviderInstance", sProviderInstance);}} catch (Throwable e) {e.printStackTrace();}}

搞定收工,预览了下效果还是蛮不错的。只是加载稍微有点点慢。

 

更多相关文章

  1. android面试题(一)
  2. Android(安卓)View(二)-View的scrollTo()以及scrollBy()说明
  3. 为 Android(安卓)添加 Java 层服务也就是添加自定义的aidl服务到
  4. Android(安卓)根据系统声音模式设置提醒方式
  5. Android(安卓)应用程序安装方式 的详细调研
  6. Android(安卓)调用系统搜索框
  7. Android(安卓)tips(十三)-->Android开发过程中使用Lambda表达式
  8. Android启动流程---App层
  9. 详解Serializable

随机推荐

  1. SD卡读写文件 代码学习
  2. [Android]Android的常用adb命令
  3. android joystick 游戏摇杆
  4. Android(安卓)深入解析selector
  5. Android(安卓)APK常驻内存解决方案
  6. android 存储联系人(save contact) 总结
  7. Android中主题的添加
  8. Android源码分析(四)-----Android源码编译
  9. Android(安卓)Toolbar
  10. scrollbarsstyle