Commit 60c336dc authored by wanglei's avatar wanglei

Merge branch 'master' of gitlab.huolea.com:koko/pdf-viewer-scanner-white

parents 6742ef78 d828de11
......@@ -24,6 +24,16 @@ android {
}
setProperty("archivesBaseName", "pdf-v${System.currentTimeMillis().toFormatTime3()}")
signingConfigs {
create("release") {
storeFile = file("../smartcl.jks")
storePassword = "123456"
keyAlias = "key0"
keyPassword = "123456"
}
}
// ndk {
// abiFilters.add("arm64-v8a")
......@@ -41,6 +51,7 @@ android {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
signingConfig = signingConfigs.getByName("release")
}
}
compileOptions {
......@@ -82,10 +93,8 @@ dependencies {
//Word库
//PPT库
api(project(":library"))
//Excel库
api(project(":library"))
}
\ No newline at end of file
......@@ -20,6 +20,7 @@
android:usesCleartextTraffic="true"
tools:targetApi="34">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
......@@ -46,6 +47,18 @@
android:launchMode="singleTask"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.set.FeedbackActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.set.SetActivity"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.document.ppt.PptActivity"
android:exported="false"
......
......@@ -34,6 +34,11 @@ object ConstObject {
const val UI_MODE_SELECT = "ui_mode_select"
const val UI_MODE_SEARCH = "ui_mode_search"
const val UI_SORT_LAST_MODIFIED = "ui_sort_last_modified"
const val UI_SORT_FINAL_MODIFIED = "ui_sort_final_modified"
const val UI_SORT_NAME_A_Z = "ui_sort_name_a_z"
const val UI_SORT_NAME_Z_A = "ui_sort_name_z_a"
var ifAgreePrivacy = false
get() {
return AppPreferences.getInstance().getBoolean("ifAgreePrivacy", field)
......
......@@ -12,6 +12,7 @@ data class DocumentBean(
var isSelect: Boolean = false
var state: Int = -1//0正常状态 1 锁定
var password: String = ""
var lastViewTime: Long = 0
companion object {
const val TYPE_PDF = "type_pdf"
......
......@@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
abstract class BaseFragment<T : ViewBinding> : Fragment() {
protected var isInitialized = false
protected abstract val binding: T
override fun onCreateView(
......
package com.base.pdfviewerscannerwhite.helper
object ConfigHelper {
const val privacyPolicy: String = "https://sites.google.com/view/pdf-reader-scan/pdf-reader"
const val termService: String = "https://sites.google.com/view/term-of-service-s/term-of-service"
}
\ No newline at end of file
......@@ -18,6 +18,7 @@ import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentMore
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.SpStringUtils
import com.cherry.lib.doc.bean.DocEngine
import com.cherry.lib.doc.office.constant.EventConstant
import com.cherry.lib.doc.office.ss.control.SSControl
......@@ -265,6 +266,8 @@ class ExcelActivity : BaseActivity<ActivityExcelBinding>() {
LogEx.logDebug(TAG, "initData-pathOrUri = $pathOrUri")
LogEx.logDebug(TAG, "initData-docSourceType = $docSourceType")
LogEx.logDebug(TAG, "initData-fileType = $fileType")
SpStringUtils.addSpString(SpStringUtils.LAST_VIEW_KEY, (pathOrUri ?: "") + "_/_" + System.currentTimeMillis())
}
......
......@@ -35,8 +35,6 @@ import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.SpStringUtils
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.LAST_VIEW_KEY
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import com.cherry.lib.doc.office.constant.EventConstant
import com.cherry.lib.doc.office.wp.control.WPControl
import java.io.File
......@@ -93,7 +91,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
pdfPageAdapter.setPassword(pwd)
createPdfUI()
muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_${System.currentTimeMillis()}")
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
} else {
toast("unknown error")
finish()
......@@ -101,7 +99,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
} else {
createPdfUI()
muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_${System.currentTimeMillis()}")
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
}
}
......@@ -141,7 +139,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
}
if (uiMode == UI_MODE_EDITE_SAVE) {
changeNormalUI()
resetPdfView()
cancelOperation()
return@addCallback
}
......@@ -172,31 +170,8 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Drawing)
}
binding.ivWancheng.setOnClickListener {
var success: Boolean = false
val pageView = binding.mupdfReaderView.displayedView as MuPDFView
when (saveMode) {
SAVE_MODE_HIGHLIGHT -> {
success = pageView.markupSelection(Annotation.Type.HIGHLIGHT)
}
SAVE_MODE_GLIDE_LINE -> {
success = pageView.markupSelection(Annotation.Type.UNDERLINE)
}
SAVE_MODE_STRIKETHROUGH -> {
success = pageView.markupSelection(Annotation.Type.STRIKEOUT)
}
SAVE_MODE_PAINTING_BRUSH -> {
success = pageView.saveDraw()
}
}
if (!success) {
toast("nothing to save")
return@setOnClickListener
}
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
changeEditSaveUI()
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
}
binding.ivBianji.setOnClickListener {
bianJiScaleXiao {
......@@ -223,13 +198,13 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
}
binding.tvBtnSave.setOnClickListener {
PdfLoadingActivity.muPDFCore = muPDFCore
changeNormalUI()
reallySave()
startActivity(Intent(this, PdfLoadingActivity::class.java).apply {
putExtra("doWhat", DO_SAVE_PDF)
putExtra("srcPath", path)
})
finish()
}
binding.ivXuanzhuan.setOnClickListener {
switchOrientation()
......@@ -246,9 +221,33 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
/**
*
*/
private fun resetPdfView() {
private fun reallySave() {
var success: Boolean = false
val pageView = binding.mupdfReaderView.displayedView as MuPDFView
when (saveMode) {
SAVE_MODE_HIGHLIGHT -> {
success = pageView.markupSelection(Annotation.Type.HIGHLIGHT)
}
SAVE_MODE_GLIDE_LINE -> {
success = pageView.markupSelection(Annotation.Type.UNDERLINE)
}
SAVE_MODE_STRIKETHROUGH -> {
success = pageView.markupSelection(Annotation.Type.STRIKEOUT)
}
SAVE_MODE_PAINTING_BRUSH -> {
success = pageView.saveDraw()
}
}
if (!success) {
toast("nothing to save")
return
}
}
private fun cancelOperation() {
val pageView = binding.mupdfReaderView.displayedView as MuPDFView?
if (pageView != null) {
......@@ -257,6 +256,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
pageView.deselectText()
pageView.cancelDraw()
}
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
}
private fun cancelSearch() {
......@@ -509,7 +509,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
/**
* 编辑报错UI模式
* 编辑保持UI模式
*/
private fun changeEditSaveUI() {
uiMode = UI_MODE_EDITE_SAVE
......@@ -526,6 +526,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)
}
override fun onPause() {
......
......@@ -6,6 +6,7 @@ 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.PDPage
......@@ -25,7 +26,6 @@ object PdfBoxUtils {
private val TAG = "PdfUtils"
fun getNumberOfPages(filePath: String, password: String? = null, uri: String? = null): Int {
val document =
loadPDDocument(path = filePath, password, uri)
......@@ -90,7 +90,8 @@ object PdfBoxUtils {
sourceFilePath: String,
userPassword: String,
ownerPassword: String
) {
): Boolean {
try {
PDDocument.load(File(sourceFilePath)).use { document ->
val ap = AccessPermission()
......@@ -102,10 +103,14 @@ object PdfBoxUtils {
val spp = StandardProtectionPolicy(userPassword, ownerPassword, ap)
document.protect(spp)
document.save(File(sourceFilePath))
LogEx.logDebug(TAG, "setPassword finish")
}
} catch (e: Exception) {
LogEx.logDebug(TAG, "setPassword Exception ${e.printStackTrace()}")
e.printStackTrace()
return false
}
return true
}
fun clearPassword(filePath: String, password: String) {
......
......@@ -62,6 +62,9 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
muPDFCore?.save()
muPDFCore = null
progressFinishAction = {
startActivity(Intent(this, PdfActivity::class.java).apply {
putExtra("path", srcPath)
})
finish()
}
lifecycleScope.launch {
......
......@@ -12,7 +12,9 @@ import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentRenameDialo
import com.base.pdfviewerscannerwhite.ui.view.PdfDialog.showPdfPwdDialog
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatTime2
import com.base.pdfviewerscannerwhite.utils.LogEx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.util.concurrent.ArrayBlockingQueue
......@@ -47,62 +49,69 @@ class PdfMergeActivity : BaseActivity<ActivityPdfMergeBinding>() {
}
binding.tvBtnNext.setOnClickListener {
verificationPasswordDialogs {
showDocumentRenameDialog(name = "Merge_${System.currentTimeMillis().toFormatTime2()}", okAction = { name ->
startActivity(Intent(this, PdfLoadingActivity::class.java).apply {
putExtra("doWhat", DO_MERGE_PDF)
putExtra("newPath", pdfPresenter.createNewPdfPath(name))
})
})
}
}
}
private fun verificationPasswordDialogs(callBack: (isContinue: Boolean) -> Unit) {
private fun verificationPasswordDialogs(callBack: () -> Unit) {
val queue: BlockingQueue<DocumentBean> = ArrayBlockingQueue(1)
val pwdItemList = mergePdfList.filter { it.state == 1 }
val pwdItemList = mergePdfList.filter { it.state == 1 }.toMutableList()
if (pwdItemList.isNotEmpty()) {
LogEx.logDebug(TAG, "verificationPasswordDialogs1")
val verifiedList = arrayListOf<DocumentBean>()
val first = pwdItemList[0]
queue.put(first)
mergePdfList.removeAt(0)
var isCancel: Boolean = false
pwdItemList.removeAt(0)
LogEx.logDebug(TAG, "verificationPasswordDialogs2")
lifecycleScope.launch() {
lifecycleScope.launch(Dispatchers.IO) {
while (isActive) {
val item: DocumentBean = queue.take()
LogEx.logDebug(TAG, "verificationPasswordDialogs3")
showPdfPwdDialog(item.state, item.path, isCheckPwd = true, verificationAction = { pwd ->
item.password = pwd
verifiedList.add(item)
if (pwdItemList.isNotEmpty()) {
val next = mergePdfList[0]
queue.put(next)
} else {
LogEx.logDebug(TAG, "pwdItem =${item.path}")
if (item.path == "Cancel") {
break
}
launch(Dispatchers.Main) {
showPdfPwdDialog(item.state, item.path, isCheckPwd = true, verificationAction = { pwd ->
item.password = pwd
verifiedList.add(item)
if (pwdItemList.isNotEmpty()) {
val next = pwdItemList[0]
queue.put(next)
pwdItemList.removeAt(0)
} else {
queue.put(DocumentBean(path = "Cancel"))
}
}, cancelAction = {
cancel()
}
}, cancelAction = {
isCancel = true
cancel()
})
})
}
}
}
if (isCancel) {
callBack.invoke(false)
return
} else {
LogEx.logDebug(TAG, "verificationPasswordDialogs3 ${verifiedList.size}")
verifiedList.forEach { verifiedItem ->
mergePdfList.find { it.path == verifiedItem.path }?.password = verifiedItem.password
}
mergePdfList.forEach {
LogEx.logDebug(TAG, "密码=" + it.password)
}
launch(Dispatchers.Main) {
callBack.invoke()
}
}
mergePdfList.forEach {
LogEx.logDebug(TAG, "密码=" + it.password)
}
} else {
callBack.invoke()
}
callBack.invoke(true)
}
private fun initAdapter() {
......@@ -112,7 +121,7 @@ class PdfMergeActivity : BaseActivity<ActivityPdfMergeBinding>() {
adapter = PdfMergeAdapter(itemTouchHelper, callBack)
adapter.removeAction = {
mergePdfList.remove(it)
binding.tvBtnNext.isEnabled = mergePdfList.isNotEmpty()
binding.tvBtnNext.isEnabled = mergePdfList.size >= 2
}
binding.rv.adapter = adapter
......@@ -133,6 +142,7 @@ class PdfMergeActivity : BaseActivity<ActivityPdfMergeBinding>() {
}
mergePdfList.let { adapter.submitList(it) }
binding.tvBtnNext.isEnabled = mergePdfList.size >= 2
}
companion object {
......
......@@ -13,8 +13,6 @@ 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.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
......@@ -142,20 +140,46 @@ class PdfPresenter(
val mergerUtility = PDFMergerUtility()
mergerUtility.destinationFileName = mergePath
//解密
PdfMergeActivity.mergePdfList.filter { it.state == 1 }.forEach {
PdfBoxUtils.clearPassword(it.path, it.password)
}
LogEx.logDebug(TAG, "mergePdf ${mergePdfList.size}")
PdfMergeActivity.mergePdfList.forEach { documentBean ->
if (documentBean.state == 0) {
mergerUtility.addSource(File(documentBean.path))
} else {
LogEx.logDebug(TAG, "documentBean.password=${documentBean.password}")
val pdfDocument = PDDocument.load(File(documentBean.path), documentBean.password)
val byteArrayOutputStream = ByteArrayOutputStream()
pdfDocument.save(byteArrayOutputStream)
pdfDocument.close()
val inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
mergerUtility.addSource(inputStream)
}
LogEx.logDebug(TAG, "mergePdf item= ${documentBean.path} ${documentBean.state}")
//带密码 mergerUtility.addSource(inputStream) 不行
mergerUtility.addSource(File(documentBean.path))
// if (documentBean.state == 0) {
// mergerUtility.addSource(File(documentBean.path))
// } else {
// LogEx.logDebug(TAG, "mergePdf password=${documentBean.password}")
// try {
// val pdfDocument = PDDocument.load(File(documentBean.path), documentBean.password)
// LogEx.logDebug(TAG, "mergePdf pdfDocument ${pdfDocument.numberOfPages}")
// val byteArrayOutputStream = ByteArrayOutputStream()
// pdfDocument.save(byteArrayOutputStream)
// LogEx.logDebug(TAG, "mergePdf byteArrayOutputStream ${byteArrayOutputStream.size()}")
// pdfDocument.close()
// val inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
// LogEx.logDebug(TAG, "mergePdf inputStream")
// mergerUtility.addSource(inputStream)
// } catch (e: Exception) {
// LogEx.logDebug(TAG, "mergePdf Exception ${e.printStackTrace()}")
// }
// LogEx.logDebug(TAG, "mergePdf inputStream")
// }
}
mergerUtility.mergeDocuments(null)
//重新加密
PdfMergeActivity.mergePdfList.filter { it.state == 1 }.forEach {
val flag = PdfBoxUtils.setPassword(it.path, it.password, it.password)
LogEx.logDebug(TAG, "重新加密 flag=$flag ${it.path} ${it.password}")
}
mergePdfList.clear()
LogEx.logDebug(TAG, "mergePdf finish")
isSuccess = true
......@@ -163,6 +187,7 @@ class PdfPresenter(
}
finishAction.invoke(isSuccess)
}.start()
......
......@@ -14,6 +14,7 @@ import com.base.pdfviewerscannerwhite.databinding.ActivityPptBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentMore
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.SpStringUtils
import com.cherry.lib.doc.bean.DocEngine
import com.cherry.lib.doc.office.pg.control.PGControl
import com.cherry.lib.doc.util.Constant
......@@ -111,6 +112,9 @@ class PptActivity : BaseActivity<ActivityPptBinding>() {
LogEx.logDebug(TAG, "initData-docUrl = $pathOrUri")
LogEx.logDebug(TAG, "initData-docSourceType = $docSourceType")
LogEx.logDebug(TAG, "initData-fileType = $fileType")
SpStringUtils.addSpString(SpStringUtils.LAST_VIEW_KEY, (pathOrUri ?: "") + "_/_" + System.currentTimeMillis())
}
private fun showTopLayout() {
......
......@@ -21,6 +21,7 @@ import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentMore
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.SpStringUtils
import com.cherry.lib.doc.bean.DocEngine
import com.cherry.lib.doc.office.constant.EventConstant.APP_PAGE_DOWN_ID
import com.cherry.lib.doc.office.constant.EventConstant.APP_PAGE_UP_ID
......@@ -295,6 +296,10 @@ class WordActivity : BaseActivity<ActivityWordBinding>() {
LogEx.logDebug(TAG, "initData-docSourceType = $docSourceType")
LogEx.logDebug(TAG, "initData-fileType = $fileType")
LogEx.logDebug(TAG, "initData-engine = $engine")
val value =( pathOrUri ?: "") + "_/_" + System.currentTimeMillis()
LogEx.logDebug(TAG, "value=$value")
SpStringUtils.addSpString(SpStringUtils.LAST_VIEW_KEY, value)
}
companion object {
......
......@@ -51,8 +51,13 @@ class DocumentAdapter : BaseQuickAdapter<DocumentBean, DocumentAdapter.DocumentV
override fun onBindViewHolder(holder: DocumentViewHolder, position: Int, item: DocumentBean?) {
if (item == null) return
val binding = ItemDocumentBinding.bind(holder.itemView)
if (item.type == TYPE_PDF) {
checkPwd(item, binding.iv)
if (item.type == TYPE_PDF ) {
if (item.state==0){
binding.iv.setImageResource(R.mipmap.h_pdfiocn)
}
if (item.state==1){
binding.iv.setImageResource(R.mipmap.suoding)
}
}
if (item.type == TYPE_WORD) {
binding.iv.setImageResource(R.mipmap.h_wordfiocn)
......@@ -144,20 +149,7 @@ class DocumentAdapter : BaseQuickAdapter<DocumentBean, DocumentAdapter.DocumentV
}
}
private fun checkPwd(item: DocumentBean, iv: ImageView) {
threadPoolExecutor.execute {
item.state = PdfBoxUtils.checkPdfEncryption(item.path)
LogEx.logDebug(TAG, "checkPwd ${item.state}")
var res = R.mipmap.h_pdfiocn
when (item.state) {
0 -> res = R.mipmap.h_pdfiocn
1 -> res = R.mipmap.suoding
}
iv.post {
iv.setImageResource(res)
}
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): DocumentViewHolder {
return DocumentViewHolder(R.layout.item_document.inflate(parent))
......
package com.base.pdfviewerscannerwhite.ui.main
import android.annotation.SuppressLint
import android.util.Log
import android.view.View
import android.view.inputmethod.EditorInfo
import androidx.core.content.ContextCompat
......@@ -20,6 +21,7 @@ import com.base.pdfviewerscannerwhite.bean.DocumentBean
import com.base.pdfviewerscannerwhite.databinding.FragmentDocumentBinding
import com.base.pdfviewerscannerwhite.helper.BaseFragment
import com.base.pdfviewerscannerwhite.ui.main.MainActivity.Companion.jumpDocument
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showSortDialog
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.hideKeyboard
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.showKeyBoard
import com.base.pdfviewerscannerwhite.utils.LogEx
......@@ -54,6 +56,7 @@ class DocumentFragment(
var uiMode = UI_MODE_NORMAL
@SuppressLint("SetTextI18n")
override fun setView() {
when (dataType) {
......@@ -74,6 +77,15 @@ class DocumentFragment(
initPageViewer()
initTabLayout()
initSearchAdapter()
isInitialized = true
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if(hidden){
return
}
currentPage.refreshData()
}
private fun initSearchAdapter() {
......@@ -111,6 +123,11 @@ class DocumentFragment(
}
false
}
binding.ivPaixu.setOnClickListener {
requireContext().showSortDialog {
currentPage.refreshData()
}
}
}
private fun initPageViewer() {
......
......@@ -2,9 +2,13 @@ package com.base.pdfviewerscannerwhite.ui.main
import android.annotation.SuppressLint
import android.content.Intent
import android.util.Log
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.base.pdfviewerscannerwhite.bean.ConstObject
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_FINAL_MODIFIED
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_NAME_A_Z
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_NAME_Z_A
import com.base.pdfviewerscannerwhite.bean.DocumentBean
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PDF
......@@ -15,8 +19,11 @@ import com.base.pdfviewerscannerwhite.helper.BaseFragment
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfSelectActivity
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfSplitActivity
import com.base.pdfviewerscannerwhite.ui.main.MainActivity.Companion.jumpDocument
import com.base.pdfviewerscannerwhite.ui.view.DialogView.SortMode
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentHomeMoreDialog
import com.base.pdfviewerscannerwhite.ui.view.PdfDialog.showPdfHomeMoreDialog
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatTime3
import com.base.pdfviewerscannerwhite.utils.LogEx
import java.io.File
import java.util.Locale
......@@ -41,20 +48,58 @@ class DocumentPageFragment() : BaseFragment<FragmentDocumentPageBinding>(), Docu
override fun setView() {
documentPresenter = DocumentPresenter(requireContext(), this, type, lifecycleScope)
initAdapter()
isInitialized = true
Log.d("glc", "我被调用了setView")
}
override fun onResume() {
super.onResume()
refreshData()
}
fun refreshData() {
if (isVisible) {
val list = (requireActivity() as MainActivity).mainPresenter.getDataByType(type, dataType)
adapter.submitList(list)
if (isInitialized && !isHidden) {
val list =
(requireActivity() as MainActivity).mainPresenter.getDataByType(type, dataType)
val dataType = (parentFragment as DocumentFragment).dataType
if (dataType == ConstObject.RECENT_DATA_TYPE) {
adapter.submitList(list)
} else {
val sortList = sortByMode(list)
adapter.submitList(sortList)
}
binding.llEmpty.isVisible = list.isEmpty()
Log.d("glc", "加载数据成功:" + type + " list:" + list.size)
} else {
Log.d("glc", "加载数据失败:" + type)
}
}
private fun sortByMode(list: List<DocumentBean>): List<DocumentBean> {
when (SortMode) {
ConstObject.UI_SORT_LAST_MODIFIED -> {
LogEx.logDebug(TAG, "sortByMode 1")
return list.sortedByDescending { File(it.path).lastModified() }
}
UI_SORT_FINAL_MODIFIED -> {
LogEx.logDebug(TAG, "sortByMode 2")
return list.sortedBy { File(it.path).lastModified() }
}
UI_SORT_NAME_A_Z -> {
LogEx.logDebug(TAG, "sortByMode 3")
return list.sortedBy { File(it.path).name }
}
UI_SORT_NAME_Z_A -> {
LogEx.logDebug(TAG, "sortByMode 4")
return list.sortedByDescending { File(it.path).name }
}
}
return list
}
......@@ -143,7 +188,10 @@ class DocumentPageFragment() : BaseFragment<FragmentDocumentPageBinding>(), Docu
fun getSearchItems(search: String): List<DocumentBean> {
if (isVisible) {
return adapter.items.filter { File(it.path).name.lowercase(Locale.ENGLISH).contains(search.lowercase(Locale.ENGLISH)) }
return adapter.items.filter {
File(it.path).name.lowercase(Locale.ENGLISH)
.contains(search.lowercase(Locale.ENGLISH))
}
}
return listOf()
}
......
......@@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
......@@ -21,15 +22,18 @@ import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfActivity
import com.base.pdfviewerscannerwhite.ui.document.ppt.PptActivity
import com.base.pdfviewerscannerwhite.ui.document.word.WordActivity
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDeleteDialog
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showDocumentRenameDialog
import com.base.pdfviewerscannerwhite.ui.view.DialogView.showStoragePermission
import com.base.pdfviewerscannerwhite.ui.view.PdfDialog.showPdfPwdDialog
import com.base.pdfviewerscannerwhite.utils.IntentShareUtils.shareMutDocuments
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.PermissionUtils.checkStorePermission
import com.base.pdfviewerscannerwhite.utils.updateMediaStore
import java.io.File
class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
private val TAG="MainActivity"
private val TAG = "MainActivity"
lateinit var mainPresenter: MainPresenter
override val binding: ActivityMain2Binding by lazy {
ActivityMain2Binding.inflate(layoutInflater)
......@@ -49,25 +53,28 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
private var currentFragment: Fragment = documentFragment
override fun initView() {
LogEx.logDebug(TAG,"initView")
mainPresenter = MainPresenter(this, this, lifecycleScope)
LogEx.logDebug(TAG, "initView")
mainPresenter = MainPresenter(this, this, lifecycleScope)
mainPresenter.initScannerLauncher(this)
}
override fun onResume() {
super.onResume()
if (checkStorePermission() && needRefresh) {
mainPresenter.initAllDocumentData()
// Log.d("glc","我被调用了A")
} else {
showStoragePermission(launcher, allowAction = {
mainPresenter.initAllDocumentData()
// mainPresenter.initAllDocumentData()
// Log.d("glc","我被调用了B")
})
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
LogEx.logDebug(TAG,"onSaveInstanceState")
LogEx.logDebug(TAG, "onSaveInstanceState")
}
var isDocumentAdd: Boolean = false
......@@ -114,6 +121,7 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
}
currentFragment = documentFragment
isDocumentAdd = true
binding.ivScan.visibility = View.VISIBLE
}
binding.llDocument.callOnClick()
binding.llRecent.setOnClickListener {
......@@ -130,6 +138,7 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
}
currentFragment = recentFragment
isRecentAdd = true
binding.ivScan.visibility = View.VISIBLE
}
binding.llBookmark.setOnClickListener {
changeTabSelect(it)
......@@ -146,6 +155,7 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
}
currentFragment = bookmarkFragment
isBookmarkAdd = true
binding.ivScan.visibility = View.VISIBLE
}
binding.llTool.setOnClickListener {
changeTabSelect(it)
......@@ -159,8 +169,10 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
show(toolFragment)
commit()
}
currentFragment.userVisibleHint = true
currentFragment = toolFragment
isToolAdd = true
binding.ivScan.visibility = View.INVISIBLE
}
binding.llDelete.setOnClickListener {
if (currentFragment is DocumentPageFragment) {
......@@ -175,6 +187,9 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
binding.llShare.setOnClickListener {
shareDocument()
}
binding.ivScan.setOnClickListener {
mainPresenter.starGmsScan(this)
}
}
......@@ -222,6 +237,18 @@ class MainActivity : BaseActivity<ActivityMain2Binding>(), MainView {
override fun handleActivityGmsScanResult(imageUri: Uri, pdfUri: Uri) {
// LogEx.logDebug(TAG, "imageUri=$imageUri")
LogEx.logDebug(TAG, "pdfUri=$pdfUri")
val file = File(pdfUri.toString().replace("file://", ""))
if (file.exists()) {
// binding.tvTest.text = "imageUri=$imageUri\n\n\n\npdfUri=$pdfUri"
showDocumentRenameDialog(file.name) {
val newFile = File(mainPresenter.getDocumentAppDir(), "$it.pdf")
mainPresenter.copyFile(file, newFile)
this.updateMediaStore()
// refreshPageList()
}
}
}
......
......@@ -4,6 +4,8 @@ import android.app.Activity
import android.content.Context
import android.content.IntentSender
import android.net.Uri
import android.os.Environment
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
......@@ -18,9 +20,13 @@ import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfBoxUtils
import com.base.pdfviewerscannerwhite.utils.AssetUtils.saveAssetsFile
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatTime3
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.SpStringUtils
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.BOOKMARK_KEY
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.LAST_VIEW_KEY
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import com.base.pdfviewerscannerwhite.utils.getMediaFile
import com.base.pdfviewerscannerwhite.utils.upDateDemoStore
......@@ -39,6 +45,14 @@ class MainPresenter(
val lifecycleScope: LifecycleCoroutineScope
) {
private val TAG = "MainPresenter"
fun getDocumentAppDir(): File {
val appDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), context.packageName)
if (!appDir.exists())
appDir.exists()
return appDir
}
//所有fragment的数据,都从这里取
val pdfDocuments = arrayListOf<DocumentBean>()
val wordDocuments = arrayListOf<DocumentBean>()
......@@ -48,32 +62,23 @@ class MainPresenter(
private lateinit var scannerLauncher: ActivityResultLauncher<IntentSenderRequest>
fun initAllDocumentData() = lifecycleScope.launch(Dispatchers.IO) {
pdfDocuments.clear()
wordDocuments.clear()
excelDocuments.clear()
pptDocuments.clear()
Log.d("glc", "pdfs 清理前:" + pdfDocuments.size)
context.upDateDemoStore()
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
pdfDocuments.addAll(initAllPdfData())
lifecycleScope.launch(Dispatchers.Main) {
mainView.refreshPageList()
}
val pdfs = initAllPdfData()
pdfs.map { it.state = PdfBoxUtils.checkPdfEncryption(it.path) }
pdfDocuments.clear()
wordDocuments.clear()
excelDocuments.clear()
pptDocuments.clear()
Log.d("glc", "pdfs:" + pdfs.size)
pdfDocuments.addAll(pdfs)
Log.d("glc", "添加了 pdfDocuments:" + pdfDocuments.size)
wordDocuments.addAll(initAllWordData())
lifecycleScope.launch(Dispatchers.Main) {
mainView.refreshPageList()
}
excelDocuments.addAll(initAllExcelData())
lifecycleScope.launch(Dispatchers.Main) {
mainView.refreshPageList()
}
pptDocuments.addAll(initAllPptData())
lifecycleScope.launch(Dispatchers.Main) {
mainView.refreshPageList()
......@@ -85,6 +90,9 @@ class MainPresenter(
val bookmarkList = SpStringUtils.getSpStringList(SpStringUtils.BOOKMARK_KEY)
Log.d("glc", "pdfDocuments:" + pdfDocuments.size)
val recentList = SpStringUtils.getSpStringList(LAST_VIEW_KEY)
when (documentType) {
TYPE_PDF -> {
pdfDocuments.forEach {
......@@ -96,7 +104,8 @@ class MainPresenter(
}
RECENT_DATA_TYPE -> {
return pdfDocuments.filter { recentFilter(it) }
pdfDocuments.forEach { recentFilter(recentList, it) }
return pdfDocuments.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
}
BOOKMARK_DATA_TYPE -> {
......@@ -117,7 +126,8 @@ class MainPresenter(
}
RECENT_DATA_TYPE -> {
return wordDocuments.filter { recentFilter(it) }
wordDocuments.forEach { recentFilter(recentList, it) }
return wordDocuments.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
}
BOOKMARK_DATA_TYPE -> {
......@@ -138,7 +148,8 @@ class MainPresenter(
}
RECENT_DATA_TYPE -> {
return excelDocuments.filter { recentFilter(it) }
excelDocuments.forEach { recentFilter(recentList, it) }
return excelDocuments.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
}
BOOKMARK_DATA_TYPE -> {
......@@ -158,7 +169,8 @@ class MainPresenter(
}
RECENT_DATA_TYPE -> {
return pptDocuments.filter { recentFilter(it) }
pptDocuments.forEach { recentFilter(recentList, it) }
return pptDocuments.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
}
BOOKMARK_DATA_TYPE -> {
......@@ -171,8 +183,16 @@ class MainPresenter(
return listOf()
}
private fun recentFilter(documentBean: DocumentBean): Boolean {
return (System.currentTimeMillis() - File(documentBean.path).lastModified()) < 300L * 24 * 60 * 60 * 1000
private fun recentFilter(recentList: List<String>, documentBean: DocumentBean) {
val findLastTime = recentList.filter { it.contains(documentBean.path) }.map {
it.split("_/_")[1].toLong()
}
if (findLastTime.isNotEmpty()) {
val max = findLastTime.max()
LogEx.logDebug(TAG, "recentFilter ${documentBean.path} ${max.toFormatTime3()}")
documentBean.lastViewTime = max
}
}
......@@ -372,4 +392,17 @@ class MainPresenter(
}
}
fun copyFile(file: File, newFile: File) {
runCatching {
file.copyTo(newFile, true)
}
}
fun changePdfLock(item: DocumentBean, documentPageFragment: DocumentPageFragment) {
val pdf = pdfDocuments.find { it.path == item.path }
pdf?.state = PdfBoxUtils.checkPdfEncryption(item.path)
documentPageFragment.refreshData()
}
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ 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.set.SetActivity
import com.base.pdfviewerscannerwhite.ui.view.PdfDialog.showPdfPwdDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
......@@ -87,6 +88,9 @@ class ToolFragment : BaseFragment<FragmentToolBinding>() {
putExtra("doWhat", DO_UNLOCK_PDF)
})
}
binding.llSet.setOnClickListener {
startActivity(Intent(requireContext(), SetActivity::class.java))
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.set
import androidx.activity.addCallback
import androidx.core.widget.addTextChangedListener
import com.base.pdfviewerscannerwhite.databinding.ActivityFeedbackBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
class FeedbackActivity : BaseActivity<ActivityFeedbackBinding>() {
override val binding: ActivityFeedbackBinding by lazy {
ActivityFeedbackBinding.inflate(layoutInflater)
}
override fun initView() {
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
finish()
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.edit.addTextChangedListener {
binding.tvBtn.isEnabled = it?.isNotEmpty() == true
}
binding.tvBtn.setOnClickListener {
toast("Feedback success")
onBackPressedDispatcher.onBackPressed()
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.set
import android.content.Intent
import android.net.Uri
import androidx.activity.addCallback
import com.base.pdfviewerscannerwhite.databinding.ActivitySetBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.helper.ConfigHelper
import com.base.pdfviewerscannerwhite.ui.view.RateDialog.showRateDialog
class SetActivity : BaseActivity<ActivitySetBinding>() {
override val binding: ActivitySetBinding by lazy {
ActivitySetBinding.inflate(layoutInflater)
}
override fun initView() {
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
finishToMain()
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.llRate.setOnClickListener {
showRateDialog(true)
}
binding.llFeedback.setOnClickListener {
startActivity(Intent(this, FeedbackActivity::class.java))
}
binding.llPrivacy.setOnClickListener {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(ConfigHelper.privacyPolicy)
)
startActivity(intent)
}
binding.llTerm.setOnClickListener {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(ConfigHelper.termService)
)
startActivity(intent)
}
}
}
\ No newline at end of file
......@@ -3,11 +3,16 @@ package com.base.pdfviewerscannerwhite.ui.view
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import androidx.core.widget.addTextChangedListener
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_FINAL_MODIFIED
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_LAST_MODIFIED
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_NAME_A_Z
import com.base.pdfviewerscannerwhite.bean.ConstObject.UI_SORT_NAME_Z_A
import com.base.pdfviewerscannerwhite.bean.DocumentBean
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PPT
......@@ -19,6 +24,7 @@ import com.base.pdfviewerscannerwhite.databinding.DialogDocumentHomeMoreBinding
import com.base.pdfviewerscannerwhite.databinding.DialogDocumentMoreBinding
import com.base.pdfviewerscannerwhite.databinding.DialogDocumentRenameBinding
import com.base.pdfviewerscannerwhite.databinding.DialogPageNumberBinding
import com.base.pdfviewerscannerwhite.databinding.DialogSortBinding
import com.base.pdfviewerscannerwhite.databinding.DialogStoragePermissionBinding
import com.base.pdfviewerscannerwhite.ui.main.DocumentFragment
import com.base.pdfviewerscannerwhite.ui.main.DocumentPageFragment
......@@ -67,6 +73,88 @@ object DialogView {
}
}
var SortMode = UI_SORT_LAST_MODIFIED
fun Context.showSortDialog(okAction: () -> Unit) {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
val binding = DialogSortBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
val showSortUI: (mode: String) -> Unit = { mode ->
when (mode) {
UI_SORT_LAST_MODIFIED -> {
binding.iv1.visibility = View.VISIBLE
binding.tv1.setTextColor(Color.parseColor("#00B8DE"))
}
UI_SORT_FINAL_MODIFIED -> {
binding.iv2.visibility = View.VISIBLE
binding.tv2.setTextColor(Color.parseColor("#00B8DE"))
}
UI_SORT_NAME_A_Z -> {
binding.iv3.visibility = View.VISIBLE
binding.tv3.setTextColor(Color.parseColor("#00B8DE"))
}
UI_SORT_NAME_Z_A -> {
binding.iv4.visibility = View.VISIBLE
binding.tv4.setTextColor(Color.parseColor("#00B8DE"))
}
}
}
val resetUI = {
binding.iv1.visibility = View.INVISIBLE
binding.iv2.visibility = View.INVISIBLE
binding.iv3.visibility = View.INVISIBLE
binding.iv4.visibility = View.INVISIBLE
binding.tv1.setTextColor(Color.parseColor("#333333"))
binding.tv2.setTextColor(Color.parseColor("#333333"))
binding.tv3.setTextColor(Color.parseColor("#333333"))
binding.tv4.setTextColor(Color.parseColor("#333333"))
}
showSortUI.invoke(SortMode)
var temp: String = SortMode
binding.llLastModified.setOnClickListener {
temp = UI_SORT_LAST_MODIFIED
resetUI.invoke()
showSortUI.invoke(temp)
}
binding.llFinalModified.setOnClickListener {
temp = UI_SORT_FINAL_MODIFIED
resetUI.invoke()
showSortUI.invoke(temp)
}
binding.llNameAZ.setOnClickListener {
temp = UI_SORT_NAME_A_Z
resetUI.invoke()
showSortUI.invoke(temp)
}
binding.llNameZA.setOnClickListener {
temp = UI_SORT_NAME_Z_A
resetUI.invoke()
showSortUI.invoke(temp)
}
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
binding.tvOk.setOnClickListener {
dialog.dismiss()
SortMode = temp
okAction.invoke()
}
}
fun Context.showDocumentDetail(path: String) {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
val binding = DialogDocumentDetailBinding.inflate(LayoutInflater.from(this))
......
......@@ -119,7 +119,7 @@ object PdfDialog {
binding.llLock.setOnClickListener {
showPdfPwdDialog(state = item.state, path = item.path, firstDialog = dialog, encryptionAction = {
dialog.dismiss()
documentPageFragment.adapter.notifyDataSetChanged()
mainActivity.mainPresenter.changePdfLock(item,documentPageFragment)
})
}
dialog.setOnDismissListener {
......
package com.base.pdfviewerscannerwhite.utils
object SpStringUtils {
private val TAG="SpStringUtils"
const val BOOKMARK_KEY = "bookmark_key"
const val LAST_VIEW_KEY = "last_view_key"
......@@ -14,6 +15,7 @@ object SpStringUtils {
}
fun addSpString(key: String, value: String) {
LogEx.logDebug(TAG,"key=$key value=$value")
val list = getSpStringList(key).toMutableList()
list.add(value)
val string = list.joinToString(separator = "|||")
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FAFCFB" />
<corners android:radius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.set.FeedbackActivity">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/fanhui_b"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="Feedback"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui"
tools:ignore="HardcodedText" />
<EditText
android:layout_marginTop="30dp"
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="485dp"
android:layout_marginHorizontal="15dp"
android:background="@drawable/bg_fafcfb_15"
android:gravity="top|start"
android:hint="Please enter your feedback or thoughts"
android:inputType="text"
android:paddingHorizontal="20dp"
android:paddingVertical="25dp"
android:textColor="@color/black"
android:textColorHint="#BFBFBF"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui"
tools:ignore="Autofill,HardcodedText,TextFields" />
<TextView
android:id="@+id/tv_btn"
android:layout_width="338dp"
android:layout_height="48dp"
android:layout_marginBottom="25dp"
android:background="@drawable/bg_selector_btn"
android:enabled="false"
android:gravity="center"
android:text="Send"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -243,5 +243,16 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:visibility="gone"
android:id="@+id/tv_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -81,7 +81,7 @@
android:layout_height="48dp"
android:layout_marginBottom="24dp"
android:background="@drawable/bg_selector_btn"
android:enabled="true"
android:enabled="false"
android:gravity="center"
android:text="Merge"
android:textColor="@color/white"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.set.SetActivity">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/fanhui_b"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Set"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui" />
<LinearLayout
android:id="@+id/ll_rate"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="15dp"
android:layout_marginTop="15dp"
android:background="@drawable/bg_fbfbfb_15"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="18dp"
android:src="@mipmap/pingjia"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Evaluate Us"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_feedback"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="15dp"
android:background="@drawable/bg_fbfbfb_15"
app:layout_constraintTop_toBottomOf="@id/ll_rate">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="18dp"
android:src="@mipmap/fankui"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Feedback"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_privacy"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="15dp"
android:background="@drawable/bg_fbfbfb_15"
app:layout_constraintTop_toBottomOf="@id/ll_feedback">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="18dp"
android:src="@mipmap/yinsi"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Privacy Policy"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_term"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="15dp"
android:background="@drawable/bg_fbfbfb_15"
app:layout_constraintTop_toBottomOf="@id/ll_privacy">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="18dp"
android:src="@mipmap/tiaokuan"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Term of service"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_f3f3f3_tlr25"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="65dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:includeFontPadding="false"
android:text="Sort Order"
android:textColor="#333333"
android:textSize="17sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fl">
<LinearLayout
android:id="@+id/ll_last_modified"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16.5dp"
android:background="?android:attr/selectableItemBackground"
android:paddingVertical="15dp"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Last modification (From new to 1st)"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/sort_xia"
android:visibility="invisible"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_final_modified"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16.5dp"
android:background="?android:attr/selectableItemBackground"
android:paddingVertical="15dp"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Final modification (From old to new)"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/sort_xia"
android:visibility="invisible"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_name_a_z"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16.5dp"
android:background="?android:attr/selectableItemBackground"
android:paddingVertical="15dp"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Name (A-Z)"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/sort_xia"
android:visibility="invisible"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_name_z_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16.5dp"
android:background="?android:attr/selectableItemBackground"
android:paddingVertical="15dp"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/tv_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="Name (Z-A)"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/sort_xia"
android:visibility="invisible"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="26dp"
android:layout_marginBottom="20dp">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="163dp"
android:layout_height="48dp"
android:background="@drawable/bg_f1f2f6_10"
android:gravity="center"
android:text="Cancel"
android:textColor="#505050"
android:textSize="18sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_ok"
android:layout_width="163dp"
android:layout_height="48dp"
android:layout_marginStart="14dp"
android:background="@drawable/bg_00b8de_10"
android:gravity="center"
android:text="Ok"
android:textColor="@color/white"
android:textSize="18sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -4,14 +4,37 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".ui.main.ToolFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="60dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="Tool"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="42dp">
android:layout_marginTop="20dp">
<LinearLayout
......
<resources>
<string name="app_name">PDF Viewer &amp; Scanner</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" tools:ignore="MissingTranslation">PDF Reader &amp; Scanner</string>
<string name="next" tools:ignore="MissingTranslation">Next</string>
<string name="previous" tools:ignore="MissingTranslation">Previous</string>
<string name="lorem_ipsum">
<string name="lorem_ipsum" tools:ignore="MissingTranslation">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris volutpat, dolor id interdum
ullamcorper, risus dolor egestas lectus, sit amet mattis purus dui nec risus. Maecenas non sodales nisi, vel dictum dolor.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse blandit eleifend diam,
......
......@@ -12,8 +12,8 @@ android {
targetSdk 34
ndk {
abiFilters "arm64-v8a"
// "armeabi-v7a"
//noinspection ChromeOsAbiSupport
abiFilters "arm64-v8a", "armeabi-v7a"
}
sourceSets {
......
......@@ -24,206 +24,205 @@ import android.widget.ListView;
import com.lonelypluto.pdfviewerlibrary.R;
enum Purpose {
PickPDF,
PickKeyFile
PickPDF,
PickKeyFile
}
public class ChoosePDFActivity extends ListActivity {
static public final String PICK_KEY_FILE = "com.artifex.mupdfdemo.PICK_KEY_FILE";
static private File mDirectory;
static private Map<String, Integer> mPositions = new HashMap<String, Integer>();
private File mParent;
private File [] mDirs;
private File [] mFiles;
private Handler mHandler;
private Runnable mUpdateFiles;
private ChoosePDFAdapter adapter;
private Purpose mPurpose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPurpose = PICK_KEY_FILE.equals(getIntent().getAction()) ? Purpose.PickKeyFile : Purpose.PickPDF;
String storageState = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(storageState)
&& !Environment.MEDIA_MOUNTED_READ_ONLY.equals(storageState))
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.no_media_warning);
builder.setMessage(R.string.no_media_hint);
AlertDialog alert = builder.create();
alert.setButton(AlertDialog.BUTTON_POSITIVE,getString(R.string.dismiss),
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
return;
}
if (mDirectory == null)
mDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// Create a list adapter...
adapter = new ChoosePDFAdapter(getLayoutInflater());
setListAdapter(adapter);
// ...that is updated dynamically when files are scanned
mHandler = new Handler();
mUpdateFiles = new Runnable() {
public void run() {
Resources res = getResources();
String appName = res.getString(R.string.app_name);
String version = res.getString(R.string.version);
String title = res.getString(R.string.picker_title_App_Ver_Dir);
setTitle(String.format(title, appName, version, mDirectory));
mParent = mDirectory.getParentFile();
mDirs = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
});
if (mDirs == null)
mDirs = new File[0];
mFiles = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
if (file.isDirectory())
return false;
String fname = file.getName().toLowerCase();
switch (mPurpose) {
case PickPDF:
if (fname.endsWith(".pdf"))
return true;
if (fname.endsWith(".xps"))
return true;
if (fname.endsWith(".cbz"))
return true;
if (fname.endsWith(".epub"))
return true;
if (fname.endsWith(".png"))
return true;
if (fname.endsWith(".jpe"))
return true;
if (fname.endsWith(".jpeg"))
return true;
if (fname.endsWith(".jpg"))
return true;
if (fname.endsWith(".jfif"))
return true;
if (fname.endsWith(".jfif-tbnl"))
return true;
if (fname.endsWith(".tif"))
return true;
if (fname.endsWith(".tiff"))
return true;
return false;
case PickKeyFile:
if (fname.endsWith(".pfx"))
return true;
return false;
default:
return false;
}
}
});
if (mFiles == null)
mFiles = new File[0];
Arrays.sort(mFiles, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
Arrays.sort(mDirs, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
adapter.clear();
if (mParent != null)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.PARENT, getString(R.string.parent_directory)));
for (File f : mDirs)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DIR, f.getName()));
for (File f : mFiles)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DOC, f.getName()));
lastPosition();
}
};
// Start initial file scan...
mHandler.post(mUpdateFiles);
// ...and observe the directory and scan files upon changes.
FileObserver observer = new FileObserver(mDirectory.getPath(), FileObserver.CREATE | FileObserver.DELETE) {
public void onEvent(int event, String path) {
mHandler.post(mUpdateFiles);
}
};
observer.startWatching();
}
private void lastPosition() {
String p = mDirectory.getAbsolutePath();
if (mPositions.containsKey(p))
getListView().setSelection(mPositions.get(p));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
if (position < (mParent == null ? 0 : 1)) {
mDirectory = mParent;
mHandler.post(mUpdateFiles);
return;
}
position -= (mParent == null ? 0 : 1);
if (position < mDirs.length) {
mDirectory = mDirs[position];
mHandler.post(mUpdateFiles);
return;
}
position -= mDirs.length;
Uri uri = Uri.fromFile(mFiles[position]);
Intent intent = new Intent(this,MuPDFActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
switch (mPurpose) {
case PickPDF:
// Start an activity to display the PDF file
startActivity(intent);
break;
case PickKeyFile:
// Return the uri to the caller
setResult(RESULT_OK, intent);
finish();
break;
}
}
@Override
protected void onPause() {
super.onPause();
if (mDirectory != null)
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
}
static public final String PICK_KEY_FILE = "com.artifex.mupdfdemo.PICK_KEY_FILE";
static private File mDirectory;
static private Map<String, Integer> mPositions = new HashMap<String, Integer>();
private File mParent;
private File[] mDirs;
private File[] mFiles;
private Handler mHandler;
private Runnable mUpdateFiles;
private ChoosePDFAdapter adapter;
private Purpose mPurpose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPurpose = PICK_KEY_FILE.equals(getIntent().getAction()) ? Purpose.PickKeyFile : Purpose.PickPDF;
String storageState = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(storageState)
&& !Environment.MEDIA_MOUNTED_READ_ONLY.equals(storageState)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.no_media_warning);
builder.setMessage(R.string.no_media_hint);
AlertDialog alert = builder.create();
alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.dismiss),
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
return;
}
if (mDirectory == null)
mDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// Create a list adapter...
adapter = new ChoosePDFAdapter(getLayoutInflater());
setListAdapter(adapter);
// ...that is updated dynamically when files are scanned
mHandler = new Handler();
mUpdateFiles = new Runnable() {
public void run() {
Resources res = getResources();
String appName = "app_name";
String version = "1.0";
String title = res.getString(R.string.picker_title_App_Ver_Dir);
setTitle(String.format(title, appName, version, mDirectory));
mParent = mDirectory.getParentFile();
mDirs = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
});
if (mDirs == null)
mDirs = new File[0];
mFiles = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
if (file.isDirectory())
return false;
String fname = file.getName().toLowerCase();
switch (mPurpose) {
case PickPDF:
if (fname.endsWith(".pdf"))
return true;
if (fname.endsWith(".xps"))
return true;
if (fname.endsWith(".cbz"))
return true;
if (fname.endsWith(".epub"))
return true;
if (fname.endsWith(".png"))
return true;
if (fname.endsWith(".jpe"))
return true;
if (fname.endsWith(".jpeg"))
return true;
if (fname.endsWith(".jpg"))
return true;
if (fname.endsWith(".jfif"))
return true;
if (fname.endsWith(".jfif-tbnl"))
return true;
if (fname.endsWith(".tif"))
return true;
if (fname.endsWith(".tiff"))
return true;
return false;
case PickKeyFile:
if (fname.endsWith(".pfx"))
return true;
return false;
default:
return false;
}
}
});
if (mFiles == null)
mFiles = new File[0];
Arrays.sort(mFiles, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
Arrays.sort(mDirs, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
adapter.clear();
if (mParent != null)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.PARENT, getString(R.string.parent_directory)));
for (File f : mDirs)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DIR, f.getName()));
for (File f : mFiles)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DOC, f.getName()));
lastPosition();
}
};
// Start initial file scan...
mHandler.post(mUpdateFiles);
// ...and observe the directory and scan files upon changes.
FileObserver observer = new FileObserver(mDirectory.getPath(), FileObserver.CREATE | FileObserver.DELETE) {
public void onEvent(int event, String path) {
mHandler.post(mUpdateFiles);
}
};
observer.startWatching();
}
private void lastPosition() {
String p = mDirectory.getAbsolutePath();
if (mPositions.containsKey(p))
getListView().setSelection(mPositions.get(p));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
if (position < (mParent == null ? 0 : 1)) {
mDirectory = mParent;
mHandler.post(mUpdateFiles);
return;
}
position -= (mParent == null ? 0 : 1);
if (position < mDirs.length) {
mDirectory = mDirs[position];
mHandler.post(mUpdateFiles);
return;
}
position -= mDirs.length;
Uri uri = Uri.fromFile(mFiles[position]);
Intent intent = new Intent(this, MuPDFActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
switch (mPurpose) {
case PickPDF:
// Start an activity to display the PDF file
startActivity(intent);
break;
case PickKeyFile:
// Return the uri to the caller
setResult(RESULT_OK, intent);
finish();
break;
}
}
@Override
protected void onPause() {
super.onPause();
if (mDirectory != null)
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="accept">接受</string>
<string name="app_name">MuPDF</string>
<string name="cancel">取消</string>
<string name="cannot_open_buffer">无法打开缓冲器</string>
<string name="cannot_open_document">无法打开文档</string>
<string name="cannot_open_document_Reason">无法打开文档: %1$s</string>
<string name="cannot_open_file_Path">无法打开文件:%1$s</string>
<string name="choose_value">选择值</string>
<string name="copied_to_clipboard">已复制到剪贴板</string>
<string name="copy">复制</string>
<string name="copy_text">复制文本</string>
<string name="copy_text_to_the_clipboard">将文本复制到剪贴板</string>
<string name="delete">删除</string>
<string name="dismiss">解除</string>
<string name="document_has_changes_save_them_">文档已变更,保存变更吗?</string>
<string name="draw_annotation">作批注</string>
<string name="edit_annotations">编辑批注</string>
<string name="enter_password">输入密码</string>
<string name="entering_reflow_mode">输入重排模式</string>
<string name="fill_out_text_field">填充文本字段</string>
<string name="format_currently_not_supported">当前不支持此格式</string>
<string name="highlight">高亮</string>
<string name="ink">墨迹</string>
<string name="leaving_reflow_mode">正在离开重排模式</string>
<string name="more">更多</string>
<string name="no"></string>
<string name="no_further_occurrences_found">未发现更多实例。</string>
<string name="no_media_hint">存储介质在设备和 PC 上共同使用,会导致该存储介质在设备上无法被访问</string>
<string name="no_media_warning">没有存储介质</string>
<string name="no_text_selected">未选择文本</string>
<string name="not_supported">不被支持</string>
<string name="nothing_to_save">没有要保存的内容</string>
<string name="okay">确定</string>
<string name="outline_title">目录</string>
<string name="parent_directory">[向上一级]</string>
<string name="picker_title_App_Ver_Dir">%1$s%2$s:%3$s</string>
<string name="print">打印</string>
<string name="print_failed">未能打印</string>
<string name="save">保存</string>
<string name="search">搜索</string>
<string name="search_backwards">向后搜索</string>
<string name="search_document">搜索文档</string>
<string name="search_forwards">向前搜索</string>
<string name="searching_">正在搜索…</string>
<string name="select">选择</string>
<string name="select_text">选择文本</string>
<string name="strike_out">删除线</string>
<string name="text_not_found">未发现文本</string>
<string name="toggle_links">高亮并启用墨迹</string>
<string name="underline">下划线</string>
<string name="yes"></string>
<string name="select_certificate_and_sign">选择证书并签名?</string>
<string name="signature_checked">签名已检查</string>
<string name="accept">接受</string>
<string name="cancel">取消</string>
<string name="cannot_open_buffer">无法打开缓冲器</string>
<string name="cannot_open_document">无法打开文档</string>
<string name="cannot_open_document_Reason">无法打开文档: %1$s</string>
<string name="cannot_open_file_Path">无法打开文件:%1$s</string>
<string name="choose_value">选择值</string>
<string name="copied_to_clipboard">已复制到剪贴板</string>
<string name="copy">复制</string>
<string name="copy_text">复制文本</string>
<string name="copy_text_to_the_clipboard">将文本复制到剪贴板</string>
<string name="delete">删除</string>
<string name="dismiss">解除</string>
<string name="document_has_changes_save_them_">文档已变更,保存变更吗?</string>
<string name="draw_annotation">作批注</string>
<string name="edit_annotations">编辑批注</string>
<string name="enter_password">输入密码</string>
<string name="entering_reflow_mode">输入重排模式</string>
<string name="fill_out_text_field">填充文本字段</string>
<string name="format_currently_not_supported">当前不支持此格式</string>
<string name="highlight">高亮</string>
<string name="ink">墨迹</string>
<string name="leaving_reflow_mode">正在离开重排模式</string>
<string name="more">更多</string>
<string name="no"></string>
<string name="no_further_occurrences_found">未发现更多实例。</string>
<string name="no_media_hint">存储介质在设备和 PC 上共同使用,会导致该存储介质在设备上无法被访问</string>
<string name="no_media_warning">没有存储介质</string>
<string name="no_text_selected">未选择文本</string>
<string name="not_supported">不被支持</string>
<string name="nothing_to_save">没有要保存的内容</string>
<string name="okay">确定</string>
<string name="outline_title">目录</string>
<string name="parent_directory">[向上一级]</string>
<string name="picker_title_App_Ver_Dir">%1$s%2$s:%3$s</string>
<string name="print">打印</string>
<string name="print_failed">未能打印</string>
<string name="save">保存</string>
<string name="search">搜索</string>
<string name="search_backwards">向后搜索</string>
<string name="search_document">搜索文档</string>
<string name="search_forwards">向前搜索</string>
<string name="searching_">正在搜索…</string>
<string name="select">选择</string>
<string name="select_text">选择文本</string>
<string name="strike_out">删除线</string>
<string name="text_not_found">未发现文本</string>
<string name="toggle_links">高亮并启用墨迹</string>
<string name="underline">下划线</string>
<string name="yes"></string>
<string name="select_certificate_and_sign">选择证书并签名?</string>
<string name="signature_checked">签名已检查</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MuPDF</string>
<string name="version">1.9 (git build)</string>
<string name="no_media_warning">Storage media not present</string>
<string name="no_media_hint">Sharing the storage media with a PC can make it inaccessible</string>
<string name="cancel">Cancel</string>
......
File added
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