有时我们在APP里会有浏览的需求,常见的文件有Word、Excel、ppt、pdf等格式的文件,这里我选用了腾讯的TBS浏览服务。在这里记录一下,方便以后使用,有需要的朋友也可以参考一下。下面就来看一下怎样集成TBS。

先来张效果图看下

首先下载腾讯浏览服务SDK,下载地址:https://x5.tencent.com/tbs/sdk.html,接入文档地址:https://x5.tencent.com/tbs/guide/sdkInit.html,下载完导入jar包和.so文件。

在app的build.gradle里配置

android {compileSdkVersion 28defaultConfig {……//X5兼容64位手机ndk {abiFilters "armeabi", "armeabi-v7a", "x86", "mips"}}buildTypes {……}
}dependencies {……//网络请求okhttp3implementation 'com.squareup.okhttp3:okhttp:3.12.0'//Retrofit2库implementation 'com.squareup.retrofit2:retrofit:2.3.0'//gson解析implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//TBS腾讯浏览服务implementation files('libs/tbs_sdk_thirdapp_v4.3.0.1148_43697_sharewithdownloadwithfile_withoutGame_obfs_20190805_175505.jar')
}

在AndroidManifest.xml里加入如下权限

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在Application 的onCreat()里加入

//增加这句话
QbSdk.initX5Environment(this,null);

自定义一个现实文件的ViewSuperFileView

package com.wjy.project.mytbs;import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.LinearLayout;import com.tencent.smtt.sdk.TbsReaderView;import java.io.File;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;/*** Created by wjy on 2020/2/11* 自定义文件打开阅读View*/
public class SuperFileView extends FrameLayout implements TbsReaderView.ReaderCallback {private static String TAG = "SuperFileView";private Context context;private TbsReaderView mTbsReaderView;private OnGetFilePathListener mOnGetFilePathListener;public OnGetFilePathListener getOnGetFilePathListener() {return mOnGetFilePathListener;}public void setOnGetFilePathListener(OnGetFilePathListener mOnGetFilePathListener) {this.mOnGetFilePathListener = mOnGetFilePathListener;}public SuperFileView(@NonNull Context context) {this(context, null, 0);}public SuperFileView(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public SuperFileView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.context = context;mTbsReaderView = new TbsReaderView(context, this);this.addView(mTbsReaderView, new LinearLayout.LayoutParams(-1, -1));}@Overridepublic void onCallBackAction(Integer integer, Object o, Object o1) {Log.e(TAG,"****************************************************" + integer);}/**** 获取File路径*/public interface OnGetFilePathListener {void onGetFilePath(SuperFileView mSuperFileView);}/*** 展示*/public void show() {if(mOnGetFilePathListener!=null){mOnGetFilePathListener.onGetFilePath(this);}}/*** 显示文件的界面,退出界面以后需要销毁,否则再次加载文件无法加载成功,会一直显示加载文件进度条。*/public void onStopDisplay() {if (mTbsReaderView != null) {mTbsReaderView.onStop();}}/*** 显示文件*/public void displayFile(File mFile){if (mFile != null && !TextUtils.isEmpty(mFile.toString())){//增加下面一句解决没有TbsReaderTemp文件夹存在导致加载文件失败String bsReaderTemp = "/storage/emulated/0/TbsReaderTemp";//SD卡下面文件路径File bsReaderTempFile =new File(bsReaderTemp);if (!bsReaderTempFile.exists()){//如果SD卡下不存在TbsReaderTemp文件夹Log.e(TAG,"准备在SD卡下创建TbsReaderTemp文件夹!");boolean mkdir = bsReaderTempFile.mkdir();if(!mkdir){Log.e(TAG,"创建/storage/emulated/0/TbsReaderTemp失败!!!!!");}}//加载文件Bundle localBundle = new Bundle();Log.e(TAG,"mFile.toString()="+mFile.toString());localBundle.putString("filePath", mFile.toString());localBundle.putString("tempPath", Environment.getExternalStorageDirectory() + "/" + "TbsReaderTemp");if (mTbsReaderView == null){mTbsReaderView = new TbsReaderView(context,this);}boolean bool = mTbsReaderView.preOpen(getFileType(mFile.toString()), false);if (bool){mTbsReaderView.openFile(localBundle);}}else {Log.e(TAG,"文件路径无效!");}}/**** 获取文件类型** @param paramString* @return*/private String getFileType(String paramString){String str = "";if (TextUtils.isEmpty(paramString)) {Log.e(TAG, "paramString---->null");return str;}Log.e(TAG, "paramString:" + paramString);int i = paramString.lastIndexOf('.');if (i <= -1) {Log.e(TAG, "i <= -1");return str;}str = paramString.substring(i + 1);Log.e(TAG, "paramString.substring(i + 1)------>" + str);return str;}
}

之后就可以在使用了,新建打开文件的Activity页面FileDisplayActivity

package com.wjy.project.mytbs;import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;import androidx.annotation.Nullable;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;/*** Created by wjy on 2020/2/11* 文件打开阅读页面*/
public class FileDisplayActivity extends Activity {SuperFileView mSuperFileView;String filePathUrl;private TextView tv_progress;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_filedisplay);filePathUrl = getIntent().getStringExtra("filePath");Log.e("tag","filePathUrl="+filePathUrl);init();}private void init(){tv_progress = findViewById(R.id.tv_progress);mSuperFileView = findViewById(R.id.mSuperFileView);mSuperFileView.setOnGetFilePathListener(new SuperFileView.OnGetFilePathListener() {@Overridepublic void onGetFilePath(SuperFileView mSuperFileView) {openFile(filePathUrl,mSuperFileView);//获取文件路径并打开文件}});mSuperFileView.show();}@Overrideprotected void onDestroy() {super.onDestroy();Log.e("tag","FileDisplayActivity-->onDestroy");if (mSuperFileView != null) {mSuperFileView.onStopDisplay();}}/*** 打开文件文件* @param filePathUrl* @param mSuperFileView*/private void openFile(final String filePathUrl,final SuperFileView mSuperFileView){//从缓存获取文件File cacheFile = FileTools.getCacheFile(filePathUrl);if (cacheFile.exists()) {//如果文件存在if (cacheFile.length() <= 0) {Log.e("tag", "删除空文件!!");cacheFile.delete();return;}Log.e("tag","如果文件存在"+cacheFile.exists());mSuperFileView.displayFile(cacheFile);//直接打开文件}else {tv_progress.setVisibility(View.VISIBLE);//如果文件不存在,则在网络先下载然后再打开requestDownLoadFile();}}/*** 从网络下载文件*/private void requestDownLoadFile(){//网络下载LoadFileModel.loadFile(filePathUrl, new Callback<ResponseBody>() {@Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {Log.e("tag", "下载文件-->onResponse");InputStream is = null;byte[] buf = new byte[2048];int len = 0;FileOutputStream fos = null;try {ResponseBody responseBody = response.body();is = responseBody.byteStream();long total = responseBody.contentLength();File file1 = FileTools.getCacheDir();if (!file1.exists()) {file1.mkdirs();Log.e("tag", "创建缓存目录: " + file1.toString());}File fileN = FileTools.getCacheFile(filePathUrl);Log.e("tag", "创建缓存文件: " + fileN.toString());if (!fileN.exists()) {boolean mkdir = fileN.createNewFile();}fos = new FileOutputStream(fileN);long sum = 0;while ((len = is.read(buf)) != -1) {fos.write(buf, 0, len);sum += len;int progress = (int) (sum * 1.0f / total * 100);Log.e("tag", "写入缓存文件" + fileN.getName() + "进度: " + progress);}fos.flush();Log.e("tag", "文件下载成功,准备展示文件。");tv_progress.setVisibility(View.GONE);mSuperFileView.displayFile(fileN);} catch (Exception e) {Log.e("tag", "文件下载异常 = " + e.toString());} finally {try {if (is != null)is.close();} catch (IOException e) {}try {if (fos != null)fos.close();} catch (IOException e) {}}}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {Log.e("tag", "文件下载失败");File file = FileTools.getCacheFile(filePathUrl);if (!file.exists()) {Log.e("tag", "删除下载失败文件");file.delete();requestDownLoadFile();//重新下载}}});}
}

布局文件activity_filedisplay.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><com.wjy.project.mytbs.SuperFileViewandroid:id="@+id/mSuperFileView"android:layout_width="match_parent"android:layout_height="match_parent"/><TextViewandroid:id="@+id/tv_progress"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#E7E7E7"android:text="文件加载中"android:textColor="#999999"android:textSize="18sp"android:gravity="center"android:visibility="gone"/></RelativeLayout>

里面用到的一个工具类FileTools

package com.wjy.project.mytbs;import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;import java.io.File;/*** Created by wjy on 2020/2/11* 文件工具类*/
public class FileTools {public static String pathName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/TbsReaderTemp/";/**** 获取缓存目录* @return*/public static File getCacheDir() {return new File(pathName);}/**** 绝对路径获取缓存文件* @param url* @return*/public static File getCacheFile(String url) {File cacheFile = new File(pathName + getFileName(url));Log.e("tag", "缓存文件 = " + cacheFile.toString());return cacheFile;}/**** 根据链接获取文件名(带类型的),具有唯一性* @param url* @return*/private static String getFileName(String url) {String fileName = Md5Tool.hashKey(url) + "." + getFileType(url);Log.e("tag","fileName="+fileName);return fileName;}/**** 获取文件类型* @param paramString* @return*/private static String getFileType(String paramString) {String str = "";if (TextUtils.isEmpty(paramString)) {Log.e("tag", "paramString---->null");return str;}Log.e("tag","paramString:"+paramString);int i = paramString.lastIndexOf('.');if (i <= -1) {Log.e("tag","i <= -1");return str;}str = paramString.substring(i + 1);Log.e("tag","paramString.substring(i + 1)------>"+str);return str;}
}

用到的MD5工具,文件下载的名字唯一性

package com.wjy.project.mytbs;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;/*** Created by wjy on 2020/2/11.*/public class Md5Tool {private static String bytesToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(0xFF & bytes[i]);if (hex.length() == 1) {sb.append('0');}sb.append(hex);}return sb.toString();}public static String hashKey(String key) {String hashKey;try {final MessageDigest mDigest = MessageDigest.getInstance("MD5");mDigest.update(key.getBytes());hashKey = bytesToHexString(mDigest.digest());} catch (NoSuchAlgorithmException e) {hashKey = String.valueOf(key.hashCode());}return hashKey;}}

下面的本例子中用到的网络请求 okhttp3:LoadFileModel

package com.wjy.project.mytbs;import android.text.TextUtils;import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;/*** Created by wjy on 2020/2/11.*/public class LoadFileModel {public static void loadFile(String url, Callback<ResponseBody> callback) {Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.baidu.com/").addConverterFactory(GsonConverterFactory.create()).build();LoadFileApi mLoadFileApi = retrofit.create(LoadFileApi.class);if (!TextUtils.isEmpty(url)) {Call<ResponseBody> call = mLoadFileApi.loadPdfFile(url);call.enqueue(callback);}}
}
package com.wjy.project.mytbs;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Url;/*** Created by wjy on 2020/2/11.*/public interface LoadFileApi {@GETCall<ResponseBody> loadPdfFile(@Url String fileUrl);}

到此 整个例子就结束了。

源码地址:

git:https://gitee.com/AlaYu/MyTBS

CSDN://download.csdn.net/download/u013184970/12154456

Android之TBS浏览Word、Excel、PPT、PDF等文件相关推荐

  1. Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法)

    Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法) 1.需求背景 2.环境准备工作 2.1 JACOB介绍及安装 2.2 Microsoft Office W ...

  2. C#编写ASP.NET Core的Web API并部署到IIS上的详细教程(API用于准确获取Word/Excel/PPT/PDF的页数)6 -将项目部署到IIS,及常见错误解决方案

    C#编写ASP.NET Core的Web API并部署到IIS上的详细教程(API用于准确获取Word/Excel/PPT/PDF的页数)6 -将项目部署到IIS,及常见错误解决方案 1.前言 2.安 ...

  3. 性能优化之通过Aspose组件将Word/Excel/PPT/PDF转成HTML文件,解决大附件预览性能问题

    在最近的一个项目中,遇到一个非常棘手的性能问题,场景是这样的:有PC端和手机端两个应用,用户在PC端上传的附件,如word,Excel,pdf等,当用户出差或不在电脑边上时,上传的附件在手机端能够打开 ...

  4. Word,Excel,PPT等Office文件Web浏览器在线预览

    博主联系方式   https://fizzz.blog.csdn.net/article/details/113049879 前两天接到一个需求:需要在线预览用户上传的Word,Excel,PPT文档 ...

  5. lucent检索技术之创建索引:使用POI读取txt/word/excel/ppt/pdf内容

    在使用lucent检索文档时,必须先为各文档创建索引.索引的创建即读出文档信息(如文档名称.上传时间.文档内容等),然后再经过分词建索引写入到索引文件里.这里主要是总结下读取各类文档内容这一步. 一. ...

  6. 关于在线预览word,excel,ppt,pdf的需求处理方法。

    参考文档:http://www.cnblogs.com/wolf-sun/p/3574278.html 我选用的方案:先用office com组件生成pdf,然后使用pdf.js在线预览pdf文档.在 ...

  7. office2016安装后新建图标(word\excel\ppt)等文件图标均显示白色

    虽然激活的2016打开也可以输入文件,但是图标看着很不舒服! 找了找 Excel文件不显示图标的第一种方式:图标未知 如下面的截图,一个Excel文档,在桌面上预览,可以看到excel文件不显示图标. ...

  8. Vue 预览word,excel,ppt等office文档-内网访问(基于onlyoffice,后端返回文件流)

    Vue 预览word,excel等office 先看效果!! 需求背景:在前端页面中预览office文件且是内网访问,服务器不可访问外网的前提. 因此微软的接口就废掉了,因为他接口的条件是可以访问外网 ...

  9. php word excel转pdf文件怎么打开,php office文件(word/excel/ppt)转pdf文件,pptpdf

    php office文件(word/excel/ppt)转pdf文件,pptpdf 把代码放到了github上,点击进入 前阶段有个项目用到了线上预览功能, 关于预览office文件实现核心就是,把o ...

最新文章

  1. FastThreadLocal吞吐量居然是ThreadLocal的3倍
  2. 安卓高手之路之图形系统【5】安卓ListView和EditText配合使用时的注意事项。
  3. python操作excel-python操作excel(内附python教程分享)
  4. 遭遇ORA-01200错误的原因及解决方法
  5. jdbc就是这么简单
  6. 中引入文件报错_关于前端开发中的模块化
  7. mysql----innodb统计信息
  8. 希捷宣布出货双碟装1TB硬盘 单碟500GB上市
  9. 图像处理之特征描述与匹配
  10. ffmpeg的mac安装
  11. CentOS7.0系统安全加固实施方案
  12. python输出数字三角形_Python|2020蓝桥杯之数字三角形
  13. python写闲鱼脚本_自动化篇 - 躺着收钱!闲鱼自动发货机器人来啦~
  14. k8s源码分析 pdf_我是怎么阅读kubernetes源代码的?
  15. 岁月温柔-20 妈妈在省医院第一天
  16. 5mm超厚“爱马仕”羊毛袜!堪比足底小太阳,抗寒-10℃,99%抑菌防臭不闷汗!...
  17. Weisfeiler-Lehman(WL)算法测试图同构
  18. 西电2020 python OJ作业(50道题目,持续更新)
  19. 2021新年算法小专题—2.股票买卖利润刷题(Java)
  20. driftingblues 4 靶机 wp

热门文章

  1. 【机器学习】实战系列
  2. html条形图显示统计数据,条形统计图和柱形统计图区别
  3. 远程服务调用失败重试之简单实现
  4. 两个offer:rovi和凯捷中国,不知道如何选择
  5. Linux tar过滤文件
  6. 什么是json数据?json数据应该怎么设计
  7. html设置横线中间的字,CSS伪元素before,after制作左右横线中间文字效果
  8. c语言 实习报告,计算机专业c语言实训报告范文
  9. 最强 IDE Visual Studio 2017 正式版发布-gt;最快更高效-终于等到你
  10. 面试官:使用无界队列的线程池会导致内存飙升吗?