This commit is contained in:
kunfei
2023-09-20 10:55:41 +08:00
parent fd6910afb0
commit c378af0541
7 changed files with 63 additions and 139 deletions
+3 -3
View File
@@ -168,15 +168,15 @@ dependencies {
implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3') implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3')
//androidX //androidX
implementation('androidx.core:core-ktx:1.10.1') implementation('androidx.core:core-ktx:1.12.0')
implementation('androidx.appcompat:appcompat:1.6.1') implementation('androidx.appcompat:appcompat:1.6.1')
implementation('androidx.activity:activity-ktx:1.7.2') implementation('androidx.activity:activity-ktx:1.7.2')
implementation('androidx.fragment:fragment-ktx:1.6.1') implementation('androidx.fragment:fragment-ktx:1.6.1')
implementation('androidx.preference:preference-ktx:1.2.0') implementation('androidx.preference:preference-ktx:1.2.1')
implementation('androidx.constraintlayout:constraintlayout:2.1.4') implementation('androidx.constraintlayout:constraintlayout:2.1.4')
implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0') implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0')
implementation('androidx.viewpager2:viewpager2:1.0.0') implementation('androidx.viewpager2:viewpager2:1.0.0')
implementation('androidx.webkit:webkit:1.7.0') implementation('androidx.webkit:webkit:1.8.0')
//google //google
implementation('com.google.android.material:material:1.9.0') implementation('com.google.android.material:material:1.9.0')
@@ -89,7 +89,6 @@ object PreferKey {
const val syncBookProgress = "syncBookProgress" const val syncBookProgress = "syncBookProgress"
const val cronet = "Cronet" const val cronet = "Cronet"
const val antiAlias = "antiAlias" const val antiAlias = "antiAlias"
const val useLibArchive = "useLibArchive"
const val bitmapCacheSize = "bitmapCacheSize" const val bitmapCacheSize = "bitmapCacheSize"
const val preDownloadNum = "preDownloadNum" const val preDownloadNum = "preDownloadNum"
const val autoRefresh = "auto_refresh" const val autoRefresh = "auto_refresh"
@@ -25,7 +25,6 @@ import splitties.init.appCtx
object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val isCronet = appCtx.getPrefBoolean(PreferKey.cronet) val isCronet = appCtx.getPrefBoolean(PreferKey.cronet)
var useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias) var useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
var useLibArchive = appCtx.getPrefBoolean(PreferKey.useLibArchive)
var userAgent: String = getPrefUserAgent() var userAgent: String = getPrefUserAgent()
var isEInkMode = appCtx.getPrefString(PreferKey.themeMode) == "3" var isEInkMode = appCtx.getPrefString(PreferKey.themeMode) == "3"
var clickActionTL = appCtx.getPrefInt(PreferKey.clickActionTL, 2) var clickActionTL = appCtx.getPrefInt(PreferKey.clickActionTL, 2)
@@ -78,8 +77,6 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
PreferKey.antiAlias -> useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias) PreferKey.antiAlias -> useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
PreferKey.useLibArchive -> useLibArchive =
appCtx.getPrefBoolean(PreferKey.useLibArchive)
} }
} }
@@ -5,7 +5,6 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.github.junrar.exception.UnsupportedRarV5Exception
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppLog import io.legado.app.constant.AppLog
@@ -299,13 +298,8 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
AppPattern.bookFileRegex.matches(it) AppPattern.bookFileRegex.matches(it)
} }
}.onError { }.onError {
when (it) { AppLog.put("getArchiveEntriesName Error:\n${it.localizedMessage}", it)
is UnsupportedRarV5Exception -> context.toastOnUi("暂不支持 rar v5 解压") context.toastOnUi("getArchiveEntriesName Error:\n${it.localizedMessage}")
else -> {
AppLog.put("getArchiveEntriesName Error:\n${it.localizedMessage}", it)
context.toastOnUi("getArchiveEntriesName Error:\n${it.localizedMessage}")
}
}
}.onSuccess { }.onSuccess {
onSuccess.invoke(it) onSuccess.invoke(it)
} }
@@ -3,11 +3,7 @@ package io.legado.app.utils
import android.net.Uri import android.net.Uri
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import io.legado.app.constant.AppPattern.archiveFileRegex import io.legado.app.constant.AppPattern.archiveFileRegex
import io.legado.app.help.config.AppConfig
import io.legado.app.utils.compress.LibArchiveUtils import io.legado.app.utils.compress.LibArchiveUtils
import io.legado.app.utils.compress.RarUtils
import io.legado.app.utils.compress.SevenZipUtils
import io.legado.app.utils.compress.ZipUtils
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
@@ -65,49 +61,18 @@ object ArchiveUtils {
val workPathFileDoc = getCacheFolderFileDoc(name, path) val workPathFileDoc = getCacheFolderFileDoc(name, path)
val workPath = workPathFileDoc.toString() val workPath = workPathFileDoc.toString()
return if (AppConfig.useLibArchive) { return archiveFileDoc.openReadPfd().getOrThrow().use {
archiveFileDoc.openReadPfd().getOrThrow().use { LibArchiveUtils.unArchive(it, File(workPath), filter)
LibArchiveUtils.unArchive(it, File(workPath), filter)
}
} else {
archiveFileDoc.openInputStream().getOrThrow().use {
when {
name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(
it,
workPath,
filter
)
name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(
it,
workPath,
filter
)
name.endsWith(".7z", ignoreCase = true) -> SevenZipUtils.un7zToPath(
it,
workPath,
filter
)
else -> throw IllegalArgumentException("Unexpected archive format")
}
}
} }
} }
/* 遍历目录获取文件名 */ /* 遍历目录获取文件名 */
fun getArchiveFilesName(fileUri: Uri, filter: ((String) -> Boolean)? = null): List<String> = fun getArchiveFilesName(fileUri: Uri, filter: ((String) -> Boolean)? = null): List<String> =
if (AppConfig.useLibArchive) { getArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)
getLibArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)
} else {
getArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)
}
fun getLibArchiveFilesName( fun getArchiveFilesName(
fileDoc: FileDoc, fileDoc: FileDoc,
filter: ((String) -> Boolean)? = null filter: ((String) -> Boolean)? = null
): List<String> { ): List<String> {
@@ -126,31 +91,6 @@ object ArchiveUtils {
} }
fun getArchiveFilesName(
fileDoc: FileDoc,
filter: ((String) -> Boolean)? = null
): List<String> {
val name = fileDoc.name
checkAchieve(name)
return fileDoc.openInputStream().getOrThrow().use {
when {
name.endsWith(".rar", ignoreCase = true) -> {
RarUtils.getFilesName(it, filter)
}
name.endsWith(".zip", ignoreCase = true) -> {
ZipUtils.getFilesName(it, filter)
}
name.endsWith(".7z", ignoreCase = true) -> {
SevenZipUtils.getFilesName(it, filter)
}
else -> emptyList()
}
}
}
fun isArchive(name: String): Boolean { fun isArchive(name: String): Boolean {
return archiveFileRegex.matches(name) return archiveFileRegex.matches(name)
} }
@@ -13,6 +13,7 @@ import me.zhanghai.android.libarchive.ArchiveException
import java.io.File import java.io.File
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException import java.io.IOException
import java.io.InputStream
import java.io.InterruptedIOException import java.io.InterruptedIOException
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.channels.SeekableByteChannel import java.nio.channels.SeekableByteChannel
@@ -23,52 +24,52 @@ import java.nio.charset.StandardCharsets
object LibArchiveUtils { object LibArchiveUtils {
// @Throws(ArchiveException::class) @Throws(ArchiveException::class)
// fun openArchive( fun openArchive(
// inputStream: InputStream, inputStream: InputStream,
// ): Long { ): Long {
// val archive: Long = Archive.readNew() val archive: Long = Archive.readNew()
// var successful = false var successful = false
// try { try {
// Archive.setCharset(archive, StandardCharsets.UTF_8.name().toByteArray()) Archive.setCharset(archive, StandardCharsets.UTF_8.name().toByteArray())
// Archive.readSupportFilterAll(archive) Archive.readSupportFilterAll(archive)
// Archive.readSupportFormatAll(archive) Archive.readSupportFormatAll(archive)
// Archive.readSetCallbackData(archive, null) Archive.readSetCallbackData(archive, null)
// val buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE) val buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE)
// Archive.readSetReadCallback<Any?>(archive) { _, _ -> Archive.readSetReadCallback<Any?>(archive) { _, _ ->
// buffer.clear() buffer.clear()
// val bytesRead = try { val bytesRead = try {
// inputStream.read(buffer.array()) inputStream.read(buffer.array())
// } catch (e: IOException) { } catch (e: IOException) {
// throw ArchiveException(Archive.ERRNO_FATAL, "InputStream.read", e) throw ArchiveException(Archive.ERRNO_FATAL, "InputStream.read", e)
// } }
// if (bytesRead != -1) { if (bytesRead != -1) {
// buffer.limit(bytesRead) buffer.limit(bytesRead)
// buffer buffer
// } else { } else {
// null null
// } }
// } }
// Archive.readSetSkipCallback<Any?>(archive) { _, _, request -> Archive.readSetSkipCallback<Any?>(archive) { _, _, request ->
// try { try {
// inputStream.skip(request) inputStream.skip(request)
// } catch (e: IOException) { } catch (e: IOException) {
// throw ArchiveException(Archive.ERRNO_FATAL, "InputStream.skip", e) throw ArchiveException(Archive.ERRNO_FATAL, "InputStream.skip", e)
// } }
// } }
// Archive.readOpen1(archive) Archive.readOpen1(archive)
// successful = true successful = true
// return archive return archive
//
//
// } finally { } finally {
// if (!successful) { if (!successful) {
// Archive.free(archive) Archive.free(archive)
// } }
// } }
//
//
// } }
@Throws(ArchiveException::class) @Throws(ArchiveException::class)
@@ -208,7 +209,9 @@ object LibArchiveUtils {
} }
/**
* 解压文件
*/
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unArchive( fun unArchive(
pfd: ParcelFileDescriptor, pfd: ParcelFileDescriptor,
@@ -218,14 +221,16 @@ object LibArchiveUtils {
return unArchive(openArchive(pfd), destDir, filter) return unArchive(openArchive(pfd), destDir, filter)
} }
/**
* 解压
*/
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
private fun unArchive( private fun unArchive(
archive: Long, archive: Long,
destDir: File?, destDir: File?,
filter: ((String) -> Boolean)? = null filter: ((String) -> Boolean)? = null
): List<File> { ): List<File> {
destDir ?: throw NullPointerException("路径不能为空") destDir ?: throw NullPointerException("路径不能为空")
val files = arrayListOf<File>() val files = arrayListOf<File>()
@@ -275,13 +280,8 @@ object LibArchiveUtils {
Archive.free(archive) Archive.free(archive)
} }
return files return files
} }
fun getFilesName(pfd: ParcelFileDescriptor, filter: ((String) -> Boolean)?): List<String> { fun getFilesName(pfd: ParcelFileDescriptor, filter: ((String) -> Boolean)?): List<String> {
@@ -98,12 +98,6 @@
android:summary="@string/pref_cronet_summary" android:summary="@string/pref_cronet_summary"
android:title="Cronet" /> android:title="Cronet" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="useLibArchive"
android:summary="@string/pref_use_lib_archive_summary"
android:title="@string/use_lib_archive" />
<io.legado.app.lib.prefs.SwitchPreference <io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="antiAlias" android:key="antiAlias"