当前位置: 移动技术网 > IT编程>开发语言>Java > 作为一个java后端程序员,我是怎么接手android项目,并完成移动端的pdf处理需求的?

作为一个java后端程序员,我是怎么接手android项目,并完成移动端的pdf处理需求的?

2020年07月08日  | 移动技术网IT编程  | 我要评论

本篇文章核心:Android调用第三方应用,打开pdf文件
作为一个纯的java后端程序员,最近因为公司需要,不得不暂时负责维护一个android项目。
现在项目到了需要修改的时候了。
App功能涉及到预览pdf,并且还要支持添加注释、书签、查看文档目录等功能,需求还能更复杂一些吗?对于一个纯的java后端程序员来讲,大概很少有更难受的事情了,我太难了。
所以最后我选择了跟我的领导大吵一架,接着愤而辞职!!!来表达我的不满!!!
至于为什么会有这篇文章,哼哼… …
此时… …我想你已经猜到答案了。
什么?你没猜到?那先容我卖个关子,在文章最后,再讲为什么有这篇文章。

现在,先进入主题。讲一讲android怎么调用第三方应用打开pdf文件

当然,你肯定早就在其他地方看到解决方法了,并且他们还提供了各种Intent,比如调用播放mp3的应用,播放mp4的应用,查看图片的应用等等。
这么一讲,我写这篇文章不是显得很鸡肋吗,直接转载别人的文章,不是更轻松吗?
绝对不是!作为一个“资(菜)深(鸡)”的android程序员,我列出了写代码的过程中遇到的所有问题,和思考问题的一些方式,以及解决方案。
其中包括困扰了我这个“大牛”两天的问题。

调用第三方应用打开pdf文件,也有两种方式。

方式一

列出所有能打开pdf的应用,让用户选择一个应用打开。
首先贴出实现效果:
在这里插入图片描述

主要代码如下:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW); 
Uri uri = Uri.fromFile(new File(path)); 
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);

你很容易就能在其他博客中看到这种方式对不对?但是在android7.0以上的系统中使用就会有问题了,报错信息如下:android.os.FileUriExposedException: file:///xxx.pdf exposed beyond app through Intent.getData()
在这里插入图片描述
在这里插入图片描述

这是因为Android7.0 以上,对于权限相关控制更为严格,更何况笔者是基于android9.0系统进行开发,所以需要按照如下方式做一些配置。

1.在 res目录下创建provider_paths.xml
在这里插入图片描述

2.provider_paths.xml内容

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

3. AndroidManifest.xml 添加节点

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@drawable/ic_launcher"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"
    android:usesCleartextTraffic="true">
     … …
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
</application>

4.获取uri方式修改

//Uri uri = Uri.fromFile(new File(path));
Uri 获取方式从上面的代码替换为下面
Uri uri = FileProvider.getUriForFile(getApplicationContext(), 
getApplicationContext().getPackageName() + ".provider", new File(path));

5.提供完整代码

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW); 
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION );
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

Uri uri = FileProvider.getUriForFile(getApplicationContext(), 
getApplicationContext().getPackageName() + ".provider", new File(path)); 
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);

注意此处,Intent的Flags设置。必须给予读的权限,否则会出现”pdf损坏,无法打开”的提示。
在这里插入图片描述
否则出现”pdf损坏,不能读取“。
在这里插入图片描述

方法二

指定应用启动。即,用户不需要选择,默认使用我们选择的pdf阅读器打开。
同样需要按方法一种的前两步,添加provider_paths.xml,修改AndroidManifest.xml
贴出主要代码:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setPackage("com.buildtoconnect.pdfreader");
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION );
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

//7.0 兼容
Uri uri = FileProvider.getUriForFile(getApplicationContext(), 
getApplicationContext().getPackageName() + ".provider", new File(path)); 
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);

最主要的代码是这一行:

intent.setPackage("com.buildtoconnect.pdfreader");

设置要使用的pdf阅读器的包名,此处我使用的是17pdf阅读器。如果使用adobe的pdf阅读器,它的包名为“com.adobe.reader”,关于包名的获取,可以使用反编译,也可以利用安卓的api,获取手机中安装的应用,遍历查找,建议自行搜索。网上这类的文章很多,笔者是使用的反编译的方式获取的。

到此,使用第三方应用打开pdf的两种方式介绍完毕。具体使用哪一种根据各自的业务需求决定。
但是!!
等等… …毕竟说了当前属于“资(菜)深(鸡)”android程序员,事情怎么会如此顺利??
简单测试后发现,果然还有问题!!!
在这里插入图片描述
什么情况,为什么不能添加注释?不能添加书签?
还有这个… …流文件?
在这里插入图片描述

于是,我陷入了深深的沉思。开始“全网搜”历程,诸如“android使用第三方应用打开pdf 不能编辑?”、“android使用第三方应用打开pdf 不能添加注释?”
这一沉思,就是两天,在这期间,我注意到一个细节。看图:
在这里插入图片描述

没错,文件名发生了变化,“软件测试计划.pdf”在阅读器中打开,变成了“122333444.pdf”
所以我推断出,用这种方式打开pdf,实际上不是打开的原文件,而是生成了一个临时文件,且是只读的临时文件。
这里顺带提一下,这个问题不是pdf阅读器本身的问题,因为在adobe中,用这种方式打开,同样不能编辑,提示“受保护的文件,不能执行操作”。

接下来就是黑暗的全网搜时段,甚至最后我都要放弃了,打算自己尝试做应用内打开算了,不然就陷入了无底洞呀。

就在这时候,我翻到一篇博客(博客地址忘记记录啦),提到另一种方式,处理android.os.FileUriExposedException: file:///xxx.pdf exposed beyond app through Intent.getData() 异常。
于是我尝试了以下写法,并且最终问题解决,附上主要源码

//使用17pdf阅读器 打开pdf  com.buildtoconnect.pdfreader
 Intent intent = new Intent();
 intent.setAction(Intent.ACTION_VIEW);
 intent.setPackage("com.buildtoconnect.pdfreader");
 intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION );
 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

 File pdfFile = new File(path);
 if(!pdfFile.exists()){
     Toast.makeText(getApplicationContext(),
      "pdf文件不存在!", Toast.LENGTH_SHORT).show();
     return;
 }
 //7.0 兼容
 Uri uri = Uri.fromFile(new File(path));
 StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
 StrictMode.setVmPolicy(builder.build());

 intent.setDataAndType(uri, "application/pdf");
 startActivity(intent);

就是这一段:

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
 StrictMode.setVmPolicy(builder.build());

前后折腾了两天,总算是搞定了。

最后,如果只是预览pdf,并且需要在应用内打开pdf,推荐使用github上面的一个开源库PdfViewer,项目地址: https://github.com/barteksc/AndroidPdfViewer
使用比较简单,比较容易实现功能。
如果需要在应用内打开pdf,建议可以参考这篇文章:android 在线预览pdf文件(目前最全)

咳咳,现在揭晓谜底的时候到了。为什么还有这篇文章了?
当然是因为我对技术孜孜不倦的钻研态度,即便是已经离职,还是要把问题解决了!!
???不信。
好吧,辞职当然不能随便辞的,文章开头就随便一说,既然接了项目,还是得做才行。哈哈哈… …

本文地址:https://blog.csdn.net/VA_AV/article/details/107133209

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网