kunfei 4 anos atrás
pai
commit
70dd595df1

+ 1 - 1
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -69,7 +69,7 @@ fun Book.getLocalUri(): Uri {
             Uri.fromFile(File(bookUrl))
             Uri.fromFile(File(bookUrl))
         }
         }
         //先检测uri是否有效,这个比较快
         //先检测uri是否有效,这个比较快
-        uri.inputStream(appCtx)?.use {
+        uri.inputStream(appCtx).getOrNull()?.use {
             localUriCache[bookUrl] = uri
             localUriCache[bookUrl] = uri
         }?.let {
         }?.let {
             return uri
             return uri

+ 12 - 6
app/src/main/java/io/legado/app/model/localBook/LocalBook.kt

@@ -43,10 +43,11 @@ object LocalBook {
     fun getBookInputStream(book: Book): InputStream {
     fun getBookInputStream(book: Book): InputStream {
         val uri = book.getLocalUri()
         val uri = book.getLocalUri()
         //文件不存在 尝试下载webDav文件
         //文件不存在 尝试下载webDav文件
-        val inputStream = uri.inputStream(appCtx) ?: let {
-            book.removeLocalUriCache()
-            downloadRemoteBook(book)
-        }
+        val inputStream = uri.inputStream(appCtx).getOrNull()
+            ?: let {
+                book.removeLocalUriCache()
+                downloadRemoteBook(book)
+            }
         if (inputStream != null) return inputStream
         if (inputStream != null) return inputStream
         book.removeLocalUriCache()
         book.removeLocalUriCache()
         throw FileNotFoundException("${uri.path} 文件不存在")
         throw FileNotFoundException("${uri.path} 文件不存在")
@@ -241,7 +242,12 @@ object LocalBook {
             ?: throw NoStackTraceException("没有设置书籍保存位置!")
             ?: throw NoStackTraceException("没有设置书籍保存位置!")
         val bytes = when {
         val bytes = when {
             str.isAbsUrl() -> AnalyzeUrl(str, source = source).getInputStream()
             str.isAbsUrl() -> AnalyzeUrl(str, source = source).getInputStream()
-            str.isDataUrl() -> ByteArrayInputStream(Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT))
+            str.isDataUrl() -> ByteArrayInputStream(
+                Base64.decode(
+                    str.substringAfter("base64,"),
+                    Base64.DEFAULT
+                )
+            )
             else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL")
             else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL")
         }
         }
         return saveBookFile(bytes, fileName)
         return saveBookFile(bytes, fileName)
@@ -324,7 +330,7 @@ object LocalBook {
                 localBook.bookUrl = if (it.isContentScheme()) it.toString() else it.path!!
                 localBook.bookUrl = if (it.isContentScheme()) it.toString() else it.path!!
                 localBook.save()
                 localBook.save()
                 localBook.cacheLocalUri(it)
                 localBook.cacheLocalUri(it)
-                it.inputStream(appCtx)
+                it.inputStream(appCtx).getOrThrow()
             }
             }
         } catch (e: Exception) {
         } catch (e: Exception) {
             e.printOnDebug()
             e.printOnDebug()

+ 1 - 1
app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt

@@ -15,7 +15,7 @@ abstract class BaseAssociationViewModel(application: Application) : BaseViewMode
 
 
     fun importJson(uri: Uri) {
     fun importJson(uri: Uri) {
         when {
         when {
-            uri.inputStream(context).contains("bookSourceUrl") ->
+            uri.inputStream(context).getOrNull().contains("bookSourceUrl") ->
                 successLive.postValue(Pair("bookSource", uri.toString()))
                 successLive.postValue(Pair("bookSource", uri.toString()))
             else -> importJson(uri.readText(context))
             else -> importJson(uri.readText(context))
         }
         }

+ 1 - 1
app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt

@@ -23,7 +23,7 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo
                 val fileDoc = FileDoc.fromUri(uri, false)
                 val fileDoc = FileDoc.fromUri(uri, false)
                 fileName = fileDoc.name
                 fileName = fileDoc.name
                 kotlin.runCatching {
                 kotlin.runCatching {
-                    if (uri.inputStream(context).isJson()) {
+                    if (uri.inputStream(context).getOrNull().isJson()) {
                         importJson(uri)
                         importJson(uri)
                         return@execute
                         return@execute
                     }
                     }

+ 1 - 1
app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt

@@ -112,7 +112,7 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
                 }
                 }
                 mText.isUri() -> {
                 mText.isUri() -> {
                     val uri = Uri.parse(mText)
                     val uri = Uri.parse(mText)
-                    uri.inputStream(context)?.let {
+                    uri.inputStream(context).getOrThrow().let {
                         allSources.addAll(BookSource.fromJsonArray(it).getOrThrow())
                         allSources.addAll(BookSource.fromJsonArray(it).getOrThrow())
                     }
                     }
                 }
                 }

+ 17 - 10
app/src/main/java/io/legado/app/ui/book/group/GroupEditDialog.kt

@@ -12,6 +12,7 @@ import io.legado.app.lib.dialogs.alert
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import io.legado.app.utils.viewbindingdelegate.viewBinding
+import splitties.init.appCtx
 import splitties.views.onClick
 import splitties.views.onClick
 import java.io.FileOutputStream
 import java.io.FileOutputStream
 
 
@@ -27,17 +28,23 @@ class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
     private val viewModel by viewModels<GroupViewModel>()
     private val viewModel by viewModels<GroupViewModel>()
     private var bookGroup: BookGroup? = null
     private var bookGroup: BookGroup? = null
     val selectImage = registerForActivityResult(SelectImageContract()) {
     val selectImage = registerForActivityResult(SelectImageContract()) {
-        readUri(it?.uri) { fileDoc, inputStream ->
-            var file = requireContext().externalFiles
-            val suffix = fileDoc.name.substringAfterLast(".")
-            val fileName = it.uri!!.inputStream(requireContext())!!.use {
-                MD5Utils.md5Encode(it) + ".$suffix"
-            }
-            file = FileUtils.createFileIfNotExist(file, "covers", fileName)
-            FileOutputStream(file).use { outputStream ->
-                inputStream.copyTo(outputStream)
+        it ?: return@registerForActivityResult
+        it.uri ?: return@registerForActivityResult
+        readUri(it.uri) { fileDoc, inputStream ->
+            try {
+                var file = requireContext().externalFiles
+                val suffix = fileDoc.name.substringAfterLast(".")
+                val fileName = it.uri.inputStream(requireContext()).getOrThrow().use { tmp ->
+                    MD5Utils.md5Encode(tmp) + ".$suffix"
+                }
+                file = FileUtils.createFileIfNotExist(file, "covers", fileName)
+                FileOutputStream(file).use { outputStream ->
+                    inputStream.copyTo(outputStream)
+                }
+                binding.ivCover.load(file.absolutePath)
+            } catch (e: Exception) {
+                appCtx.toastOnUi(e.localizedMessage)
             }
             }
-            binding.ivCover.load(file.absolutePath)
         }
         }
     }
     }
 
 

+ 15 - 10
app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt

@@ -17,6 +17,7 @@ import io.legado.app.help.book.isLocal
 import io.legado.app.ui.book.changecover.ChangeCoverDialog
 import io.legado.app.ui.book.changecover.ChangeCoverDialog
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import io.legado.app.utils.viewbindingdelegate.viewBinding
+import splitties.init.appCtx
 import java.io.FileOutputStream
 import java.io.FileOutputStream
 
 
 class BookInfoEditActivity :
 class BookInfoEditActivity :
@@ -120,17 +121,21 @@ class BookInfoEditActivity :
 
 
     private fun coverChangeTo(uri: Uri) {
     private fun coverChangeTo(uri: Uri) {
         readUri(uri) { fileDoc, inputStream ->
         readUri(uri) { fileDoc, inputStream ->
-            inputStream.use {
-                var file = this.externalFiles
-                val suffix = fileDoc.name.substringAfterLast(".")
-                val fileName = uri.inputStream(this)!!.use {
-                    MD5Utils.md5Encode(it) + ".$suffix"
+            runCatching {
+                inputStream.use {
+                    var file = this.externalFiles
+                    val suffix = fileDoc.name.substringAfterLast(".")
+                    val fileName = uri.inputStream(this).getOrThrow().use {
+                        MD5Utils.md5Encode(it) + ".$suffix"
+                    }
+                    file = FileUtils.createFileIfNotExist(file, "covers", fileName)
+                    FileOutputStream(file).use { outputStream ->
+                        inputStream.copyTo(outputStream)
+                    }
+                    coverChangeTo(file.absolutePath)
                 }
                 }
-                file = FileUtils.createFileIfNotExist(file, "covers", fileName)
-                FileOutputStream(file).use { outputStream ->
-                    inputStream.copyTo(outputStream)
-                }
-                coverChangeTo(file.absolutePath)
+            }.onFailure {
+                appCtx.toastOnUi(it.localizedMessage)
             }
             }
         }
         }
     }
     }

+ 15 - 10
app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt

@@ -34,6 +34,7 @@ import io.legado.app.ui.document.HandleFileContract
 import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
 import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import io.legado.app.utils.viewbindingdelegate.viewBinding
+import splitties.init.appCtx
 
 
 import java.io.File
 import java.io.File
 import java.io.FileOutputStream
 import java.io.FileOutputStream
@@ -353,17 +354,21 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
 
 
     private fun setBgFromUri(uri: Uri) {
     private fun setBgFromUri(uri: Uri) {
         readUri(uri) { fileDoc, inputStream ->
         readUri(uri) { fileDoc, inputStream ->
-            var file = requireContext().externalFiles
-            val suffix = fileDoc.name.substringAfterLast(".")
-            val fileName = uri.inputStream(requireContext())!!.use {
-                MD5Utils.md5Encode(it) + ".$suffix"
-            }
-            file = FileUtils.createFileIfNotExist(file, "bg", fileName)
-            FileOutputStream(file).use { outputStream ->
-                inputStream.copyTo(outputStream)
+            kotlin.runCatching {
+                var file = requireContext().externalFiles
+                val suffix = fileDoc.name.substringAfterLast(".")
+                val fileName = uri.inputStream(requireContext()).getOrThrow().use {
+                    MD5Utils.md5Encode(it) + ".$suffix"
+                }
+                file = FileUtils.createFileIfNotExist(file, "bg", fileName)
+                FileOutputStream(file).use { outputStream ->
+                    inputStream.copyTo(outputStream)
+                }
+                ReadBookConfig.durConfig.setCurBg(2, file.absolutePath)
+                postEvent(EventBus.UP_CONFIG, false)
+            }.onFailure {
+                appCtx.toastOnUi(it.localizedMessage)
             }
             }
-            ReadBookConfig.durConfig.setCurBg(2, file.absolutePath)
-            postEvent(EventBus.UP_CONFIG, false)
         }
         }
     }
     }
 }
 }

+ 15 - 10
app/src/main/java/io/legado/app/ui/config/CoverConfigFragment.kt

@@ -14,6 +14,7 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.model.BookCover
 import io.legado.app.model.BookCover
 import io.legado.app.utils.*
 import io.legado.app.utils.*
+import splitties.init.appCtx
 import java.io.FileOutputStream
 import java.io.FileOutputStream
 
 
 class CoverConfigFragment : PreferenceFragment(),
 class CoverConfigFragment : PreferenceFragment(),
@@ -139,17 +140,21 @@ class CoverConfigFragment : PreferenceFragment(),
 
 
     private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
     private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
         readUri(uri) { fileDoc, inputStream ->
         readUri(uri) { fileDoc, inputStream ->
-            var file = requireContext().externalFiles
-            val suffix = fileDoc.name.substringAfterLast(".")
-            val fileName = uri.inputStream(requireContext())!!.use {
-                MD5Utils.md5Encode(it) + ".$suffix"
-            }
-            file = FileUtils.createFileIfNotExist(file, "covers", fileName)
-            FileOutputStream(file).use {
-                inputStream.copyTo(it)
+            kotlin.runCatching {
+                var file = requireContext().externalFiles
+                val suffix = fileDoc.name.substringAfterLast(".")
+                val fileName = uri.inputStream(requireContext()).getOrThrow().use {
+                    MD5Utils.md5Encode(it) + ".$suffix"
+                }
+                file = FileUtils.createFileIfNotExist(file, "covers", fileName)
+                FileOutputStream(file).use {
+                    inputStream.copyTo(it)
+                }
+                putPrefString(preferenceKey, file.absolutePath)
+                BookCover.upDefaultCover()
+            }.onFailure {
+                appCtx.toastOnUi(it.localizedMessage)
             }
             }
-            putPrefString(preferenceKey, file.absolutePath)
-            BookCover.upDefaultCover()
         }
         }
     }
     }
 
 

+ 15 - 10
app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt

@@ -30,6 +30,7 @@ import io.legado.app.lib.theme.primaryColor
 import io.legado.app.ui.widget.number.NumberPickerDialog
 import io.legado.app.ui.widget.number.NumberPickerDialog
 import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
 import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
 import io.legado.app.utils.*
 import io.legado.app.utils.*
+import splitties.init.appCtx
 import java.io.FileOutputStream
 import java.io.FileOutputStream
 
 
 
 
@@ -303,17 +304,21 @@ class ThemeConfigFragment : PreferenceFragment(),
 
 
     private fun setBgFromUri(uri: Uri, preferenceKey: String, success: () -> Unit) {
     private fun setBgFromUri(uri: Uri, preferenceKey: String, success: () -> Unit) {
         readUri(uri) { fileDoc, inputStream ->
         readUri(uri) { fileDoc, inputStream ->
-            var file = requireContext().externalFiles
-            val suffix = fileDoc.name.substringAfterLast(".")
-            val fileName = uri.inputStream(requireContext())!!.use {
-                MD5Utils.md5Encode(it) + ".$suffix"
-            }
-            file = FileUtils.createFileIfNotExist(file, preferenceKey, fileName)
-            FileOutputStream(file).use {
-                inputStream.copyTo(it)
+            kotlin.runCatching {
+                var file = requireContext().externalFiles
+                val suffix = fileDoc.name.substringAfterLast(".")
+                val fileName = uri.inputStream(requireContext()).getOrThrow().use {
+                    MD5Utils.md5Encode(it) + ".$suffix"
+                }
+                file = FileUtils.createFileIfNotExist(file, preferenceKey, fileName)
+                FileOutputStream(file).use {
+                    inputStream.copyTo(it)
+                }
+                putPrefString(preferenceKey, file.absolutePath)
+                success()
+            }.onFailure {
+                appCtx.toastOnUi(it.localizedMessage)
             }
             }
-            putPrefString(preferenceKey, file.absolutePath)
-            success()
         }
         }
     }
     }
 
 

+ 14 - 9
app/src/main/java/io/legado/app/ui/config/WelcomeConfigFragment.kt

@@ -13,6 +13,7 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.model.BookCover
 import io.legado.app.model.BookCover
 import io.legado.app.utils.*
 import io.legado.app.utils.*
+import splitties.init.appCtx
 import java.io.FileOutputStream
 import java.io.FileOutputStream
 
 
 class WelcomeConfigFragment : PreferenceFragment(),
 class WelcomeConfigFragment : PreferenceFragment(),
@@ -119,16 +120,20 @@ class WelcomeConfigFragment : PreferenceFragment(),
 
 
     private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
     private fun setCoverFromUri(preferenceKey: String, uri: Uri) {
         readUri(uri) { fileDoc, inputStream ->
         readUri(uri) { fileDoc, inputStream ->
-            var file = requireContext().externalFiles
-            val suffix = fileDoc.name.substringAfterLast(".")
-            val fileName = uri.inputStream(requireContext())!!.use {
-                MD5Utils.md5Encode(it) + ".$suffix"
-            }
-            file = FileUtils.createFileIfNotExist(file, "covers", fileName)
-            FileOutputStream(file).use {
-                inputStream.copyTo(it)
+            kotlin.runCatching {
+                var file = requireContext().externalFiles
+                val suffix = fileDoc.name.substringAfterLast(".")
+                val fileName = uri.inputStream(requireContext()).getOrThrow().use {
+                    MD5Utils.md5Encode(it) + ".$suffix"
+                }
+                file = FileUtils.createFileIfNotExist(file, "covers", fileName)
+                FileOutputStream(file).use {
+                    inputStream.copyTo(it)
+                }
+                putPrefString(preferenceKey, file.absolutePath)
+            }.onFailure {
+                appCtx.toastOnUi(it.localizedMessage)
             }
             }
-            putPrefString(preferenceKey, file.absolutePath)
         }
         }
     }
     }
 
 

+ 19 - 14
app/src/main/java/io/legado/app/utils/UriExtensions.kt

@@ -173,23 +173,28 @@ fun Uri.writeBytes(
     return false
     return false
 }
 }
 
 
-fun Uri.inputStream(context: Context): InputStream? {
+fun Uri.inputStream(context: Context): Result<InputStream> {
     val uri = this
     val uri = this
-    try {
-        if (isContentScheme()) {
-            val doc = DocumentFile.fromSingleUri(context, uri)
-            doc ?: throw NoStackTraceException("未获取到文件")
-            return context.contentResolver.openInputStream(uri)!!
-        } else {
-            RealPathUtil.getPath(context, uri)?.let { path ->
+    return kotlin.runCatching {
+        try {
+            if (isContentScheme()) {
+                DocumentFile.fromSingleUri(context, uri)
+                    ?: throw NoStackTraceException("未获取到文件")
+                return@runCatching context.contentResolver.openInputStream(uri)!!
+            } else {
+                val path = RealPathUtil.getPath(context, uri)
+                    ?: throw NoStackTraceException("未获取到文件")
                 val file = File(path)
                 val file = File(path)
-                return FileInputStream(file)
+                if (file.exists()) {
+                    return@runCatching FileInputStream(file)
+                } else {
+                    throw NoStackTraceException("文件不存在")
+                }
             }
             }
+        } catch (e: Exception) {
+            e.printOnDebug()
+            AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
+            throw e
         }
         }
-    } catch (e: Exception) {
-        e.printOnDebug()
-        context.toastOnUi("读取inputStream失败:${e.localizedMessage}")
-        AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
     }
     }
-    return null
 }
 }