开启掘金成长之旅!这是我参与「掘金日新计划 · 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()。那么现在的思路就是:
这里要注意,重新初始化前要需要清除和重置,否则初始化可能失败:
QbSdk.clear(mContext)
QbSdk.reset(mContext)
QbSdk.clearAllDefaultBrowser(mContext)
通过日志发现,确实部分机型初始化时很慢,有可能在需要显示PDF文件的时候内核都还没下载初始化成功。所以在此需要设置个标识用于判断内核是否加载成功。到此,基本所有机型都能够正常加载,又学到了,哈哈。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情