diff --git a/app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt b/app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt index e2a4cfdf9..d3665bfe7 100644 --- a/app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/BaseAssociationViewModel.kt @@ -1,19 +1,29 @@ package io.legado.app.ui.association import android.app.Application +import android.net.Uri import androidx.lifecycle.MutableLiveData import io.legado.app.base.BaseViewModel +import io.legado.app.utils.contains +import io.legado.app.utils.inputStream +import io.legado.app.utils.readText abstract class BaseAssociationViewModel(application: Application) : BaseViewModel(application) { val successLive = MutableLiveData>() val errorLive = MutableLiveData() + fun importJson(uri: Uri) { + when { + uri.inputStream(context).contains("bookSourceUrl") -> + successLive.postValue(Pair("bookSource", uri.toString())) + else -> importJson(uri.readText(context)) + } + } + fun importJson(json: String) { //暂时根据文件内容判断属于什么 when { - json.contains("bookSourceUrl") -> - successLive.postValue(Pair("bookSource", json)) json.contains("sourceUrl") -> successLive.postValue(Pair("rssSource", json)) json.contains("pattern") -> diff --git a/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt b/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt index f5b0bd562..3ad302d5d 100644 --- a/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt @@ -7,7 +7,9 @@ import androidx.lifecycle.MutableLiveData import io.legado.app.constant.AppLog import io.legado.app.constant.AppPattern.bookFileRegex import io.legado.app.exception.NoStackTraceException +import io.legado.app.help.IntentData import io.legado.app.model.localBook.LocalBook +import io.legado.app.utils.inputStream import io.legado.app.utils.isJson import io.legado.app.utils.printOnDebug import java.io.File @@ -23,24 +25,19 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo fun dispatchIndent(uri: Uri) { execute { lateinit var fileName: String - lateinit var content: String - lateinit var fileStream: InputStream //如果是普通的url,需要根据返回的内容判断是什么 if (uri.scheme == "file" || uri.scheme == "content") { - if (uri.scheme == "file") { + fileName = if (uri.scheme == "file") { val file = File(uri.path.toString()) - fileStream = file.inputStream() - fileName = file.name + file.name } else { val file = DocumentFile.fromSingleUri(context, uri) if (file?.exists() != true) throw NoStackTraceException("文件不存在") - fileStream = context.contentResolver.openInputStream(uri)!! - fileName = file.name ?: "" + file.name ?: "" } kotlin.runCatching { - content = fileStream.reader(Charsets.UTF_8).use { it.readText() } - if (content.isJson()) { - importJson(content) + if (uri.inputStream(context).isJson()) { + importJson(uri) return@execute } }.onFailure { @@ -58,6 +55,7 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo }.onError { it.printOnDebug() errorLive.postValue(it.localizedMessage) + AppLog.put("无法打开文件\n${it.localizedMessage}", it) } } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt index 248a78276..89268f2e4 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt @@ -1,6 +1,7 @@ package io.legado.app.ui.association import android.app.Application +import android.net.Uri import androidx.lifecycle.MutableLiveData import com.jayway.jsonpath.JsonPath import io.legado.app.R @@ -109,6 +110,12 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) { mText.isAbsUrl() -> { importSourceUrl(mText) } + mText.isUri() -> { + val uri = Uri.parse(mText) + uri.inputStream(context)?.let { + allSources.addAll(BookSource.fromJsonArray(it).getOrThrow()) + } + } else -> throw NoStackTraceException(context.getString(R.string.wrong_format)) } }.onError { diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 69d127f87..29a60b2b7 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -21,6 +21,7 @@ import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ActivityBookSourceBinding import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.help.DirectLinkUpload +import io.legado.app.help.IntentData import io.legado.app.help.config.LocalConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor @@ -77,11 +78,7 @@ class BookSourceActivity : VMBaseActivity - try { - showDialogFragment(ImportBookSourceDialog(uri.readText(this))) - } catch (e: Exception) { - toastOnUi("readTextError:${e.localizedMessage}") - } + showDialogFragment(ImportBookSourceDialog(uri.toString())) } } private val exportDir = registerForActivityResult(HandleFileContract()) { diff --git a/app/src/main/java/io/legado/app/utils/InputStreamExtensions.kt b/app/src/main/java/io/legado/app/utils/InputStreamExtensions.kt new file mode 100644 index 000000000..e36814f8e --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/InputStreamExtensions.kt @@ -0,0 +1,25 @@ +package io.legado.app.utils + +import java.io.InputStream +import java.util.* + +fun InputStream?.isJson(): Boolean { + this ?: return false + this.use { + val byteArray = ByteArray(128) + it.read(byteArray) + val a = String(byteArray).trim() + it.skip(it.available() - 128L) + it.read(byteArray) + val b = String(byteArray).trim() + return (a + b).isJson() + } +} + +fun InputStream?.contains(str: String): Boolean { + this ?: return false + this.use { + val scanner = Scanner(it) + return scanner.findWithinHorizon(str, 0) != null + } +} diff --git a/app/src/main/java/io/legado/app/utils/StringExtensions.kt b/app/src/main/java/io/legado/app/utils/StringExtensions.kt index f52095a18..1ea3f0b39 100644 --- a/app/src/main/java/io/legado/app/utils/StringExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/StringExtensions.kt @@ -24,6 +24,11 @@ fun String.parseToUri(): Uri { } } +fun String?.isUri(): Boolean { + this ?: return false + return this.startsWith("file://", true) || isContentScheme() +} + fun String?.isAbsUrl() = this?.let { it.startsWith("http://", true) || it.startsWith("https://", true) diff --git a/app/src/main/java/io/legado/app/utils/UriExtensions.kt b/app/src/main/java/io/legado/app/utils/UriExtensions.kt index 97e25e403..db2d62f79 100644 --- a/app/src/main/java/io/legado/app/utils/UriExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/UriExtensions.kt @@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.Fragment import io.legado.app.R +import io.legado.app.constant.AppLog import io.legado.app.exception.NoStackTraceException import io.legado.app.lib.permission.Permissions import io.legado.app.lib.permission.PermissionsCompat @@ -153,4 +154,25 @@ fun Uri.writeBytes( return true } return false +} + +fun Uri.inputStream(context: Context): InputStream? { + 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 -> + val file = File(path) + return FileInputStream(file) + } + } + } catch (e: Exception) { + e.printOnDebug() + context.toastOnUi("读取inputStream失败:${e.localizedMessage}") + AppLog.put("读取inputStream失败:${e.localizedMessage}", e) + } + return null } \ No newline at end of file