基于腾讯浏览服务 TBS 实现应用内打开并浏览 Office 文件
2017-10-22 13:03
831 查看
众所周知,Android App 在国内环境下实现应用内打开本地或位于远程服务器上 word、excel、pdf 等 Office 文档的功能远远没有 iOS 系统方便得多。之前也写过一篇文章,罗列出现有解决方案间的优劣对比。直到最近,在网上又发现一种新的解决方案:腾讯浏览服务(简称:TBS)。
TBS 简单介绍
正如官网所言,依托 X5 内核强大的能力,TBS 致力于提供优化移动端浏览体验的整套解决方案。TBS 虽然核心在于提供一套 SDK 解决传统 WebView 的诸多使用问题。但是,利用其增强浏览能力,我们还能够使用这套 SDK 实现应用内的文件浏览功能、视频播放功能等。更多详细功能,可以参考官网介绍:https://x5.tencent.com/tbs/product/tbs.html
然而,美中不足的是,在浏览文件方面,官方没有提供完善的使用文档和 Demo 案例。经过一番折腾,和借鉴这篇文章 ,总算能够实现应用内打开 Office 文档的功能,于是整理于此。
本地文件浏览
注意:TBS 只能打开浏览本地文件,对于位于服务器的远程文件,无法实现在线预览,只能通过先下载再打开的方式进行浏览。这里我们先来看看如何使用 TBS 打开本地文件。首先还是添加 SDK 依赖。下载 TBS 提供的 jar 包和 so 文件,添加到工程中对应的 libs 和 jniLibs 目录下。如图:
然后在 app/build.gradle 文件中对 libs 目录中 jar 文件的依赖可以是这样:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }
**需要注意的是:**TBS 目前只提供 armeabi 类型 CPU 架构的 so 库。当然,也可以将 so 文件放置于 libs 目录下,只不过需要在 app/build.gradle 中额外修改 so 文件依赖配置:
android { sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
配置完成之后,再来看看如何使用。这里主要使用的是
TbsReaderView类。在宿主 Activity 中实现
ReaderCallback接口,并通过 Java 代码动态创建 TbsReaderView 对象,将其添加到 content view 当中。比如:
mTbsReaderView = new TbsReaderView(this, this); RelativeLayout rootRl = (RelativeLayout) findViewById(R.id.rl_root); rootRl.addView(mTbsReaderView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
ReaderCallback接口提供的方法可以不予处理(目前不知道有什么用途,但是一定要实现这个接口类):
@Override public void onCallBackAction(Integer integer, Object o, Object o1) { }
可能你会有疑惑,为什么不将
TbsReaderView放在 layout 布局文件中,而是在代码中手动 add 进去。经测试,这么做会报错,提示找不到这个类。然后我们查看
TbsReaderView源码,发现只有这么一个构造函数:
public TbsReaderView(Context var1, TbsReaderView.ReaderCallback var2) { super(var1.getApplicationContext()); if(!(var1 instanceof Activity)) { throw new RuntimeException("error: unexpect context(none Activity)"); } else { this.d = var2; this.a = var1; this.e = new au(this); } }
而没有提供含
AttributeSet类型参数的构造函数,也就是说,这个版本的 TBS 只允许我们通过 new 的方式创建
TbsReaderView实例并使用。
说完这个,再接着看如何打开本地文件。代码也很简单:
private void displayFile() { Bundle bundle = new Bundle(); bundle.putString("filePath", getLocalFile().getPath()); bundle.putString("tempPath", Environment.getExternalStorageDirectory().getPath()); boolean result = mTbsReaderView.preOpen(parseFormat(mFileName), false); if (result) { mTbsReaderView.openFile(bundle); } }
可以看到,通过
Bundle类型参数的形式向
TbsReaderView对象传递文件地址和另一个临时目录地址。这两个数据,缺一不可。
这里可能大家又有疑问,没有文档介绍,我们是如何知道
Bundle参数传递哪些数据的呢?还是查看
TbsReaderView源码,在该类中存在这两个成员变量:
public static final String KEY_FILE_PATH = "filePath"; public static final String KEY_TEMP_PATH = "tempPath";
第一个参数很好理解,第二个参数不知道什么意思,根据名字需要的应该是一个临时目录地址,反正传上就对了。这里顺便教大家两个技巧,以后阅读 Jar 包源码时也许能够用得上:
1,如何搜索 jar 包中的指定类文件?
使用
jar -tf命令能够列出 jar 包中的内容,如果再配上 grep 命令便能搜索指定类文件,如:
yifeng:desktop yifeng $ jar -tf tbs_sdk_thirdapp.jar | grep -i TbsReaderView com/tencent/smtt/sdk/TbsReaderView$ReaderCallback.class com/tencent/smtt/sdk/TbsReaderView.class
2,如何搜索 jar 包中的指定字符串?
使用 zipgrep 命令,如果搜索的关键字包含空格,则需要使用引号:
yifeng:desktop yifeng $ zipgrep filePath tbs_sdk_thirdapp.jar com/tencent/smtt/sdk/TbsReaderView.class:Binary file (standard input) matches
回到 TBS 使用上,最后别忘了在
onDestroy()生命周期函数中添加:
@Override protected void onDestroy() { super.onDestroy(); mTbsReaderView.onStop(); }
至此,使用 TBS 实现应用内打开预览本地 Office 文件的全部过程结束,我们来看一下效果图:
可以看到,第一次使用需要下载腾讯提供的 pdf 浏览插件,之后打开时则无需再次加载。
更多时候,我们预览的文件都位于远程服务器上。所以,我们需要预先下载文件,下载完成之后再使用 TBS 打开本地文件。感兴趣的话,不妨继续来看。
远程文件下载
Android App 下载文件的方式有很多,这里我们使用一种最简单的方式来做,利用系统提供的DownloadManager类来实现下载功能,并监听下载进度。
先来看看如何利用
DownloadManager下载文件。根据使用场景,这里我屏蔽默认的通知栏提示消息,并设置本地存放位置,相关代码如下:
mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mFileUrl)); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mFileName); request.allowScanningByMediaScanner(); request.setNotificationVisibility(Request.VISIBILITY_HIDDEN); mRequestId = mDownloadManager.enqueue(request);
然后是监听下载进度,使用的是
ContentObserver类。自定义一个继承自
ContentObserver的监听类:
private class DownloadObserver extends ContentObserver { private DownloadObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { queryDownloadStatus(); } }
在
onChange()回调方法中实时查询下载进度。当查询到下载完成时,使用 TBS 打开下载到本地对应目录的文件:
private void queryDownloadStatus() { DownloadManager.Query query = new DownloadManager.Query().setFilterById(mRequestId); Cursor cursor = null; try { cursor = mDownloadManager.query(query); if (cursor != null && cursor.moveToFirst()) { //已经下载的字节数 int currentBytes = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); //总需下载的字节数 int totalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); //状态所在的列索引 int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); Log.i("downloadUpdate: ", currentBytes + " " + totalBytes + " " + status); mDownloadBtn.setText("正在下载:" + currentBytes + "/" + totalBytes); if (DownloadManager.STATUS_SUCCESSFUL == status && mDownloadBtn.getVisibility() == View.VISIBLE) { mDownloadBtn.setVisibility(View.GONE); mDownloadBtn.performClick(); } } } finally { if (cursor != null) { cursor.close(); } } }
做好这些准备后,在下载文件的时候注册监听:
mDownloadObserver = new DownloadObserver(new Handler()); getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, mDownloadObserver);
并在
onDestroy()方法中取消监听:
@Override protected void onDestroy() { super.onDestroy(); if (mDownloadObserver != null) { getContentResolver().unregisterContentObserver(mDownloadObserver); } }
最后,别忘记在 Manifest 清单文件中添加相应使用权限(权限含义,就不再一一介绍):
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
总体来看,TBS 提供的文件浏览功能还是很强大的。据官网介绍,目前能够支持 42 种不同格式的文件。除此之外,TBS 还有一些其他的用途也非常值得尝试。只是,期待官方能够提供更多的使用文档介绍,帮助我们更方便地使用起来。
备注:
本文相关代码已上传至 GitHub 网站,有需要的朋友可以访问地址:
https://github.com/Mike-bel/TbsFileSamples
关于我:亦枫,博客地址:http://yifeng.studio/,新浪微博:IT亦枫
微信扫描二维码,欢迎关注我的个人公众号:安卓笔记侠
不仅分享我的原创技术文章,还有程序员的职场遐想
相关文章推荐
- Android应用内展示office文件--腾讯浏览服务(TBS)
- Android应用内实现视频播放--腾讯浏览服务(TBS)
- Android实现视频播放--腾讯浏览服务(TBS)功能
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务2[使用IE浏览本页]
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务3[聊天室][使用IE浏览本页]
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务4[聊天室][使用IE浏览本页]
- 【CSDN开源夏令营】 基于Web的SSH客户端,实现跨平台的云服务管理(四)文件树功能的实现
- MFC实现打开、保存文件对话框和浏览文件夹对话框
- 基于服务(Web Service)的文件管理Winform客户端实现(二)
- 实现让你的应用在其他应用中文件的打开方式列表中显示
- 基于 lua-resty-upload 实现简单的文件上传服务
- 基于zookeeper应用——简单统一命名服务实现
- 基于服务(Web Service)的文件管理Winform程序实现
- Android 实现应用下载并在通知栏展示进度通知 打开APK文件
- 使用 Google App Engine 实现基于云计算的小型 Java 数据服务应用
- MFC实现打开、保存文件对话框和浏览文件夹对话框
- 实现基于Spring技术应用的远程服务编程
- MFC实现打开、保存文件对话框和浏览文件夹对话框 .
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务1[使用IE浏览本页]
- MFC实现打开、保存文件对话框和浏览文件夹对话框