diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 00c5154..069e4a1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -66,6 +66,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/PrintPdfAdapter.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/PrintPdfAdapter.kt new file mode 100644 index 0000000..b7d085f --- /dev/null +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/PrintPdfAdapter.kt @@ -0,0 +1,61 @@ +package com.all.pdfreader.pro.app.ui.adapter + +import android.content.Context +import android.net.Uri +import android.os.Bundle +import android.os.CancellationSignal +import android.os.ParcelFileDescriptor +import android.print.PageRange +import android.print.PrintAttributes +import android.print.PrintDocumentAdapter +import android.print.PrintDocumentInfo +import java.io.FileOutputStream +import java.io.InputStream + +class PrintPdfAdapter(private val context: Context, private val uri: Uri) : PrintDocumentAdapter() { + + override fun onLayout( + printAttributes: PrintAttributes?, + printAttributes2: PrintAttributes?, + cancellationSignal: CancellationSignal, + layoutResultCallback: LayoutResultCallback, + bundle: Bundle? + ) { + if (cancellationSignal.isCanceled) { + layoutResultCallback.onLayoutCancelled() + } else { + layoutResultCallback.onLayoutFinished( + PrintDocumentInfo.Builder("AllPDF") + .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build(), true + ) + } + } + + override fun onWrite( + pageRangeArr: Array?, + parcelFileDescriptor: ParcelFileDescriptor, + cancellationSignal: CancellationSignal?, + writeResultCallback: WriteResultCallback + ) { + try { + val openInputStream: InputStream? = context.contentResolver.openInputStream(uri) + val fileOutputStream = FileOutputStream(parcelFileDescriptor.fileDescriptor) + val bArr = ByteArray(1024) + while (true) { + val read = openInputStream?.read(bArr) + if (read != null) { + if (read > 0) { + fileOutputStream.write(bArr, 0, read) + } else { + writeResultCallback.onWriteFinished(arrayOf(PageRange.ALL_PAGES)) + openInputStream.close() + fileOutputStream.close() + return + } + } + } + } catch (e: Exception) { + e.printStackTrace() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt index de3c6a5..03bdafc 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt @@ -1,20 +1,19 @@ package com.all.pdfreader.pro.app.ui.dialog +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.activityViewModels -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity -import com.all.pdfreader.pro.app.room.repository.PdfRepository import com.all.pdfreader.pro.app.util.AppUtils.dpToPx +import com.all.pdfreader.pro.app.util.AppUtils.printPdfFile import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation -import com.all.pdfreader.pro.app.util.FileUtils +import com.all.pdfreader.pro.app.util.AppUtils.shareFile import com.all.pdfreader.pro.app.util.FileUtils.toFormatFileSize import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate import com.all.pdfreader.pro.app.viewmodel.PdfViewModel @@ -22,7 +21,6 @@ import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import kotlinx.coroutines.launch import java.io.File class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() { @@ -97,6 +95,14 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() FileDetailsDialogFragment().show(parentFragmentManager, "FileDetailsDialogFragment") dismiss() } + binding.shareBtn.setOnClickListener { + shareFile(requireActivity(), File(pdfDocument.filePath)) + dismiss() + } + binding.printBtn.setOnClickListener { + printPdfFile(requireActivity(), Uri.fromFile(File(pdfDocument.filePath))) + dismiss() + } } private fun updateCollectUi(b: Boolean) { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/util/AppUtils.kt b/app/src/main/java/com/all/pdfreader/pro/app/util/AppUtils.kt index 99eb3fe..1fe355c 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/util/AppUtils.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/util/AppUtils.kt @@ -2,10 +2,38 @@ package com.all.pdfreader.pro.app.util import android.app.Activity import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.pdf.PdfRenderer +import android.net.Uri +import android.os.Bundle +import android.os.CancellationSignal +import android.os.ParcelFileDescriptor +import android.print.PageRange +import android.print.PrintAttributes +import android.print.PrintDocumentAdapter +import android.print.PrintDocumentInfo +import android.print.PrintManager +import android.print.pdf.PrintedPdfDocument import android.view.View import android.view.WindowManager import android.view.inputmethod.InputMethodManager +import android.webkit.MimeTypeMap +import android.webkit.WebView +import android.webkit.WebViewClient import android.widget.EditText +import android.widget.Toast +import androidx.core.content.FileProvider +import com.all.pdfreader.pro.app.R +import java.io.File +import java.io.FileOutputStream +import androidx.core.graphics.createBitmap +import androidx.print.PrintHelper +import com.all.pdfreader.pro.app.ui.adapter.PrintPdfAdapter +import com.shockwave.pdfium.PdfPasswordException +import com.shockwave.pdfium.PdfiumCore +import com.tom_roush.pdfbox.pdmodel.common.PDPageLabelRange +import java.io.IOException object AppUtils { @@ -62,4 +90,81 @@ object AppUtils { }, 200) } + /** + * 分享文件(自动识别 MIME 类型) + * @param context 上下文 + * @param file 要分享的文件 + */ + fun shareFile(context: Context, file: File) { + try { + if (!file.exists()) { + Toast.makeText(context, context.getString(R.string.error_file_not_exist), Toast.LENGTH_SHORT).show() + return + } + + val uri: Uri = FileProvider.getUriForFile( + context, + "${context.packageName}.fileprovider", + file + ) + + val mimeType = getMimeType(file) ?: "*/*" + + val shareIntent = Intent(Intent.ACTION_SEND).apply { + type = mimeType + putExtra(Intent.EXTRA_STREAM, uri) + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + + context.startActivity( + Intent.createChooser(shareIntent, "share") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + ) + } catch (e: Exception) { + e.printStackTrace() + } + } + + /** + * 根据文件扩展名自动获取 MIME 类型 + */ + private fun getMimeType(file: File): String? { + val extension = file.extension.lowercase() + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) + } + + /** + * 打印PDF,传入uri + */ + fun printPdfFile(context: Context, uri: Uri?) { + try { + PdfiumCore(context).newDocument( + context.contentResolver.openFileDescriptor( + uri!!, + PDPageLabelRange.STYLE_ROMAN_LOWER + ) + ) + if (PrintHelper.systemSupportsPrint()) { + val printManager = + context.getSystemService(Context.PRINT_SERVICE) as PrintManager + val str = context.getString(R.string.app_name) + " Document" + printManager.print( + str, + PrintPdfAdapter(context, uri), + null as PrintAttributes? + ) + return + } + Toast.makeText(context, R.string.device_does_not_support_printing, Toast.LENGTH_LONG).show() + } catch (e: PdfPasswordException) { + Toast.makeText(context, R.string.pdf_cant_print_password_protected, Toast.LENGTH_LONG).show() + e.printStackTrace() + } catch (e2: IOException) { + Toast.makeText(context, R.string.cannot_print_malformed_pdf, Toast.LENGTH_LONG).show() + e2.printStackTrace() + } catch (e3: java.lang.Exception) { + Toast.makeText(context, R.string.pdf_cannot_print_error, Toast.LENGTH_LONG).show() + e3.printStackTrace() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/all/pdfreader/pro/app/util/PdfScanner.kt b/app/src/main/java/com/all/pdfreader/pro/app/util/PdfScanner.kt index 99d23b6..fbc4a76 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/util/PdfScanner.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/util/PdfScanner.kt @@ -274,47 +274,6 @@ class PdfScanner( return TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis() - lastScan) } - -// private fun generateFastThumbnail(context: Context, pdfFile: File): String? { -// return try { -// val fileDescriptor = -// ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY) -// val pdfRenderer = PdfRenderer(fileDescriptor) -// -// if (pdfRenderer.pageCount > 0) { -// val page = pdfRenderer.openPage(0) -// // 创建 Bitmap -// val bitmap = createBitmap(page.width, page.height) -// val canvas = Canvas(bitmap) -// canvas.drawColor(Color.WHITE) // 填充白色背景 -// -// page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY) -// page.close() -// -// // 保存到缓存目录 -// val cacheDir = File(context.cacheDir, "thumbnails") -// if (!cacheDir.exists()) cacheDir.mkdirs() -// val thumbFile = File(cacheDir, pdfFile.nameWithoutExtension + ".jpg") -// -// FileOutputStream(thumbFile).use { out -> -// bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out) -// } -// -// pdfRenderer.close() -// fileDescriptor.close() -// -// thumbFile.absolutePath -// } else { -// pdfRenderer.close() -// fileDescriptor.close() -// null -// } -// } catch (e: Exception) { -// e.printStackTrace() -// null -// } -// } - private fun generateFastThumbnail( context: Context, pdfFile: File, diff --git a/app/src/main/res/layout/dialog_list_more.xml b/app/src/main/res/layout/dialog_list_more.xml index 82a81e7..3f5de4d 100644 --- a/app/src/main/res/layout/dialog_list_more.xml +++ b/app/src/main/res/layout/dialog_list_more.xml @@ -169,6 +169,7 @@ Last Modified Last Viewed Size + Your device does not support printing + Cannot print a password protected PDF file + Cannot print a malformed PDF file + Cannot print PDF file, Unknown error has occurred \ No newline at end of file diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..4b1e768 --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,7 @@ + + + + +