Android端加载PDF、Word、Excel等办公文件

537 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情

之前有个项目需求是需要在App应用内显示网络文件,其中大部分文件是pdf、和word,这可把我给难住了。完全没接触过,不知道又有多少坑需要填,接下来就分享下我的探索之旅吧。

遇到未知问题第一办法就是百度或者谷歌,搜到了一些解决办法。其中有谷歌提供得一个什么API,用于在线加载,结果纯属扯皮呢,没有用,所以这里直接忽略。后来找到了一个三方库,确实可以加载PDF但好像不能加载其他格式得文件,所以也直接舍弃。最后发现,又是腾讯出品得TBS居然提供加载这类文件的功能。你说巧不巧,当时项目中使用的Webview也是TBS

接下来简单介绍下TBS:

它是依托X5内核强大的能力,致力于提供优化移动端浏览体验的整套解决方案。

一听介绍完全就是渲染网页的工具,确实也是。但内部有TbsReaderView来专门处理这些文件的加载,可以说又开启了新大陆。基础配置我们这里就不作讲解,感兴趣的可以移步到此查看

TbsReaderView控件我们需要动态配置,不能直接写入Xml中,首先布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/fram"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

其次将添加到父布局中

val params = RelativeLayout.LayoutParams(
    RelativeLayout.LayoutParams.MATCH_PARENT,
    RelativeLayout.LayoutParams.MATCH_PARENT
)
params.addRule(RelativeLayout.CENTER_IN_PARENT)
fram.addView(tvsReader, params)

接下来就是将PDF、Word等文件路径传入并加载

val bundle = Bundle()
bundle.putString("filePath", url)
bundle.putString("tempPath", Environment.getExternalStorageDirectory().path)

var result =tvsReader?.preOpen(parseFormat(File(url).name), false)
if (result!!) {
    tvsReader?.openFile(bundle)
} else {//如果不成功就使用手机上的软件打开
    QbSdk.openFileReader(
        applicationContext,
        url,
        null
    ) { p0 -> Timber.e("tbs  $p0") }
}

不出意外以上便可正常加载PDF等文件,可是多点几次发现白屏了......

原来是没做回收处理,这里必须牢记:

override fun onDestroy() {
    super.onDestroy()
    tvsReader?.onStop()
}

就这样办公文具轻松的在手机显示了,测试了好几个机型没问题。

然而......没过多久,有人反馈某某机型无法加载,加载出来是白屏。此时的我急忙掏出身边的手机挨个测试一波,没问题呀,于是卸了又装打开发现居然有一部手机会复现!!!但再次卸载又装又能显示,这真的是离了个大谱。代码就那么几行,一会行一会又不行,官网又没有相关的文档。

终于,功夫不负有心人,在网上搜到一篇文章,问题出现的原因大概意思是说X5内核初始化失败导致。于是根据他的思路,设置了一个内核初始化监听,找了个当前加载不成功的手机一试:

QbSdk.setTbsListener(object : TbsListener {
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onDownloadFinish(i: Int) {
      //完成
    }
    override fun onInstallFinish(i: Int) {
        DataHelper.setIntergerSF(mContext, Tags.ISX5, 1)
        Timber.e("finish$i")
        //内核安装完成回调,
    }

    override fun onDownloadProgress(i: Int) {
        //下载进度监听
        Timber.e("progress$i")
    }
})
QbSdk.initX5Environment(context, object : PreInitCallback {
    override fun onCoreInitFinished() {
        Timber.e("加载内核完成")
        //x5内核初始化完成回调接口,此接口回调并表示已经加载起来了x5,有可能特殊情况下x5内核加载失败,切换到系统内核。
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onViewInitFinished(b: Boolean) {
        //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
        Timber.e("加载内核是否成功:$b")
    }
})

果不其然,加载进度不到100直接就返回false。这下终于真相大白,但如果一直初始化失败怎么办?还好,经过查看相关类得知,它内部提供了一个手动下载内核的方法TbsDownloader.startDownload()。那么现在的思路就是: 1676359886634.jpg 这里要注意,重新初始化前要需要清除和重置,否则初始化可能失败:

QbSdk.clear(mContext)
QbSdk.reset(mContext)
QbSdk.clearAllDefaultBrowser(mContext)

通过日志发现,确实部分机型初始化时很慢,有可能在需要显示PDF文件的时候内核都还没下载初始化成功。所以在此需要设置个标识用于判断内核是否加载成功。到此,基本所有机型都能够正常加载,又学到了,哈哈。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情