添加输入密码查询pdf
This commit is contained in:
parent
86750a4429
commit
687ac17419
@ -3,7 +3,6 @@ package com.all.pdfreader.pro.app.room.entity
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.all.pdfreader.pro.app.ui.dialog.PdfPasswordDialog
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
|||||||
@ -42,7 +42,7 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
pdfDao.searchDocuments(query)
|
pdfDao.searchDocuments(query)
|
||||||
|
|
||||||
suspend fun updateFavoriteStatus(fileHash: String, isFavorite: Boolean) {
|
suspend fun updateFavoriteStatus(fileHash: String, isFavorite: Boolean) {
|
||||||
val document = pdfDao.getByHash(fileHash)?.copy(
|
val document = pdfDao.getByPath(fileHash)?.copy(
|
||||||
isFavorite = isFavorite,
|
isFavorite = isFavorite,
|
||||||
addedToFavoriteTime = if (isFavorite) System.currentTimeMillis() else null
|
addedToFavoriteTime = if (isFavorite) System.currentTimeMillis() else null
|
||||||
)
|
)
|
||||||
@ -50,7 +50,7 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateReadingProgress(fileHash: String, page: Int, progress: Float) {
|
suspend fun updateReadingProgress(fileHash: String, page: Int, progress: Float) {
|
||||||
val document = pdfDao.getByHash(fileHash)?.copy(
|
val document = pdfDao.getByPath(fileHash)?.copy(
|
||||||
lastOpenedTime = System.currentTimeMillis(),
|
lastOpenedTime = System.currentTimeMillis(),
|
||||||
lastReadPage = page,
|
lastReadPage = page,
|
||||||
readingProgress = progress
|
readingProgress = progress
|
||||||
@ -59,14 +59,14 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updatePasswordStatus(fileHash: String, isPassword: Boolean) {
|
suspend fun updatePasswordStatus(fileHash: String, isPassword: Boolean) {
|
||||||
val document = pdfDao.getByHash(fileHash)?.copy(
|
val document = pdfDao.getByPath(fileHash)?.copy(
|
||||||
isPassword = isPassword
|
isPassword = isPassword
|
||||||
)
|
)
|
||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updatePassword(fileHash: String, password: String?) {
|
suspend fun updatePassword(fileHash: String, password: String?) {
|
||||||
val document = pdfDao.getByHash(fileHash)?.copy(
|
val document = pdfDao.getByPath(fileHash)?.copy(
|
||||||
password = password
|
password = password
|
||||||
)
|
)
|
||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
@ -113,7 +113,7 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
// 组合查询
|
// 组合查询
|
||||||
suspend fun getPdfWithDetails(pdfHash: String): Flow<PdfDetails> {
|
suspend fun getPdfWithDetails(pdfHash: String): Flow<PdfDetails> {
|
||||||
return combine(
|
return combine(
|
||||||
pdfDao.getByHash(pdfHash)?.let { kotlinx.coroutines.flow.flowOf(it) }
|
pdfDao.getByPath(pdfHash)?.let { kotlinx.coroutines.flow.flowOf(it) }
|
||||||
?: kotlinx.coroutines.flow.flowOf(null),
|
?: kotlinx.coroutines.flow.flowOf(null),
|
||||||
bookmarkDao.getBookmarksByPdf(pdfHash),
|
bookmarkDao.getBookmarksByPdf(pdfHash),
|
||||||
noteDao.getNotesByPdf(pdfHash)
|
noteDao.getNotesByPdf(pdfHash)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ 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.ActivityPdfViewBinding
|
import com.all.pdfreader.pro.app.databinding.ActivityPdfViewBinding
|
||||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||||
|
import com.all.pdfreader.pro.app.ui.dialog.PdfPasswordProtectionDialogFragment
|
||||||
import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle
|
import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle
|
||||||
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||||
import com.github.barteksc.pdfviewer.listener.OnErrorListener
|
import com.github.barteksc.pdfviewer.listener.OnErrorListener
|
||||||
@ -63,32 +64,13 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
|||||||
// 使用传递的文件路径加载PDF
|
// 使用传递的文件路径加载PDF
|
||||||
val file = File(pdfDocument.filePath)
|
val file = File(pdfDocument.filePath)
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
val pdfView = binding.pdfview
|
//需要密码展示对话框。
|
||||||
|
if (pdfDocument.isPassword) {
|
||||||
// 如果有密码,先尝试使用密码加载
|
showPasswordDialog(file)
|
||||||
if (!pdfDocument.password.isNullOrEmpty()) {
|
return
|
||||||
try {
|
|
||||||
pdfView.fromFile(file)
|
|
||||||
.password(pdfDocument.password) // 使用密码加载
|
|
||||||
.defaultPage(pdfDocument.lastReadPage)
|
|
||||||
.enableDoubletap(true)
|
|
||||||
.onLoad(this)
|
|
||||||
.enableAnnotationRendering(true)
|
|
||||||
.onError(this)
|
|
||||||
.onPageChange(this)
|
|
||||||
.scrollHandle(CustomScrollHandle(this))
|
|
||||||
.load()
|
|
||||||
return
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logDebug("Password protected PDF failed: ${e.message}")
|
|
||||||
// 密码错误,显示密码输入对话框
|
|
||||||
showPasswordDialog(file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 无密码PDF正常加载
|
// 无密码PDF正常加载
|
||||||
pdfView.fromFile(file)
|
binding.pdfview.fromFile(file)
|
||||||
.defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始
|
.defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始
|
||||||
.enableDoubletap(true)// 是否允许双击缩放
|
.enableDoubletap(true)// 是否允许双击缩放
|
||||||
.onLoad(this)
|
.onLoad(this)
|
||||||
@ -113,22 +95,13 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
|||||||
logDebug("PDF loading error: ${t?.message}")
|
logDebug("PDF loading error: ${t?.message}")
|
||||||
t?.let {
|
t?.let {
|
||||||
val errorMessage = it.message ?: "未知错误"
|
val errorMessage = it.message ?: "未知错误"
|
||||||
|
|
||||||
// 检查是否是密码相关的错误
|
// 检查是否是密码相关的错误
|
||||||
if (errorMessage.contains("Password") || errorMessage.contains("password")) {
|
if (errorMessage.contains("Password") || errorMessage.contains("password")) {
|
||||||
// 如果当前没有设置密码,显示密码输入对话框
|
val file = File(pdfDocument.filePath)
|
||||||
if (pdfDocument.password.isNullOrEmpty()) {
|
showPasswordDialog(file)
|
||||||
val file = File(pdfDocument.filePath)
|
|
||||||
showPasswordDialog(file)
|
|
||||||
} else {
|
|
||||||
// 密码错误,显示密码输入对话框
|
|
||||||
showToast("PDF密码错误")
|
|
||||||
val file = File(pdfDocument.filePath)
|
|
||||||
showPasswordDialog(file)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 其他错误
|
// 其他错误
|
||||||
showToast("PDF加载失败: $errorMessage")
|
showToast(getString(R.string.pdf_loading_failed))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,57 +129,23 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showPasswordDialog(file: File) {
|
private fun showPasswordDialog(file: File) {
|
||||||
val builder = android.app.AlertDialog.Builder(this)
|
PdfPasswordProtectionDialogFragment(file, onOkClick = { password ->
|
||||||
builder.setTitle("PDF密码保护")
|
tryLoadPdfWithPassword(file, password)
|
||||||
builder.setMessage("请输入PDF文件密码:")
|
}, onCancelClick = {
|
||||||
|
|
||||||
val input = android.widget.EditText(this)
|
|
||||||
input.inputType = android.text.InputType.TYPE_CLASS_TEXT or android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
|
|
||||||
builder.setView(input)
|
|
||||||
|
|
||||||
builder.setPositiveButton("确定") { dialog, _ ->
|
|
||||||
val password = input.text.toString()
|
|
||||||
if (password.isNotEmpty()) {
|
|
||||||
// 尝试使用输入的密码重新加载PDF
|
|
||||||
tryLoadPdfWithPassword(file, password)
|
|
||||||
} else {
|
|
||||||
showToast("密码不能为空")
|
|
||||||
}
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setNegativeButton("取消") { dialog, _ ->
|
|
||||||
dialog.cancel()
|
|
||||||
finish()
|
finish()
|
||||||
}
|
}).show(supportFragmentManager, TAG)
|
||||||
|
|
||||||
builder.setOnCancelListener {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryLoadPdfWithPassword(file: File, password: String) {
|
private fun tryLoadPdfWithPassword(file: File, password: String) {
|
||||||
try {
|
binding.pdfview.fromFile(file)
|
||||||
binding.pdfview.fromFile(file)
|
.password(password) // 使用输入的密码
|
||||||
.password(password) // 使用输入的密码
|
.defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始
|
||||||
.defaultPage(pdfDocument.lastReadPage)
|
.enableDoubletap(true)// 是否允许双击缩放
|
||||||
.enableDoubletap(true)
|
.onLoad(this)
|
||||||
.onLoad(this)
|
.enableAnnotationRendering(true) // 是否渲染注释(如评论、颜色、表单等)
|
||||||
.enableAnnotationRendering(true)
|
.onError(this)
|
||||||
.onError { error ->
|
.onPageChange(this)
|
||||||
logDebug("Password still incorrect: ${error?.message}")
|
.scrollHandle(CustomScrollHandle(this))
|
||||||
showToast("密码错误,请重试")
|
.load()
|
||||||
showPasswordDialog(file) // 重新显示密码对话框
|
|
||||||
}
|
|
||||||
.onPageChange(this)
|
|
||||||
.scrollHandle(CustomScrollHandle(this))
|
|
||||||
.load()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logDebug("Failed to load PDF with provided password: ${e.message}")
|
|
||||||
showToast("密码错误,请重试")
|
|
||||||
showPasswordDialog(file) // 重新显示密码对话框
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package com.all.pdfreader.pro.app.ui.dialog
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import com.all.pdfreader.pro.app.R
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogPdfPasswordProtectionBinding
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogSortBinding
|
||||||
|
import com.all.pdfreader.pro.app.model.SortConfig
|
||||||
|
import com.all.pdfreader.pro.app.model.SortDirection
|
||||||
|
import com.all.pdfreader.pro.app.model.SortField
|
||||||
|
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||||
|
import com.all.pdfreader.pro.app.sp.AppStore
|
||||||
|
import com.all.pdfreader.pro.app.ui.act.MainActivity.SortableFragment
|
||||||
|
import com.all.pdfreader.pro.app.ui.view.CustomPasswordTransformation
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
|
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
|
||||||
|
import com.all.pdfreader.pro.app.util.FileUtils.isPdfPasswordCorrect
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class PdfPasswordProtectionDialogFragment(
|
||||||
|
private val file: File,
|
||||||
|
private val onOkClick: (String) -> Unit,
|
||||||
|
private val onCancelClick: () -> Unit
|
||||||
|
) : DialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var binding: DialogPdfPasswordProtectionBinding
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = DialogPdfPasswordProtectionBinding.inflate(layoutInflater)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
isCancelable = false
|
||||||
|
dialog?.window?.apply {
|
||||||
|
// 去掉系统默认的背景 padding
|
||||||
|
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||||
|
// 设置宽度为全屏减去 16dp
|
||||||
|
val margin = resources.getDimensionPixelSize(R.dimen.dialog_margin) // 16dp
|
||||||
|
val width = resources.displayMetrics.widthPixels - margin * 2
|
||||||
|
setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.etPassword.showKeyboard()
|
||||||
|
|
||||||
|
binding.tvCancel.setOnClickListener {
|
||||||
|
onCancelClick()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
binding.tvConfirm.setOnClickListener {
|
||||||
|
val password = binding.etPassword.text.toString()
|
||||||
|
if(password.isEmpty()){
|
||||||
|
binding.tilPassword.error = getString(R.string.password_not_empty)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
if(isPdfPasswordCorrect(requireActivity(),file,password)){
|
||||||
|
onOkClick(password)
|
||||||
|
dismiss()
|
||||||
|
}else{
|
||||||
|
binding.tilPassword.error = getString(R.string.incorrect_password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package com.all.pdfreader.pro.app.ui.dialog
|
package com.all.pdfreader.pro.app.ui.dialog
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
@ -9,11 +8,11 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.all.pdfreader.pro.app.databinding.DialogPdfPasswordBinding
|
import com.all.pdfreader.pro.app.databinding.DialogPdfSetPasswordBinding
|
||||||
|
|
||||||
class PdfPasswordDialog : DialogFragment() {
|
class PdfSetPasswordDialog : DialogFragment() {
|
||||||
|
|
||||||
private var _binding: DialogPdfPasswordBinding? = null
|
private var _binding: DialogPdfSetPasswordBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private var listener: PasswordDialogListener? = null
|
private var listener: PasswordDialogListener? = null
|
||||||
|
|
||||||
@ -23,13 +22,17 @@ class PdfPasswordDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(): PdfPasswordDialog {
|
fun newInstance(): PdfSetPasswordDialog {
|
||||||
return PdfPasswordDialog()
|
return PdfSetPasswordDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(
|
||||||
_binding = DialogPdfPasswordBinding.inflate(inflater, container, false)
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = DialogPdfSetPasswordBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.all.pdfreader.pro.app.ui.view
|
||||||
|
|
||||||
|
import android.text.method.PasswordTransformationMethod
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
class CustomPasswordTransformation : PasswordTransformationMethod() {
|
||||||
|
override fun getTransformation(source: CharSequence, view: View): CharSequence {
|
||||||
|
return PasswordCharSequence(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PasswordCharSequence(private val mSource: CharSequence) : CharSequence {
|
||||||
|
override val length: Int
|
||||||
|
get() = mSource.length
|
||||||
|
|
||||||
|
override fun get(index: Int): Char {
|
||||||
|
// 最后一位显示原字符,其余显示●
|
||||||
|
return if (index == mSource.length - 1) mSource[index] else '●'
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
|
||||||
|
return mSource.subSequence(startIndex, endIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,11 @@
|
|||||||
package com.all.pdfreader.pro.app.util
|
package com.all.pdfreader.pro.app.util
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.EditText
|
||||||
|
|
||||||
object AppUtils {
|
object AppUtils {
|
||||||
|
|
||||||
@ -42,4 +46,16 @@ object AppUtils {
|
|||||||
return (this * context.resources.displayMetrics.density).toInt()
|
return (this * context.resources.displayMetrics.density).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 软键盘弹出
|
||||||
|
*/
|
||||||
|
fun EditText.showKeyboard() {
|
||||||
|
requestFocus()
|
||||||
|
(context as? Activity)?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
||||||
|
postDelayed({
|
||||||
|
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -8,6 +8,7 @@ import android.os.ParcelFileDescriptor
|
|||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.shockwave.pdfium.PdfiumCore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@ -345,6 +346,22 @@ object FileUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断pdf密码是否正确
|
||||||
|
*/
|
||||||
|
fun isPdfPasswordCorrect(context: Context, file: File, password: String): Boolean {
|
||||||
|
return try {
|
||||||
|
val descriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
|
||||||
|
val pdfiumCore = PdfiumCore(context)
|
||||||
|
val doc = pdfiumCore.newDocument(descriptor, password)
|
||||||
|
pdfiumCore.closeDocument(doc)
|
||||||
|
true // 没抛异常说明密码正确
|
||||||
|
} catch (e: Exception) {
|
||||||
|
false // 抛异常说明密码错误
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getFileFromUri(context: Context, uri: Uri): File? {
|
fun getFileFromUri(context: Context, uri: Uri): File? {
|
||||||
// 先尝试通过 DATA 字段获取
|
// 先尝试通过 DATA 字段获取
|
||||||
val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
|
val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
|
||||||
|
|||||||
76
app/src/main/res/layout/dialog_pdf_password_protection.xml
Normal file
76
app/src/main/res/layout/dialog_pdf_password_protection.xml
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/dr_rounded_corner_12_bg_white"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="@font/poppins_semibold"
|
||||||
|
android:text="@string/password_protection"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMessage"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/password_protection_dialog_desc"
|
||||||
|
android:textColor="@color/black_80"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:hint="@string/enter_password"
|
||||||
|
app:endIconMode="password_toggle"
|
||||||
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:textColor="@color/black_80" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvConfirm"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/ok"
|
||||||
|
android:textColor="@color/black" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -3,43 +3,46 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/dr_rounded_corner_12_bg_white"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="24dp"
|
android:padding="24dp">
|
||||||
android:background="@android:color/white">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTitle"
|
android:id="@+id/tvTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="设置PDF密码"
|
android:layout_marginBottom="16dp"
|
||||||
android:textSize="20sp"
|
android:fontFamily="@font/poppins_semibold"
|
||||||
android:textStyle="bold"
|
android:text="@string/set_pdf_password"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="@color/black"
|
||||||
android:layout_marginBottom="16dp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvMessage"
|
android:id="@+id/tvMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="为PDF文件设置保护密码,留空表示不设置密码"
|
android:layout_marginBottom="16dp"
|
||||||
android:textSize="14sp"
|
android:fontFamily="@font/poppins_regular"
|
||||||
android:textColor="@android:color/darker_gray"
|
android:text="@string/set_pdf_password_dialog_desc"
|
||||||
android:layout_marginBottom="16dp" />
|
android:textColor="@color/black_60"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/tilPassword"
|
android:id="@+id/tilPassword"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="输入密码"
|
android:layout_marginBottom="8dp"
|
||||||
app:passwordToggleEnabled="true"
|
android:hint="@string/enter_password"
|
||||||
app:endIconMode="password_toggle"
|
app:endIconMode="password_toggle"
|
||||||
android:layout_marginBottom="8dp">
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/etPassword"
|
android:id="@+id/etPassword"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textPassword" />
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
@ -47,43 +50,45 @@
|
|||||||
android:id="@+id/tilConfirmPassword"
|
android:id="@+id/tilConfirmPassword"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="确认密码"
|
android:layout_marginBottom="24dp"
|
||||||
app:passwordToggleEnabled="true"
|
android:hint="@string/confirm_password"
|
||||||
app:endIconMode="password_toggle"
|
app:endIconMode="password_toggle"
|
||||||
android:layout_marginBottom="24dp">
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/etConfirmPassword"
|
android:id="@+id/etConfirmPassword"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textPassword" />
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:gravity="end"
|
||||||
android:gravity="end">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvCancel"
|
android:id="@+id/tvCancel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="取消"
|
|
||||||
android:textColor="@color/black"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless" />
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:textColor="@color/black_80" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvConfirm"
|
android:id="@+id/tvConfirm"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="确认"
|
android:fontFamily="@font/poppins_medium"
|
||||||
android:textColor="@color/black"
|
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless" />
|
android:text="@string/ok"
|
||||||
|
android:textColor="@color/black" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
4
app/src/main/res/values/dimens.xml
Normal file
4
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<dimen name="dialog_margin">16dp</dimen>
|
||||||
|
</resources>
|
||||||
@ -28,4 +28,13 @@
|
|||||||
<string name="unlock">Unlock</string>
|
<string name="unlock">Unlock</string>
|
||||||
<string name="eye_protect">Eye Protect</string>
|
<string name="eye_protect">Eye Protect</string>
|
||||||
<string name="bookmarks">Bookmarks</string>
|
<string name="bookmarks">Bookmarks</string>
|
||||||
|
<string name="set_pdf_password">Set PDF Password</string>
|
||||||
|
<string name="set_pdf_password_dialog_desc">Set a protection password for the PDF file,Leaving it blank means no password is set.</string>
|
||||||
|
<string name="password_protection">PDF Password Protection</string>
|
||||||
|
<string name="enter_password">Enter password</string>
|
||||||
|
<string name="confirm_password">Confirm password</string>
|
||||||
|
<string name="password_protection_dialog_desc">Please enter the PDF file password</string>
|
||||||
|
<string name="password_not_empty">Password cannot be empty</string>
|
||||||
|
<string name="incorrect_password">Incorrect password</string>
|
||||||
|
<string name="pdf_loading_failed">PDF loading failed</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user