Commit 76c2e1cc authored by wanglei's avatar wanglei

...

parent 6d575f28
......@@ -7,6 +7,7 @@ import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.net.Uri
import android.util.DisplayMetrics
import android.view.View
import android.view.animation.Animation
......@@ -29,6 +30,7 @@ import com.base.pdfviewerscannerwhite.databinding.ActivityPdfBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.hideKeyboard
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.showKeyBoard
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import java.io.File
......@@ -36,6 +38,7 @@ import java.io.File
class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
private val TAG = "PdfActivity"
private lateinit var pdfPresenter: PdfPresenter
private lateinit var pdfPageAdapter: PdfPagerAdapter
......@@ -45,6 +48,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
private var uiMode = UI_MODE_NORMAL
private var saveMode = ""
private var path: String = ""
private var uri: String? = null
private var density = 0f
override val binding: ActivityPdfBinding by lazy {
......@@ -59,6 +63,10 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
density = metrics.density
path = intent.extras?.getString("path") ?: ""
uri = intent.extras?.getString("uri")
LogEx.logDebug(TAG, "path=$path")
LogEx.logDebug(TAG, "uri=$uri")
val file = File(path)
binding.tvPdfName.text = file.name
......@@ -67,7 +75,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
initAdapter()
changeNormalUI()
muPDFCore = pdfPresenter.openFile(path)
muPDFCore = if (uri == null) pdfPresenter.openFile(path) else pdfPresenter.openUri(uri = Uri.parse(uri))
// 搜索设为空
......@@ -81,7 +89,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
pdfPageAdapter.setPassword(pwd)
createPdfUI()
binding.root.postDelayed({
pdfPresenter.iniPdfPage(path)
if (uri == null) pdfPresenter.iniPdfPage(path) else pdfPresenter.iniPdfPageByUri(uri ?: "")
}, 500)
} else {
toast("unknown error")
......@@ -90,7 +98,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
} else {
createPdfUI()
binding.root.postDelayed({
pdfPresenter.iniPdfPage(path)
if (uri == null) pdfPresenter.iniPdfPage(path) else pdfPresenter.iniPdfPageByUri(uri ?: "")
}, 500)
}
......@@ -240,7 +248,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
}
private fun initAdapter() {
pdfPageAdapter = PdfPagerAdapter(path)
pdfPageAdapter = PdfPagerAdapter(path, uri)
pdfPageAdapter.clickAction = { pageIndex ->
binding.mupdfReaderView.displayedViewIndex = pageIndex
}
......@@ -447,7 +455,6 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
binding.ivWancheng.visibility = View.VISIBLE
if (binding.llHighlight == view) {
binding.llHighlight.setBackgroundColor(Color.parseColor("#F5F5F5"))
} else {
......
......@@ -4,7 +4,10 @@ import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import com.base.pdfviewerscannerwhite.helper.MyApplication.Companion.context
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.UriUtils.readFileToByteArray
import com.tom_roush.pdfbox.pdmodel.PDDocument
import com.tom_roush.pdfbox.pdmodel.encryption.AccessPermission
import com.tom_roush.pdfbox.pdmodel.encryption.StandardProtectionPolicy
......@@ -47,6 +50,15 @@ object PdfBoxUtils {
return document.numberOfPages
}
fun getNumberOfPagesByUri(uri: String, password: String? = null): Int {
val byteArray = readFileToByteArray(context, Uri.parse(uri))
val document = if (password == null) PDDocument.load(byteArray) else PDDocument.load(byteArray, password)
val count = document.numberOfPages
document.close()
return count
}
fun getPdfDrawablePage(
context: Context,
filePath: String,
......@@ -64,6 +76,28 @@ object PdfBoxUtils {
return drawable
}
fun getPdfDrawablePageByUri(
context: Context,
uri: String,
pageIndex: Int,
scale: Float = 1f,
password: String? = null
): Drawable {
val document =
if (password == null)
PDDocument.load(readFileToByteArray(context, Uri.parse(uri)))
else
PDDocument.load(readFileToByteArray(context, Uri.parse(uri)), password)
val renderer = PDFRenderer(document)
val bitmap: Bitmap = renderer.renderImage(pageIndex, scale, ImageType.RGB, RenderDestination.EXPORT)
val drawable = BitmapDrawable(context.resources, bitmap)
return drawable
}
fun checkPdfEncryption(filePath: String): Int {
var state = 0
......@@ -96,6 +130,37 @@ object PdfBoxUtils {
return state
}
fun checkPdfEncryptionByUri(uri: String): Int {
var state = 0
try {
PDDocument.load(readFileToByteArray(context, Uri.parse(uri))).use { document ->
if (document.isEncrypted) {
println("The PDF is encrypted.")
val ap = document.getCurrentAccessPermission()
if (ap.canExtractContent()) {
println("You are allowed to extract content.")
} else {
state = 1
println("You are not allowed to extract content.")
}
if (ap.canPrint()) {
println("You are allowed to print the document.")
} else {
println("You are not allowed to print the document.")
state = 1
}
} else {
println("The PDF is not encrypted.")
state = 0
}
}
} catch (e: IOException) {
e.printStackTrace()
state = 1
}
return state
}
fun setPassword(
sourceFilePath: String,
userPassword: String,
......@@ -140,10 +205,21 @@ object PdfBoxUtils {
}
}
fun checkPwd(filePath: String, password: String): Boolean {
fun checkPwd(
context: Context,
filePath: String,
password: String,
uri: String? = null
): Boolean {
try {
val pdfDocument =
if (uri == null)
PDDocument.load(File(filePath), password)
else
PDDocument.load(readFileToByteArray(context, Uri.parse(uri)) ?: byteArrayOf(), password)
// 尝试使用提供的密码加载PDF文件
PDDocument.load(File(filePath), password).use { document ->
pdfDocument.use { document ->
// 如果没有抛出异常,说明密码正确
return true
}
......@@ -156,4 +232,6 @@ object PdfBoxUtils {
}
return false
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
......@@ -19,6 +20,7 @@ import java.util.concurrent.TimeUnit
class PdfPagerAdapter(
val pdfPath: String,
val uri: String? = null,
val itemLayout: Int = R.layout.item_pdf_pager,
) : BaseQuickAdapter<PdfPageBean, PdfPagerAdapter.PdfPagerViewHolder>() {
......@@ -53,7 +55,11 @@ class PdfPagerAdapter(
if (item.pageDrawable != null) {
binding.ivPager.setImageDrawable(item.pageDrawable)
} else {
loadPagerDrawable(context, item, binding.root, binding.ivPager)
if (uri == null) {
loadPagerDrawable(context, item, binding.root, binding.ivPager)
} else {
loadPagerDrawableByUri(context, item, binding.root, binding.ivPager)
}
}
binding.root.setOnClickListener {
clickAction?.invoke(item.pageIndex)
......@@ -100,6 +106,27 @@ class PdfPagerAdapter(
}
}
private fun loadPagerDrawableByUri(
context: Context,
item: PdfPageBean,
itemView: View,
iv: ImageView,
scale: Float = 1f
) {
threadPoolExecutor.execute {
runCatching {
val drawable = PdfBoxUtils.getPdfDrawablePageByUri(context, uri ?: "", item.pageIndex, scale, mPassword)
item.pageDrawable = drawable
itemView.post {
item.pageDrawable?.let {
iv.setImageDrawable(it)
}
}
}
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): PdfPagerViewHolder {
return PdfPagerViewHolder(itemLayout.inflate(parent))
}
......
package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.content.Context
import android.net.Uri
import android.os.Environment
import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.OutlineActivityData
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_PDF
import com.base.pdfviewerscannerwhite.bean.PdfPageBean
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfMergeActivity.Companion.mergePdfList
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.UriUtils.readFileToByteArray
import com.tom_roush.pdfbox.multipdf.PDFMergerUtility
import com.tom_roush.pdfbox.pdmodel.PDDocument
import java.io.File
......@@ -34,6 +37,20 @@ class PdfPresenter(
return muPDFCore
}
fun openUri(uri: Uri): MuPDFCore? {
var muPDFCore: MuPDFCore? = null
try {
muPDFCore = MuPDFCore(context, readFileToByteArray(context, uri), MIME_TYPE_PDF)
// 新建:删除旧的目录数据
OutlineActivityData.set(null)
} catch (e: java.lang.Exception) {
return null
} catch (e: OutOfMemoryError) {
return null
}
return muPDFCore
}
fun iniPdfPage(filePath: String) {
val list = arrayListOf<PdfPageBean>()
......@@ -44,6 +61,15 @@ class PdfPresenter(
pdfView?.initPdfPageRv(list)
}
fun iniPdfPageByUri(uri: String) {
val list = arrayListOf<PdfPageBean>()
val number = PdfBoxUtils.getNumberOfPagesByUri(uri, password)
repeat(number) {
list.add(PdfPageBean(it))
}
pdfView?.initPdfPageRv(list)
}
fun splitPdf(
srcPath: String, newPath: String, splitIndex: List<Int>,
finishAction: (newFile: File?) -> Unit
......
......@@ -89,12 +89,12 @@ class PdfSelectActivity : BaseActivity<ActivityPdfSelectBinding>(), DocumentView
}
if (doWhat == DO_LOCK_PDF) {
showPdfPwdDialog(it, null, false, encryptionAction = {
showPdfPwdDialog(state = it.state, path = it.path, encryptionAction = {
adapter.remove(it)
})
}
if (doWhat == DO_UNLOCK_PDF) {
showPdfPwdDialog(it, null, false, encryptionAction = {
showPdfPwdDialog(state = it.state, path = it.path, encryptionAction = {
adapter.remove(it)
})
}
......
......@@ -53,7 +53,7 @@ class PdfSplitActivity : BaseActivity<ActivityPdfSplitBinding>(), PdfView {
}
private fun initAdapter() {
pdfPagerAdapter = PdfPagerAdapter(path, R.layout.item_pdf_pager_split)
pdfPagerAdapter = PdfPagerAdapter(path, null,R.layout.item_pdf_pager_split)
pdfPagerAdapter.selectAction = { enable, allSelect ->
binding.tvBtnSplit.isEnabled = enable
binding.ivSelector.isSelected = allSelect
......
......@@ -52,15 +52,20 @@ class DocumentFragment() : BaseFragment<FragmentDocumentBinding>(), DocumentView
if (item.state == 0) {
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("path", item.path)
// putExtra("uri", item.uri.toString())
})
}
if (item.state == 1) {
requireContext().showPdfPwdDialog(item, null, true, verificationAction = { pwd ->
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("path", item.path)
putExtra("pwd", pwd)
requireContext().showPdfPwdDialog(
state = item.state,
path = item.path,
isCheckPwd = true,
verificationAction = { pwd ->
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("path", item.path)
putExtra("pwd", pwd)
})
})
})
}
}
......
package com.base.pdfviewerscannerwhite.ui.main
import android.content.Intent
import android.net.Uri
import androidx.lifecycle.lifecycleScope
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_LOCK_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_MERGE_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_SPLIT_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_UNLOCK_PDF
import com.base.pdfviewerscannerwhite.databinding.FragmentToolBinding
import com.base.pdfviewerscannerwhite.helper.BaseFragment
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfActivity
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfBoxUtils
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfSelectActivity
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showPdfPwdDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class ToolFragment : BaseFragment<FragmentToolBinding>() {
private val TAG = "ToolFragment"
override val binding: FragmentToolBinding by lazy {
FragmentToolBinding.inflate(layoutInflater)
}
......@@ -21,6 +30,43 @@ class ToolFragment : BaseFragment<FragmentToolBinding>() {
override fun setListener() {
super.setListener()
binding.llManager.setOnClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.setType("application/pdf")
intent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
(requireActivity() as MainActivity).launcher.launch(intent) {
val uri = it.data?.data ?: Uri.EMPTY
lifecycleScope.launch(Dispatchers.IO) {
val state = PdfBoxUtils.checkPdfEncryption(uri.toString())
if (state == 0) {
launch(Dispatchers.Main) {
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
})
}
} else {
launch(Dispatchers.Main) {
requireContext().showPdfPwdDialog(
state = state,
uri = uri.toString(),
isCheckPwd = true,
verificationAction = { pwd ->
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
putExtra("pwd", pwd)
})
})
}
}
}
}
}
binding.llMerge.setOnClickListener {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_MERGE_PDF)
......
......@@ -129,7 +129,7 @@ object DialogView {
binding.tvLock.text = "Lock PDF"
}
binding.llLock.setOnClickListener {
showPdfPwdDialog(item, dialog)
showPdfPwdDialog(state = item.state, path = item.path, firstDialog = dialog)
}
dialog.setOnDismissListener {
dismissAction.invoke()
......@@ -188,8 +188,10 @@ object DialogView {
@SuppressLint("SetTextI18n")
fun Context.showPdfPwdDialog(
item: DocumentBean,
firstDialog: Dialog?,
state: Int,
path: String = "",
uri: String? = null,
firstDialog: Dialog? = null,
isCheckPwd: Boolean = false,
verificationAction: ((pwd: String) -> Unit)? = null,
encryptionAction: (() -> Unit)? = null
......@@ -210,18 +212,18 @@ object DialogView {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
if (!isCheckPwd) {
if (item.state == 1) {
if (state == 1) {
binding.tvTittle.text = "Delete Password"
binding.tvTip.text = "Delete password, the file is not password protected"
}
if (item.state == 0) {
if (state == 0) {
binding.tvTittle.text = "Set Password"
binding.tvTip.text = "Set password protection pdf"
}
} else {
binding.tvTittle.text = "Input Password"
val file = File(item.path)
val file = File(path)
binding.tvTip.text = "${file.name} password protected"
binding.tvInputTip.visibility = View.VISIBLE
}
......@@ -241,18 +243,18 @@ object DialogView {
val pwd = binding.edit.text.toString()
if (!isCheckPwd) {
if (item.state == 0) {
PdfBoxUtils.setPassword(item.path, pwd, pwd)
if (state == 0) {
PdfBoxUtils.setPassword(path, pwd, pwd)
toast("Success Encryption")
encryptionAction?.invoke()
}
if (item.state == 1) {
PdfBoxUtils.clearPassword(item.path, pwd)
if (state == 1) {
PdfBoxUtils.clearPassword(path, pwd)
toast("clear Encryption")
encryptionAction?.invoke()
}
} else {
val result = PdfBoxUtils.checkPwd(item.path, pwd)
val result = PdfBoxUtils.checkPwd(this, path, pwd, uri.toString())
if (!result) {
binding.tvErrorTip.visibility = View.VISIBLE
return@setOnClickListener
......
......@@ -7,7 +7,9 @@ import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.OpenableColumns
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_APK
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_DOC
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_DOCX
......@@ -441,3 +443,23 @@ fun queryFiles(context: Context, fileSuffix: String): MutableList<File> {
}
return fileList
}
fun getFileNameFromUri(context: Context, uri: Uri): String {
var displayName = ""
if (DocumentsContract.isDocumentUri(context, uri)) {
val projection = arrayOf(OpenableColumns.DISPLAY_NAME)
var cursor: Cursor? = null
try {
cursor = context.contentResolver.query(uri, projection, null, null, null)
val column_index = cursor!!.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
if (cursor.moveToFirst()) {
displayName = cursor.getString(column_index)
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
}
return displayName
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.utils
import android.content.Context
import android.net.Uri
import com.tom_roush.pdfbox.io.IOUtils
import java.io.InputStream
object UriUtils {
fun readFileToByteArray(context: Context, uri: Uri): ByteArray? {
var inputStream: InputStream? = null
return try {
inputStream = context.contentResolver.openInputStream(uri)
// 读取文件内容到字节数组
IOUtils.toByteArray(inputStream)
} catch (e: java.lang.Exception) {
e.printStackTrace()
null
} finally {
if (inputStream != null) {
try {
inputStream.close()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment