- 集成 AndroidPdfViewer (mhiew fork) 实现不依赖浏览器的 PDF 预览 - 新增 PdfPreviewActivity 与 JS Bridge (AndroidPdfBridge) - ShowFileCard 在 Android App 内对 PDF 显示「预览」按钮,不内嵌 iframe - 新增 /api/file/content 后端接口用于文件内容 inline 预览 - 前端支持 <show_file> 标签与 download:// 链接渲染 - 更新 Android 版本号至 1.0.35
151 lines
4.5 KiB
Kotlin
151 lines
4.5 KiB
Kotlin
package com.cyjai.agent
|
|
|
|
import android.net.Uri
|
|
import android.os.Bundle
|
|
import android.view.MenuItem
|
|
import android.view.View
|
|
import android.widget.LinearLayout
|
|
import android.widget.ProgressBar
|
|
import android.widget.TextView
|
|
import android.widget.Toast
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import androidx.lifecycle.lifecycleScope
|
|
import com.github.barteksc.pdfviewer.PDFView
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.withContext
|
|
import java.io.File
|
|
import java.io.FileOutputStream
|
|
import java.net.HttpURLConnection
|
|
import java.net.URL
|
|
|
|
class PdfPreviewActivity : AppCompatActivity() {
|
|
|
|
companion object {
|
|
const val EXTRA_PDF_URL = "pdf_url"
|
|
private const val HOME_URL = "https://agent.cyjai.com"
|
|
}
|
|
|
|
private lateinit var pdfView: PDFView
|
|
private lateinit var loadingContainer: LinearLayout
|
|
private lateinit var progressBar: ProgressBar
|
|
private lateinit var statusText: TextView
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
setContentView(R.layout.activity_pdf_preview)
|
|
|
|
supportActionBar?.apply {
|
|
setDisplayHomeAsUpEnabled(true)
|
|
title = "PDF 预览"
|
|
}
|
|
|
|
pdfView = findViewById(R.id.pdfView)
|
|
loadingContainer = findViewById(R.id.loadingContainer)
|
|
progressBar = findViewById(R.id.progressBar)
|
|
statusText = findViewById(R.id.statusText)
|
|
|
|
val rawUrl = intent.getStringExtra(EXTRA_PDF_URL) ?: ""
|
|
if (rawUrl.isBlank()) {
|
|
showError("PDF 地址为空")
|
|
return
|
|
}
|
|
|
|
val url = if (rawUrl.startsWith("http://") || rawUrl.startsWith("https://")) {
|
|
rawUrl
|
|
} else {
|
|
HOME_URL.trimEnd('/') + (if (rawUrl.startsWith("/")) rawUrl else "/$rawUrl")
|
|
}
|
|
|
|
loadPdf(url)
|
|
}
|
|
|
|
private fun showLoading(msg: String) {
|
|
loadingContainer.visibility = View.VISIBLE
|
|
progressBar.visibility = View.VISIBLE
|
|
statusText.visibility = View.VISIBLE
|
|
statusText.text = msg
|
|
pdfView.visibility = View.INVISIBLE
|
|
}
|
|
|
|
private fun hideLoading() {
|
|
loadingContainer.visibility = View.GONE
|
|
progressBar.visibility = View.GONE
|
|
statusText.visibility = View.GONE
|
|
pdfView.visibility = View.VISIBLE
|
|
}
|
|
|
|
private fun showError(msg: String) {
|
|
loadingContainer.visibility = View.VISIBLE
|
|
progressBar.visibility = View.GONE
|
|
statusText.visibility = View.VISIBLE
|
|
statusText.text = msg
|
|
pdfView.visibility = View.INVISIBLE
|
|
Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
|
|
}
|
|
|
|
private fun loadPdf(url: String) {
|
|
showLoading("加载中...")
|
|
lifecycleScope.launch(Dispatchers.IO) {
|
|
try {
|
|
val file = downloadToCache(url)
|
|
withContext(Dispatchers.Main) {
|
|
showPdf(file)
|
|
}
|
|
} catch (e: Exception) {
|
|
withContext(Dispatchers.Main) {
|
|
showError("PDF 加载失败: ${e.message}")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun downloadToCache(url: String): File {
|
|
val conn = URL(url).openConnection() as HttpURLConnection
|
|
conn.connectTimeout = 30_000
|
|
conn.readTimeout = 60_000
|
|
conn.setRequestProperty("Accept", "application/pdf,*/*")
|
|
conn.connect()
|
|
|
|
if (conn.responseCode !in 200..299) {
|
|
throw RuntimeException("HTTP ${conn.responseCode}")
|
|
}
|
|
|
|
val pathParam = Uri.parse(url).getQueryParameter("path")
|
|
val fileName = if (!pathParam.isNullOrBlank()) {
|
|
"preview_" + pathParam.replace("/", "_")
|
|
} else {
|
|
"preview_${System.currentTimeMillis()}.pdf"
|
|
}
|
|
val file = File(cacheDir, fileName)
|
|
|
|
FileOutputStream(file).use { out ->
|
|
conn.inputStream.use { input ->
|
|
input.copyTo(out)
|
|
}
|
|
}
|
|
conn.disconnect()
|
|
return file
|
|
}
|
|
|
|
private fun showPdf(file: File) {
|
|
pdfView.fromFile(file)
|
|
.enableSwipe(true)
|
|
.swipeHorizontal(false)
|
|
.enableDoubletap(true)
|
|
.defaultPage(0)
|
|
.onError { showError("PDF 渲染失败") }
|
|
.onLoad { hideLoading() }
|
|
.load()
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
return if (item.itemId == android.R.id.home) {
|
|
finish()
|
|
true
|
|
} else {
|
|
super.onOptionsItemSelected(item)
|
|
}
|
|
}
|
|
}
|