不同于 iOS,Android 的 webView 不支持打开 office 和 pdf 文档,所以当我们遇到在应用内打开 office 和 pdf 文档的需求时,往往无法从系统原生功能去支持。这篇文章的写下笔者在 Android 应用中集成 office 和 pdf 文件能力的心得,附上 demo 地址:github.com/windinwork/…

一、确定解决方案

Android 应用打开 office 和 pdf 文件。常用的有以下四种解决方案:

  1. 在线网页打开文件方案:通过微软或谷歌提供的在线页面打开 office 和 pdf 文件
  2. 集成相关文档处理开源库:通过集成开源库类似于 AndroidPdfViewer
  3. 通过系统中的第三方应用打开文档
  4. 集成腾讯 x5 sdk 文件能力

四种方案各有优劣,这里笔者选择了 x5 sdk 为主要手段,第三方应用辅助的这样一种解决方案

二、集成 x5 内核

腾讯官方提供的 x5 内核有两个版本,这里选择具有文件能和的 sdk:

接下来的集成可以参考x5 内核接入文档,这里便不详述。集成的主要工作便是集成 jar 包和 so 文件,并在 Application 初始化时调用 QbSdk.initX5Environment(context, callback) 来完成初始化工作。

三、集成 TbsReader

x5 内核中提供了 TbsReaderView,让我们可以通过这个类在 App 中显示文档。考虑到 TbsReaderView 这个类具有生命周期的方法,我们把它封装在一个 Fragment 中,方便我们的调用。TbsReaderView 的主要方法有两个,一个是 preOpen(String, boolean),另一个是 openFile(Bundle)。preOpen(String, boolean) 是用来检测 x5 文件能力是否成功初始化和是否支持打开文件的格式,当符合打开文件的条件时该方法返回 true;openFile(Bundle) 则是在 preOpen(String, boolean) 的返回值为 true 的情况进行调用,顾名思义这个方法是用来打开文件的,其中 bundle 用来传入文件路径。

String path = file.getPath();
String format = parseFormat(path);
boolean preOpen = mReaderView.preOpen(format, false); // 该状态标志x5文件能力是否成功初始化并支持打开文件的格式
if (preOpen) { // 使用x5内核打开office文件
    Bundle bundle = new Bundle();
    bundle.putString("filePath", path);
    bundle.putString("tempPath", StorageUtils.getTempDir(context).getPath());
    mReaderView.openFile(bundle);
}
复制代码

有了这部分核心代码,TbsReaderView 基本上就能打开 Office 和 PDF 文件了。

四、完善文件能力

市面上的安卓手机各式各样,虽然集成了 TbsReaderView,但是还是会收到用户反馈说无法打开 Office 文件。这是因为用户手机上的 x5 文件能力没有初始化成功,至于为什么没有初始化成功,原因还无法确定。针对这部分用户,我们需要在他们无法使用 TbsReaderView 浏览 Office 文件的情况下,提供另外的途径去打开 Office 文件。大致思路是检测到 TbsReaderView 无法打开 Office 或 PDF 时,跳转到第三方应用去打开。这里 x5 的 jar 包提供了这样一个 api:openFileReader(Context, String, HashMap<String, String>, ValueCallback) 用来使用第三方应用打开文件,并且支持前往下载具有 Office 浏览功能的 QQ 浏览器,这样的功能对用户比较友好,我们可以直接拿来用。

然而,x5 的 jar 包中使用第三方应用打开时调用了 Uri.fromFile(file),这个生成文件 Uri 的方法在 Android7.0 以下有效,但在 Android7.0 及以上会造成崩溃,这是 Android7.0 的文件权限管理导致。为了使 Android7.0 及以上的用户可以正常跳转到第三方应用打开,我们需要使用 FileProvider 去获取 Uri,但代码在 Jar 包中写死了。幸运的是,经过多次尝试,发现可以将跳转到第三方应用打开的这部分代码复制出来,修正 Uri.fromFile(file) 的代码以正常调用,免去了要修改 jar 的麻烦。这里笔者把这部分代码封装在一个叫 TbsReaderAssist 的类中,辅助调用。

这样一来,一个比较完善的打开 Office 和 PDF 的功能就算做完成。

String path = file.getPath();
String format = parseFormat(path);
boolean preOpen = mReaderView.preOpen(format, false); // 该状态标志x5文件能力是否成功初始化并支持打开文件的格式
if (preOpen) { // 使用x5内核打开office文件
    Bundle bundle = new Bundle();
    bundle.putString("filePath", path);
    bundle.putString("tempPath", StorageUtils.getTempDir(context).getPath());
    mReaderView.openFile(bundle);
} else { // 打开文件失败,可能是由于x5内核未成功初始化引起
    if (QbSdk.isSuportOpenFile(format, 1)) { // 再次检查文件是否支持
        HashMap<String, String> params = new HashMap<>();
        params.put("style", "1");
        params.put("local", "false");
        TbsReaderAssist.openFileReader(context, path, params, null);
    }
}
复制代码

五、总结

这里笔者写了一个 App 打开 Office 或 PDF 文件的解决方案,个人认为对于一个 App 来说是相对完善的处理。这里是 demo 的地址:github.com/windinwork/…,共享出来,可以让有需要做类似功能的小伙伴少走些弯路。

  • Android

    开放手机联盟(一个由 30 多家科技公司和手机公司组成的团体)已开发出 Android,Android 是第一个完整、开放、免费的手机平台。

    293 引用
感谢    赞同    分享    收藏    关注    反对    举报    ...