文章目录

  • 前言
  • 一、效果图
  • 二、实现步骤
    • 1.去官网注册并创建应用[腾讯官网](https://console.cloud.tencent.com/tbs/client)
    • 2.下载arr文件并引入[腾讯TBS](https://download.csdn.net/download/Android_Cll/91764395)
    • 3.application实例化
    • 4.activity实例化
    • 5.下载网络文件
    • 6.PreviewActivity预览
    • 7.preview布局
  • 总结


前言

做Android的各位,是不是觉得移动端去搞这个文件预览很操蛋,而且还是各种文件预览,如果只是PDF可以直接搞定,要预览各种文件怎么办,不接第三方怎么弄,猝死都弄不了的,相信我,来吧,今天就是为这个问题来的。


一、效果图

还是老样子,先来张效果图稳定军心。
在这里插入图片描述

二、实现步骤

1.去官网注册并创建应用腾讯官网

在这里插入图片描述

2.下载arr文件并引入腾讯TBS

代码如下(示例):

//腾讯TBS文件预览
implementation fileTree(dir: 'libs', include: ['TbsFileSdk_base_arm64_1.0.5.6000094.20250604183426.aar'])

3.application实例化

代码如下(示例):

//腾讯TBS初始化fun initEngineAsync() {//设置 licenseKeyTbsFileInterfaceImpl.setLicenseKey("你自己的licensekey")val callback: ITbsReaderCallback = object : ITbsReaderCallback {override fun onCallBackAction(actionType: Int, args: Any, result: Any) {println("初始化actionType=$actionType,args=$args,result=$result")// ITbsReader.OPEN_FILEREADER_ASYNC_LOAD_READER_ENTRY_CALLBACK 的值为7002,不是错误码if (ITbsReader.OPEN_FILEREADER_ASYNC_LOAD_READER_ENTRY_CALLBACK === actionType) {val ret = args as Int // 错误码为 actionType == 7002时 args 的值if (ret == 0) {// 初始化成功println("初始化成功了-----")} else {// 初始化失败println("初始化失败了-----")}}}}if (!TbsFileInterfaceImpl.isEngineLoaded()) {TbsFileInterfaceImpl.initEngineAsync(this, callback)}}

4.activity实例化

代码如下(实例化成功才能有后续哦):

//定义变量
private var isInit = false
//实例化
var ret = initEngine(this)if (ret == 0) {println("初始化成功--->界面")isInit = true} else {println("初始化失败--->界面")}

5.下载网络文件

//docurl下载文件地址,filename本地存储路径,endname文件格式fun download(docUrl: String, fileName: String, endName: String) {DialogUtils.showLoadingDialog(this)val filePath =getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + fileName // 本地存储路径// 下载文件(可以使用 OkHttp、Retrofit 或原生 HttpURLConnection)Thread {try {val url = URL(docUrl)val connection: HttpURLConnection = url.openConnection() as HttpURLConnectionconnection.setRequestMethod("GET")connection.setDoInput(true)connection.connect()val file = File(filePath)if (!file.exists()) {file.createNewFile()}connection.getInputStream().use { `in` ->FileOutputStream(file).use { out ->val buffer = ByteArray(1024)var len: Intwhile ((`in`.read(buffer).also { len = it }) != -1) {out.write(buffer, 0, len)}out.flush()}}// 下载完成后,在主线程打开文件runOnUiThread {openExternalFilesDirDocument(filePath, endName)DialogUtils.hideLoadingDialog()}} catch (e: Exception) {e.printStackTrace()runOnUiThread {ToastUtils.showToast("下载失败")}}}.start()}//打开预览private fun openExternalFilesDirDocument(filePath: String, extName: String) {if (isInit) {if (TbsFileInterfaceImpl.canOpenFileExt(extName)) {startActivity(Intent(this, PreviewActivity::class.java).putExtra("filePath",filePath).putExtra("fileExt", extName).putExtra("url", zhlist[0]))finish()} else {ToastUtils.showToast("此类型文档暂不支持打开")// tbs 不支持打开的类型}} else {Toast.makeText(applicationContext,"Engine未初始化成功,无法打开文件",Toast.LENGTH_SHORT).show()}}

6.PreviewActivity预览

class PreviewActivity : BaseActivity() {private lateinit var mFlRoot: FrameLayoutprivate lateinit var mRl: RelativeLayoutprivate var isDestroyed = falseprivate lateinit var imag_fh: ImageViewprivate lateinit var relaitve_xyb: RelativeLayoutoverride fun getContentViewId(): Int {return R.layout.preview}override fun initView(savedInstanceState: Bundle?) {mFlRoot = findViewById(R.id.content)mRl = findViewById(R.id.reader_top)imag_fh = findViewById(R.id.imag_fh)relaitve_xyb = findViewById(R.id.relaitve_xyb)imag_fh.setOnClickListener(this)relaitve_xyb.setOnClickListener(this)val filePath = intent.getStringExtra("filePath").toString()val fileExt = intent.getStringExtra("fileExt").toString()openFile(filePath, fileExt)}override fun onClick(v: View?) {when (v?.id) {R.id.imag_fh -> finish()//下载R.id.relaitve_xyb -> {downloadFile(this, intent.getStringExtra("url").toString(), "下载文档")}}}fun downloadFile(context: Context, url: String?, fileName: String?) {val downloadManager = context.getSystemService(DOWNLOAD_SERVICE) as DownloadManagerval uri = Uri.parse(url)val request = DownloadManager.Request(uri)// 设置通知栏提示(下载中、完成)request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)// 设置保存路径(Android 10+ 需使用 MediaStore API 或保存到 Downloads 目录)request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)// 发起下载downloadManager.enqueue(request)ToastUtils.showToast("已开始下载,请注意导航栏下载进度")}fun openFile(filePath: String, fileExt: String) {//设置回调val callback =ITbsReaderCallback { actionType, args, result ->println("actionType=$actionType,args=$args,result=$result")if (ITbsReader.OPEN_FILEREADER_STATUS_UI_CALLBACK == actionType) {if (args is Bundle) {val id = (args as Bundle).getInt("typeId")if (ITbsReader.TBS_READER_TYPE_STATUS_UI_SHUTDOWN == id) {finish() // 加密文档弹框取消需关闭 activity}}}}//设置参数val param = Bundle()param.putString("filePath", filePath)param.putString("fileExt", fileExt) // 文件后缀名,如文件名为 test.pdf,则只需要传入"pdf"param.putString("tempPath", getExternalFilesDir("temp")!!.absolutePath)//调用openFileReader打开文件mFlRoot.post {val height = mFlRoot.height// 自定义 layout 模式必须设置这个值,否则可能导致文档内容显示不全param.putInt("set_content_view_height", height)val ret = TbsFileInterfaceImpl.getInstance().openFileReader(this@PreviewActivity, param, callback, mFlRoot)}}// 销毁资源使用 onpause + ondestroy 的方式。避免 onDestroy 延迟回调private fun destroy() {if (isDestroyed) {return}// 回收资源mFlRoot.removeAllViews() //移除内容显示区域 layoutTbsFileInterfaceImpl.getInstance().closeFileReader() //关闭 fileReaderisDestroyed = true}override fun onPause() {super.onPause()if (isFinishing) {destroy()}}public override fun onDestroy() {super.onDestroy()destroy()}//横竖屏切换override fun onConfigurationChanged(@NonNull newConfig: Configuration) {super.onConfigurationChanged(newConfig)mFlRoot.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {override fun onGlobalLayout() {mFlRoot.viewTreeObserver.removeOnGlobalLayoutListener(this)val w = mFlRoot.widthval h = mFlRoot.heightTbsFileInterfaceImpl.getInstance().onSizeChanged(w, h)}})}
}

7.preview布局

<?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"android:background="@color/backColor"android:orientation="vertical"><FrameLayoutandroid:id="@+id/content"android:layout_width="match_parent"android:layout_below="@+id/reader_top"android:layout_height="match_parent"/><RelativeLayoutandroid:id="@+id/relaitve_xyb"android:layout_width="240dp"android:layout_height="48dp"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="10dp"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY"android:src="@mipmap/scmbback" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="下载"android:textColor="#ffffff"android:textSize="16dp" /></RelativeLayout>
</RelativeLayout>

总结

到此结束就解决了Android文件预览问题,如果有疑问随时评论区见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920360.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920360.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920360.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于微信小程序的化妆品成分查询系统源码

源码题目&#xff1a;基于微信小程序的化妆品成分查询系统源码☑️ 文末联系获取&#xff08;含源码、技术文档&#xff09;博主简介&#xff1a;10年高级软件工程师、JAVA技术指导员、Python讲师、文章撰写修改专家、Springboot高级&#xff0c;欢迎高校老师、同行交流合作。毕…

STM32 启动执行逻辑与代码烧入方法详解:从底层原理到实操落地

STM32 启动执行逻辑与代码烧入方法详解&#xff1a;从底层原理到实操落地背景概要STM32启动和执行的核心逻辑链条代码烧入到STM32的途径方法结束语背景概要 在学习STM32时候我们知道代码需要通过一些下载器&#xff08;如ST-Link、J-Link&#xff09;或者串口下载烧入到STM32芯…

Go对接印度股票数据源指南:使用StockTV API

一、StockTV API简介 StockTV提供全球200国家的实时金融数据&#xff0c;覆盖股票、外汇、期货和加密货币市场。针对印度市场&#xff08;国家ID14&#xff09;&#xff0c;其主要优势包括&#xff1a; 毫秒级低延迟响应7x24小时稳定服务日均处理亿级数据免费技术支持 官方资源…

ESP8266:Arduino学习

ESP8266一&#xff1a;环境搭建使用Ardino框架&#xff0c;在官网下载&#xff0c;下载离线的支持包二&#xff1a;实现简单的项目1. 点灯{pinMode(LED_PIN, OUTPUT); // 设置引脚为输出模式digitalWrite(LED_PIN, HIGH); // 点亮 LED}I/O引脚的三种模式分别为&#xff1a;INPU…

青少年软件编程(python六级)等级考试试卷-客观题(2023年3月)

更多内容和历年真题请查看网站&#xff1a;【试卷中心 -----> 电子学会 ----> 机器人技术 ----> 六级】 网站链接 青少年软件编程历年真题模拟题实时更新 青少年软件编程&#xff08;python六级&#xff09;等级考试试卷-客观题&#xff08;2023年3月&#xff09…

mongodb influxdb

、您需要提前配置 MongoDB 和 InfluxDB。让我帮您说明配置步骤&#xff1a; MongoDB 配置 启动 MongoDB 容器后&#xff0c;进入容器创建数据库&#xff1a; # 进入 MongoDB 容器 docker exec -it mongo mongosh -u root -p 123456# 创建 product 数据库 use product# 创建集合…

模拟电路中什么时候适合使用电流传递信号,什么时候合适使用电压传递信号

一、应用 1.实际应用中&#xff0c;需要进行权衡&#xff0c;比如抗干扰能力&#xff0c;传输距离&#xff0c;功耗 2.电压信号比较容易受到干扰&#xff0c;对噪声比较敏感&#xff0c;有噪声容限一说 3.电流信号对噪声不敏感 4.电源电压下降的稳定性或者长距离传输中的损耗问…

Flink2.0学习笔记:使用HikariCP 自定义sink实现数据库连接池化

stevensu1/EC0823: Flink2.0学习笔记&#xff1a;使用HikariCP 自定义sink实现数据库连接池化 在 Flink 流处理应用中使用 HikariCP 实现数据库连接池化&#xff0c;对于写入关系型数据库&#xff08;如 MySQL、PostgreSQL&#xff09;的 自定义 Sink 来说&#xff0c;不仅是推…

Ubuntu安装及配置Git(Ubuntu install and config Git Tools)

Setup Git sudo apt update sudo apt install git // 查看git版本 git --versionConfig Github // 不清楚username和email的可以直接在github网站上点击头像选择settings来查看 git config --global user

将C++资源管理测试框架整合到GitLab CI/CD的完整实践指南

将C资源管理测试框架整合到GitLab CI/CD的完整实践指南 摘要 本文深入探讨了如何将先进的C资源管理测试框架无缝集成到GitLab CI/CD流水线中&#xff0c;实现自动化资源监控、性能回归检测和高质量测试。通过实际案例和最佳实践&#xff0c;展示了如何构建一个能够精确控制CPU亲…

Web漏洞

一、Sql注入 sql注入漏洞的成因是由于后端数据库查询语句没有做过滤导致了前端输入字符串可以直接拼接到语句而获取数据库信息。 1.类型 数字型和字符型 区分&#xff1a;数字型可以进行加减运算&#xff0c;id11会获取id2的信息&#xff0c;而字符型只会获取1的数据 2.方…

Java中使用Spring Boot+Ollama构建本地对话机器人

目录结构Ollama是什么安装 Ollama下载大模型运行模型Java和IDEA版本创建一个springboot项目创建一个简单的对话接口启动spring boot流式对话输出用原生 HTML 打造可交互前端接入 OpenAI、DeepSeek 等云模型&#xff08;可选&#xff09;原文地址传送门 我是想做一个大模型本地部…

学习设计模式《二十四》——访问者模式

一、基础概念 访问者模式的本质是【预留后路&#xff0c;回调实现】。仔细思考访问者模式&#xff0c;它的实现主要是通过预先定义好调用的通路&#xff0c;在被访问的对象上定义accept方法&#xff0c;在访问者的对象上定义visit方法&#xff1b;然后在调用真正发生的时候&…

Rust 符号体系全解析:分类、应用与设计意图

Rust 的符号体系是其语法规则、内存安全与类型安全设计的核心载体。每个符号不仅承担特定功能&#xff0c;更隐含 Rust 对 “安全” 与 “表达力” 的平衡逻辑。本文按功能维度&#xff0c;系统梳理 Rust 中所有常用符号&#xff0c;结合代码示例与设计背景&#xff0c;提供全面…

神经网络|(十六)概率论基础知识-伽马函数·上

【1】引言 前序学习进程中&#xff0c;对经典的二项分布和正态分布已经有一定的掌握。 今天为学习一种稍显复杂的分布提前布局一下&#xff0c;学习伽马函数。 【2】伽马函数 伽马函数有两种经典写法&#xff0c;一种是积分形式&#xff0c;另一种是无穷乘积形式。 【2.1】…

安全向量模板类SiVector

实现一个安全向量模板类 SiVector&#xff0c;其设计目标是&#xff1a;在保持 std::vector 易用性的基础上&#xff0c;增强越界访问的安全性&#xff08;避免崩溃&#xff09;&#xff0c;同时兼容 std::vector 的核心接口和使用习惯。支持嵌套使用&#xff08;如 SiVector&l…

Cloudflare 推出 GenAI 安全工具,守护企业数据

8 月 26 日,Cloudflare 为其企业平台 Cloudflare One 推出了新的安全功能,帮助企业安全地采用 ChatGPT、Claude 和 Gemini 等生成式 AI 工具。该工具构建为云访问安全代理 (CASB),通过 API 集成来监控和保护这些 AI 服务,无需安装设备。 随着企业对 GenAI 的使用激增——C…

Mac测试端口连接的几种方式

在 macOS 上测试端口是否开放&#xff0c;可通过以下三种常用方法实现&#xff08;推荐优先使用系统自带的 nc 命令&#xff0c;简单高效&#xff09;&#xff1a;方法 1&#xff1a;用系统自带 nc&#xff08;netcat&#xff09;测试&#xff08;最推荐&#xff09;nc 是 macO…

用PyTorch实现多类图像分类:从原理到实际操作

引言 图像分类作为计算机视觉的基石&#xff0c;已深度渗透到我们生活的方方面面——从医疗影像中早期肿瘤的识别、自动驾驶汽车对道路元素的实时检测&#xff0c;到卫星图像的地形分析与零售行业的商品识别&#xff0c;其核心都是让机器学会"看懂"世界并做出分类决…

window安装python环境

1、确认操作系统类型和位数&#xff0c;明确下载安装包的版本&#xff0c;示例为&#xff1a;windows&#xff0c;64位环境。 2、登录python官网下载exe安装包&#xff0c;下载网址&#xff1a;Download Python | Python.org 找到想要的对应python版本&#xff0c;本次示例下…