Skip to content

Commit

Permalink
添加LibArchive解压
Browse files Browse the repository at this point in the history
  • Loading branch information
ag2s20150909 committed Sep 12, 2023
1 parent 9b45ce0 commit 99c2a2e
Show file tree
Hide file tree
Showing 23 changed files with 553 additions and 36 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ dependencies {
//颜色选择
implementation('com.jaredrummler:colorpicker:1.1.0')

implementation 'me.zhanghai.android.libarchive:library:1.0.0'

//apache
implementation('org.apache.commons:commons-text:1.10.0')
//noinspection GradleDependency,1.23.0对安卓支持不好
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/io/legado/app/constant/PreferKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ object PreferKey {
const val syncBookProgress = "syncBookProgress"
const val cronet = "Cronet"
const val antiAlias = "antiAlias"
const val useLibArchive = "useLibArchive"
const val bitmapCacheSize = "bitmapCacheSize"
const val preDownloadNum = "preDownloadNum"
const val autoRefresh = "auto_refresh"
Expand Down
21 changes: 19 additions & 2 deletions app/src/main/java/io/legado/app/help/config/AppConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ import io.legado.app.BuildConfig
import io.legado.app.constant.AppConst
import io.legado.app.constant.PreferKey
import io.legado.app.data.appDb
import io.legado.app.utils.*
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefInt
import io.legado.app.utils.getPrefLong
import io.legado.app.utils.getPrefString
import io.legado.app.utils.isNightMode
import io.legado.app.utils.putPrefBoolean
import io.legado.app.utils.putPrefInt
import io.legado.app.utils.putPrefLong
import io.legado.app.utils.putPrefString
import io.legado.app.utils.removePref
import io.legado.app.utils.sysConfiguration
import io.legado.app.utils.toastOnUi
import splitties.init.appCtx

@Suppress("MemberVisibilityCanBePrivate")
object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val isCronet = appCtx.getPrefBoolean(PreferKey.cronet)
val useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
var useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
var useLibArchive = appCtx.getPrefBoolean(PreferKey.useLibArchive)
var userAgent: String = getPrefUserAgent()
var isEInkMode = appCtx.getPrefString(PreferKey.themeMode) == "3"
var clickActionTL = appCtx.getPrefInt(PreferKey.clickActionTL, 2)
Expand Down Expand Up @@ -63,6 +75,11 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.getPrefBoolean(PreferKey.useZhLayout)

PreferKey.userAgent -> userAgent = getPrefUserAgent()

PreferKey.antiAlias -> useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)

PreferKey.useLibArchive -> useLibArchive =
appCtx.getPrefBoolean(PreferKey.useLibArchive)
}
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/io/legado/app/ui/widget/image/PhotoView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ class PhotoView @JvmOverloads constructor(
}

override fun onFling(
e1: MotionEvent,
e1: MotionEvent?,
e2: MotionEvent,
velocityX: Float,
velocityY: Float
Expand Down Expand Up @@ -1139,7 +1139,7 @@ class PhotoView @JvmOverloads constructor(
}

override fun onScroll(
e1: MotionEvent,
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.appcompat.widget.AppCompatTextView
class MultilineTextView(context: Context, attrs: AttributeSet?) :
AppCompatTextView(context, attrs) {

override fun onDraw(canvas: Canvas?) {
override fun onDraw(canvas: Canvas) {
calculateLines()
super.onDraw(canvas)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ open class ScrollMultiAutoCompleteTextView @JvmOverloads constructor(
}

override fun onScroll(
e1: MotionEvent,
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class ScrollTextView(context: Context, attrs: AttributeSet?) :
}

override fun onScroll(
e1: MotionEvent,
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
Expand Down
73 changes: 64 additions & 9 deletions app/src/main/java/io/legado/app/utils/ArchiveUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package io.legado.app.utils
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
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.RarUtils
import io.legado.app.utils.compress.SevenZipUtils
import io.legado.app.utils.compress.ZipUtils
Expand All @@ -14,6 +16,7 @@ import java.io.File
object ArchiveUtils {

const val TEMP_FOLDER_NAME = "ArchiveTemp"

// 临时目录 下次启动自动删除
val TEMP_PATH: String by lazy {
appCtx.externalCache.getFile(TEMP_FOLDER_NAME).createFolderReplace().absolutePath
Expand Down Expand Up @@ -61,19 +64,68 @@ object ArchiveUtils {
checkAchieve(name)
val workPathFileDoc = getCacheFolderFileDoc(name, path)
val workPath = workPathFileDoc.toString()
return 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")

return if (AppConfig.useLibArchive) {
archiveFileDoc.openReadPfd().getOrThrow().use {
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> = getArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)

fun getArchiveFilesName(fileUri: Uri, filter: ((String) -> Boolean)? = null): List<String> =
if (AppConfig.useLibArchive) {
getLibArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)
} else {
getArchiveFilesName(FileDoc.fromUri(fileUri, false), filter)
}


fun getLibArchiveFilesName(
fileDoc: FileDoc,
filter: ((String) -> Boolean)? = null
): List<String> {
val name = fileDoc.name
checkAchieve(name)

return fileDoc.openReadPfd().getOrThrow().use {
try {
LibArchiveUtils.getFilesName(it, filter)
} catch (e: Exception) {
emptyList()
}

}


}

fun getArchiveFilesName(
fileDoc: FileDoc,
filter: ((String) -> Boolean)? = null
Expand All @@ -85,14 +137,17 @@ object ArchiveUtils {
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()
}
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/io/legado/app/utils/FileDocExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.app.DownloadManager
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.ParcelFileDescriptor
import android.provider.DocumentsContract
import androidx.documentfile.provider.DocumentFile
import io.legado.app.exception.NoStackTraceException
Expand Down Expand Up @@ -236,6 +237,14 @@ fun FileDoc.openOutputStream(): Result<OutputStream> {
return uri.outputStream(appCtx)
}

fun FileDoc.openReadPfd(): Result<ParcelFileDescriptor> {
return uri.toReadPfd(appCtx)
}

fun FileDoc.openWritePfd(): Result<ParcelFileDescriptor> {
return uri.toWritePfd(appCtx)
}

fun FileDoc.exists(
fileName: String,
vararg subDirs: String
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/io/legado/app/utils/QRCodeUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ object QRCodeUtils {
}

// 生成二维码图片的格式
var bitmap = Bitmap.createBitmap(heightPix, heightPix, Bitmap.Config.ARGB_8888)
var bitmap: Bitmap? = Bitmap.createBitmap(heightPix, heightPix, Bitmap.Config.ARGB_8888)
bitmap!!.setPixels(pixels, 0, heightPix, 0, 0, heightPix, heightPix)
if (logo != null) {
bitmap = addLogo(bitmap, logo, ratio)
Expand Down Expand Up @@ -141,7 +141,7 @@ object QRCodeUtils {

//logo大小为二维码整体大小
val scaleFactor = srcWidth * ratio / logoWidth
var bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888)
var bitmap: Bitmap? = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888)
try {
val canvas = Canvas(bitmap!!)
canvas.drawBitmap(src, 0f, 0f, null)
Expand Down Expand Up @@ -449,7 +449,7 @@ object QRCodeUtils {
if (srcWidth <= 0 || srcHeight <= 0) {
return null
}
var bitmap = Bitmap.createBitmap(
var bitmap: Bitmap? = Bitmap.createBitmap(
srcWidth,
srcHeight + textSize + offset * 2,
Bitmap.Config.ARGB_8888
Expand Down
63 changes: 63 additions & 0 deletions app/src/main/java/io/legado/app/utils/UriExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.legado.app.utils

import android.content.Context
import android.net.Uri
import android.os.ParcelFileDescriptor
import androidx.appcompat.app.AppCompatActivity
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
Expand Down Expand Up @@ -232,6 +233,68 @@ fun Uri.outputStream(context: Context): Result<OutputStream> {
}
}

fun Uri.toReadPfd(context: Context): Result<ParcelFileDescriptor> {
val uri = this
return kotlin.runCatching {
try {
if (isContentScheme()) {
DocumentFile.fromSingleUri(context, uri)
?: throw NoStackTraceException("未获取到文件")
return@runCatching context.contentResolver.openFileDescriptor(uri, "r")!!
} else {
val path = RealPathUtil.getPath(context, uri)
?: throw NoStackTraceException("未获取到文件")
val file = File(path)
if (file.exists()) {
return@runCatching ParcelFileDescriptor.open(
file,
ParcelFileDescriptor.MODE_READ_ONLY
)
} else {
throw NoStackTraceException("文件不存在")
}
}


} catch (e: Exception) {
e.printOnDebug()
AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
throw e
}
}
}

fun Uri.toWritePfd(context: Context): Result<ParcelFileDescriptor> {
val uri = this
return kotlin.runCatching {
try {
if (isContentScheme()) {
DocumentFile.fromSingleUri(context, uri)
?: throw NoStackTraceException("未获取到文件")
return@runCatching context.contentResolver.openFileDescriptor(uri, "w")!!
} else {
val path = RealPathUtil.getPath(context, uri)
?: throw NoStackTraceException("未获取到文件")
val file = File(path)
if (file.exists()) {
return@runCatching ParcelFileDescriptor.open(
file,
ParcelFileDescriptor.MODE_WRITE_ONLY
)
} else {
throw NoStackTraceException("文件不存在")
}
}


} catch (e: Exception) {
e.printOnDebug()
AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
throw e
}
}
}

fun Uri.toRequestBody(contentType: MediaType? = null): RequestBody {
val uri = this
return object : RequestBody() {
Expand Down
Loading

0 comments on commit 99c2a2e

Please sign in to comment.