添加分享,打印,功能。
This commit is contained in:
parent
23e7e8f97b
commit
5323ad1324
@ -66,6 +66,16 @@
|
|||||||
<data android:scheme="content" />
|
<data android:scheme="content" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths" />
|
||||||
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -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<PageRange?>?,
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,19 @@
|
|||||||
package com.all.pdfreader.pro.app.ui.dialog
|
package com.all.pdfreader.pro.app.ui.dialog
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.activityViewModels
|
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.R
|
||||||
import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding
|
import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding
|
||||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
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.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.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.toFormatFileSize
|
||||||
import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate
|
import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate
|
||||||
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
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.CenterCrop
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() {
|
class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() {
|
||||||
@ -97,6 +95,14 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
|
|||||||
FileDetailsDialogFragment().show(parentFragmentManager, "FileDetailsDialogFragment")
|
FileDetailsDialogFragment().show(parentFragmentManager, "FileDetailsDialogFragment")
|
||||||
dismiss()
|
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) {
|
private fun updateCollectUi(b: Boolean) {
|
||||||
|
|||||||
@ -2,10 +2,38 @@ package com.all.pdfreader.pro.app.util
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
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.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
import android.widget.EditText
|
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 {
|
object AppUtils {
|
||||||
|
|
||||||
@ -62,4 +90,81 @@ object AppUtils {
|
|||||||
}, 200)
|
}, 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -274,47 +274,6 @@ class PdfScanner(
|
|||||||
return TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis() - lastScan)
|
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(
|
private fun generateFastThumbnail(
|
||||||
context: Context,
|
context: Context,
|
||||||
pdfFile: File,
|
pdfFile: File,
|
||||||
|
|||||||
@ -169,6 +169,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/shareBtn"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
@ -191,6 +192,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/printBtn"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
|||||||
@ -84,4 +84,8 @@
|
|||||||
<string name="last_modified">Last Modified</string>
|
<string name="last_modified">Last Modified</string>
|
||||||
<string name="last_viewed">Last Viewed</string>
|
<string name="last_viewed">Last Viewed</string>
|
||||||
<string name="size">Size</string>
|
<string name="size">Size</string>
|
||||||
|
<string name="device_does_not_support_printing">Your device does not support printing</string>
|
||||||
|
<string name="pdf_cant_print_password_protected">Cannot print a password protected PDF file</string>
|
||||||
|
<string name="cannot_print_malformed_pdf">Cannot print a malformed PDF file</string>
|
||||||
|
<string name="pdf_cannot_print_error">Cannot print PDF file, Unknown error has occurred</string>
|
||||||
</resources>
|
</resources>
|
||||||
7
app/src/main/res/xml/file_paths.xml
Normal file
7
app/src/main/res/xml/file_paths.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 允许分享外部存储中的文件 -->
|
||||||
|
<external-path
|
||||||
|
name="external_files"
|
||||||
|
path="." />
|
||||||
|
</paths>
|
||||||
Loading…
Reference in New Issue
Block a user