修复firebase崩溃错误,1.0.3(3)
This commit is contained in:
parent
30c04ee7d9
commit
70850c8a2c
@ -16,6 +16,7 @@ import com.all.pdfreader.pdf.reader.ui.dialog.PdfPasswordProtectionDialogFragmen
|
||||
import com.all.pdfreader.pdf.reader.util.AppUtils.setOnSingleClickListener
|
||||
import com.all.pdfreader.pdf.reader.util.FileUtils.isPdfEncrypted
|
||||
import com.all.pdfreader.pdf.reader.util.PdfUtils
|
||||
import com.all.pdfreader.pdf.reader.util.ToastUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -55,8 +56,8 @@ class PdfToImageActivity : BaseActivity() {
|
||||
statusBarDarkFont(true)
|
||||
navigationBarColor(R.color.bg_color)
|
||||
}
|
||||
filePath = intent.getStringExtra(EXTRA_PDF_PATH)
|
||||
?: throw IllegalArgumentException("PDF file hash is required")
|
||||
filePath = intent.getStringExtra(EXTRA_PDF_PATH) ?: ""
|
||||
|
||||
source = getSerializableOrDefault(EXTRA_SOURCE, PdfPickerSource.NONE)
|
||||
if (filePath.isEmpty()) {
|
||||
showToast(getString(R.string.file_not))
|
||||
@ -153,8 +154,18 @@ class PdfToImageActivity : BaseActivity() {
|
||||
PdfUtils.splitPdfToPageItemsFlow(
|
||||
context = this@PdfToImageActivity,
|
||||
inputFile = file,
|
||||
password = password
|
||||
password = password,
|
||||
onError = { e ->
|
||||
runOnUiThread {
|
||||
ToastUtils.show(
|
||||
this@PdfToImageActivity,
|
||||
getString(R.string.file_not_pdf_or_corrupted)
|
||||
)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
).collect { pageItem ->
|
||||
|
||||
logDebug("splitPdfToPageItemsFlow pageItem->$pageItem")
|
||||
if (pdfPageList.size <= pageItem.pageIndex) {
|
||||
pdfPageList.add(pageItem)
|
||||
|
||||
@ -49,12 +49,12 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
get() = binding.rootBottomLayout
|
||||
companion object {
|
||||
const val FRAG_TAG = "PdfViewActivity"
|
||||
private const val EXTRA_PDF_HASH = "extra_pdf_hash"
|
||||
private const val EXTRA_PDF_FILE_PATH = "extra_pdf_file_path"
|
||||
|
||||
// 创建启动Intent的便捷方法
|
||||
fun createIntent(context: Context, filePath: String): Intent {
|
||||
return Intent(context, PdfViewActivity::class.java).apply {
|
||||
putExtra(EXTRA_PDF_HASH, filePath)
|
||||
putExtra(EXTRA_PDF_FILE_PATH, filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,9 +81,12 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
navigationBarColor(R.color.white)
|
||||
}
|
||||
setupDoubleBackExit()
|
||||
val filePath = intent.getStringExtra(EXTRA_PDF_FILE_PATH) ?: ""
|
||||
if (filePath.isEmpty()) {
|
||||
showToast(getString(R.string.file_not))
|
||||
finish()
|
||||
}
|
||||
initObserve()
|
||||
val filePath = intent.getStringExtra(EXTRA_PDF_HASH)
|
||||
?: throw IllegalArgumentException("PDF file hash is required")
|
||||
// 加载PDF数据
|
||||
viewModel.getPDFDocument(filePath)
|
||||
//加载书签数据
|
||||
|
||||
@ -23,6 +23,7 @@ import com.all.pdfreader.pdf.reader.util.AppUtils.setOnSingleClickListener
|
||||
import com.all.pdfreader.pdf.reader.util.FileUtils.isPdfEncrypted
|
||||
import com.all.pdfreader.pdf.reader.util.FileUtils.toUnderscoreDateTime
|
||||
import com.all.pdfreader.pdf.reader.util.PdfUtils
|
||||
import com.all.pdfreader.pdf.reader.util.ToastUtils
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -69,8 +70,7 @@ class SplitPdfActivity : BaseActivity() {
|
||||
statusBarDarkFont(true)
|
||||
navigationBarColor(R.color.bg_color)
|
||||
}
|
||||
filePath = intent.getStringExtra(EXTRA_PDF_PATH)
|
||||
?: throw IllegalArgumentException("PDF file hash is required")
|
||||
filePath = intent.getStringExtra(EXTRA_PDF_PATH) ?: ""
|
||||
if (filePath.isEmpty()) {
|
||||
showToast(getString(R.string.file_not))
|
||||
finish()
|
||||
@ -188,7 +188,16 @@ class SplitPdfActivity : BaseActivity() {
|
||||
PdfUtils.splitPdfToPageItemsFlow(
|
||||
context = this@SplitPdfActivity,
|
||||
inputFile = file,
|
||||
password = password
|
||||
password = password,
|
||||
onError = { e ->
|
||||
runOnUiThread {
|
||||
ToastUtils.show(
|
||||
this@SplitPdfActivity,
|
||||
getString(R.string.file_not_pdf_or_corrupted)
|
||||
)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
).collect { pageItem ->
|
||||
logDebug("splitPdfToPageItemsFlow pageItem->$pageItem")
|
||||
if (splitList.size <= pageItem.pageIndex) {
|
||||
|
||||
@ -518,24 +518,10 @@ object FileUtils {
|
||||
}
|
||||
|
||||
fun getFileFromUri(context: Context, uri: Uri): File? {
|
||||
// 先尝试通过 DATA 字段获取
|
||||
val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
|
||||
context.contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val path =
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
|
||||
if (!path.isNullOrEmpty()) {
|
||||
val file = File(path)
|
||||
if (file.exists()) {
|
||||
return file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Android 10+ 或 DATA 字段为空时,使用 ContentResolver 流访问
|
||||
return try {
|
||||
val tempFile = File(context.cacheDir, "temp_pdf_${System.currentTimeMillis()}.pdf")
|
||||
val fileName = getFileName(context, uri) ?: "temp_${System.currentTimeMillis()}"
|
||||
val tempFile = File(context.cacheDir, fileName)
|
||||
|
||||
context.contentResolver.openInputStream(uri)?.use { input ->
|
||||
tempFile.outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
@ -543,11 +529,28 @@ object FileUtils {
|
||||
}
|
||||
tempFile
|
||||
} catch (e: Exception) {
|
||||
// Log.e("ocean", "无法获取文件: ${e.message}", e)
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileName(context: Context, uri: Uri): String? {
|
||||
return try {
|
||||
val cursor = context.contentResolver.query(uri,
|
||||
arrayOf(MediaStore.Files.FileColumns.DISPLAY_NAME),
|
||||
null, null, null)
|
||||
cursor?.use {
|
||||
if (it.moveToFirst()) {
|
||||
return it.getString(0)
|
||||
}
|
||||
}
|
||||
null
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun duplicateFile(originalFile: File): File? {
|
||||
if (!originalFile.exists()) return null
|
||||
|
||||
|
||||
@ -86,7 +86,8 @@ class PDFSearchManager(private val pdfView: PDFView) {
|
||||
onLoaded?.invoke(cachedDoc!!)
|
||||
} catch (e: Exception) {
|
||||
onError?.invoke(e)
|
||||
throw e
|
||||
cachedDoc = null
|
||||
cachedPath = null
|
||||
}
|
||||
} else {
|
||||
// 已缓存文档,仍可调用回调
|
||||
|
||||
@ -52,18 +52,25 @@ object PdfUtils {
|
||||
dpi: Float = 72f,
|
||||
chunkSize: Int = 5,
|
||||
thumbWidth: Int = 200,
|
||||
password: String? = null
|
||||
password: String? = null,
|
||||
onError: ((Exception) -> Unit)? = null
|
||||
): Flow<PdfPageItem> = flow {
|
||||
val pdfiumCore = PdfiumCore(context)
|
||||
|
||||
try {
|
||||
ParcelFileDescriptor.open(inputFile, ParcelFileDescriptor.MODE_READ_ONLY).use { fd ->
|
||||
val pdfDocument = if (password.isNullOrEmpty()) {
|
||||
val pdfDocument = try {
|
||||
if (password.isNullOrEmpty()) {
|
||||
pdfiumCore.newDocument(fd)
|
||||
} else {
|
||||
pdfiumCore.newDocument(fd, password)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
onError?.invoke(e)
|
||||
return@flow // 直接退出 flow,不崩溃
|
||||
}
|
||||
|
||||
val pageCount = pdfiumCore.getPageCount(pdfDocument)
|
||||
|
||||
val pages = List(pageCount) {
|
||||
PdfPageItem(pageIndex = it, previewFilePath = null, isSelected = false)
|
||||
}
|
||||
@ -74,6 +81,7 @@ object PdfUtils {
|
||||
val cacheDir = File(context.cacheDir, child).apply { mkdirs() }
|
||||
|
||||
for (i in 0 until pageCount) {
|
||||
try {
|
||||
pdfiumCore.openPage(pdfDocument, i)
|
||||
|
||||
val width = (pdfiumCore.getPageWidthPoint(pdfDocument, i) * dpi / 72).toInt()
|
||||
@ -85,7 +93,6 @@ object PdfUtils {
|
||||
val bitmap = createBitmap(thumbWidth, targetHeight, Bitmap.Config.RGB_565)
|
||||
pdfiumCore.renderPageBitmap(pdfDocument, bitmap, i, 0, 0, thumbWidth, targetHeight)
|
||||
|
||||
// 保存为压缩 JPEG
|
||||
val outFile = File(cacheDir, inputFile.name + "_page_$i.jpg")
|
||||
FileOutputStream(outFile).use { fos ->
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos)
|
||||
@ -95,11 +102,19 @@ object PdfUtils {
|
||||
pages[i].previewFilePath = outFile.absolutePath
|
||||
emit(pages[i])
|
||||
|
||||
if ((i + 1) % chunkSize == 0) delay(50) // 分批渲染,保证 UI 流畅
|
||||
if ((i + 1) % chunkSize == 0) delay(50)
|
||||
} catch (e: Exception) {
|
||||
// 单页渲染失败也不崩溃,只提示
|
||||
onError?.invoke(e)
|
||||
}
|
||||
}
|
||||
|
||||
pdfiumCore.closeDocument(pdfDocument)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// 打开文件失败或 PFDium 异常
|
||||
onError?.invoke(e)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
/**
|
||||
|
||||
@ -193,4 +193,5 @@
|
||||
<string name="save_to_album">Save to Album</string>
|
||||
<string name="one_image_converted">1 image converted</string>
|
||||
<string name="number_image_converted">%1$d imagesF converted</string>
|
||||
<string name="file_not_pdf_or_corrupted">File not in PDF format or corrupted</string>
|
||||
</resources>
|
||||
Loading…
Reference in New Issue
Block a user