From 861994e80446a0591e7e2a9ef2c6f0cfdab7ec96 Mon Sep 17 00:00:00 2001 From: tom5079 Date: Wed, 2 Sep 2020 12:15:37 +0900 Subject: [PATCH] Fixed crash when download folder is changed --- app/build.gradle | 2 +- .../pupil/adapters/GalleryBlockAdapter.kt | 6 +- .../quaver/pupil/services/DownloadService.kt | 9 ++- .../java/xyz/quaver/pupil/ui/MainActivity.kt | 56 ++++++++++++++++--- .../xyz/quaver/pupil/ui/ReaderActivity.kt | 15 ++--- .../pupil/ui/dialog/DownloadLocationDialog.kt | 4 +- .../pupil/ui/fragment/SettingsFragment.kt | 1 + .../pupil/util/download/DownloadWorker.kt | 7 --- .../xyz/quaver/pupil/util/downloader/Cache.kt | 5 +- ...oadFolderManager.kt => DownloadManager.kt} | 50 ++++++++++------- 10 files changed, 96 insertions(+), 59 deletions(-) rename app/src/main/java/xyz/quaver/pupil/util/downloader/{DownloadFolderManager.kt => DownloadManager.kt} (69%) diff --git a/app/build.gradle b/app/build.gradle index 594ef7fb..9309a624 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,7 @@ android { minSdkVersion 16 targetSdkVersion 29 versionCode 57 - versionName "4.21-hotfix1" + versionName "5.0-alpha1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt index 2636430b..dc41940c 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt @@ -52,7 +52,7 @@ import xyz.quaver.pupil.favorites import xyz.quaver.pupil.types.Tag import xyz.quaver.pupil.util.Preferences import xyz.quaver.pupil.util.downloader.Cache -import xyz.quaver.pupil.util.downloader.DownloadFolderManager +import xyz.quaver.pupil.util.downloader.DownloadManager import xyz.quaver.pupil.util.wordCapitalize import java.util.* import kotlin.collections.ArrayList @@ -94,7 +94,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri } if (progress == max) { - val downloadManager = DownloadFolderManager.getInstance(context) + val downloadManager = DownloadManager.getInstance(context) if (completeFlag.get(galleryID, false)) { with(view.galleryblock_progress_complete) { @@ -357,7 +357,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri mItemManger.closeAllExcept(layout) holder.view.galleryblock_download.text = - if (DownloadFolderManager.getInstance(holder.view.context).isDownloading(galleryID)) + if (DownloadManager.getInstance(holder.view.context).isDownloading(galleryID)) holder.view.context.getString(android.R.string.cancel) else holder.view.context.getString(R.string.main_download) diff --git a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt index aebc9a67..af2f498e 100644 --- a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt +++ b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt @@ -23,7 +23,6 @@ import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent -import android.util.Log import android.util.SparseArray import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -43,7 +42,7 @@ import xyz.quaver.pupil.client import xyz.quaver.pupil.interceptors import xyz.quaver.pupil.ui.ReaderActivity import xyz.quaver.pupil.util.downloader.Cache -import xyz.quaver.pupil.util.downloader.DownloadFolderManager +import xyz.quaver.pupil.util.downloader.DownloadManager import xyz.quaver.pupil.util.ellipsize import xyz.quaver.pupil.util.normalizeID import xyz.quaver.pupil.util.requestBuilders @@ -121,7 +120,7 @@ class DownloadService : Service() { .setProgress(max, progress, false) .setContentText("$progress/$max") - if (DownloadFolderManager.getInstance(this).getDownloadFolder(galleryID) != null) + if (DownloadManager.getInstance(this).getDownloadFolder(galleryID) != null) notification.let { notificationManager.notify(galleryID, it.build()) } else notificationManager.cancel(galleryID) @@ -226,7 +225,7 @@ class DownloadService : Service() { notify(galleryID) if (isCompleted(galleryID)) { - if (DownloadFolderManager.getInstance(this@DownloadService) + if (DownloadManager.getInstance(this@DownloadService) .getDownloadFolder(galleryID) != null) Cache.getInstance(this@DownloadService, galleryID).moveToDownload() @@ -279,7 +278,7 @@ class DownloadService : Service() { fun delete(galleryID: Int, startId: Int? = null) = CoroutineScope(Dispatchers.IO).launch { cancel(galleryID) - DownloadFolderManager.getInstance(this@DownloadService).deleteDownloadFolder(galleryID) + DownloadManager.getInstance(this@DownloadService).deleteDownloadFolder(galleryID) Cache.delete(galleryID) startId?.let { stopSelf(it) } diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt index bb80d3d0..1f9143cb 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -23,6 +23,7 @@ import android.app.Activity import android.content.Intent import android.graphics.drawable.Animatable import android.net.Uri +import android.os.Build import android.os.Bundle import android.text.* import android.text.style.AlignmentSpan @@ -50,13 +51,16 @@ import com.google.android.material.snackbar.Snackbar import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main_content.* +import kotlinx.android.synthetic.main.settings_activity.* import kotlinx.coroutines.* import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import net.rdrei.android.dirchooser.DirectoryChooserActivity import xyz.quaver.hitomi.doSearch import xyz.quaver.hitomi.getGalleryIDsFromNozomi import xyz.quaver.hitomi.getSuggestionsForQuery +import xyz.quaver.io.FileX import xyz.quaver.pupil.R import xyz.quaver.pupil.adapters.GalleryBlockAdapter import xyz.quaver.pupil.favorites @@ -64,10 +68,11 @@ import xyz.quaver.pupil.histories import xyz.quaver.pupil.services.DownloadService import xyz.quaver.pupil.types.TagSuggestion import xyz.quaver.pupil.types.Tags +import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog import xyz.quaver.pupil.ui.dialog.GalleryDialog import xyz.quaver.pupil.util.* import xyz.quaver.pupil.util.downloader.Cache -import xyz.quaver.pupil.util.downloader.DownloadFolderManager +import xyz.quaver.pupil.util.downloader.DownloadManager import java.io.File import java.util.* import kotlin.collections.ArrayList @@ -110,7 +115,6 @@ class MainActivity : AppCompatActivity() { private var loadingJob: Job? = null private var currentPage = 0 - private lateinit var downloadFolderManager: DownloadFolderManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -146,7 +150,9 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) - downloadFolderManager = DownloadFolderManager.getInstance(this) + if (Preferences["download_folder", ""].isEmpty()) + DownloadLocationDialog(this).show() + checkUpdate(this) initView() @@ -225,7 +231,7 @@ class MainActivity : AppCompatActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when(requestCode) { - R.id.request_settings -> { + R.id.request_settings.normalizeID() -> { runOnUiThread { cancelFetch() clearGalleries() @@ -233,10 +239,44 @@ class MainActivity : AppCompatActivity() { loadBlocks() } } - R.id.request_lock -> { + R.id.request_lock.normalizeID() -> { if (resultCode != Activity.RESULT_OK) finish() } + R.id.request_download_folder.normalizeID() -> { + if (resultCode == Activity.RESULT_OK) { + data?.data?.also { uri -> + val takeFlags: Int = + intent.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + contentResolver.takePersistableUriPermission(uri, takeFlags) + + if (FileX(this, uri).canWrite()) + Preferences["download_folder"] = uri.toString() + else + Snackbar.make( + settings, + R.string.settings_download_folder_not_writable, + Snackbar.LENGTH_LONG + ).show() + } + } + } + R.id.request_download_folder_old.normalizeID() -> { + if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { + val directory = data?.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)!! + + if (!File(directory).canWrite()) + Snackbar.make( + settings, + R.string.settings_download_folder_not_writable, + Snackbar.LENGTH_LONG + ).show() + else + Preferences["download_folder"] = File(directory).canonicalPath + } + } } } @@ -443,11 +483,11 @@ class MainActivity : AppCompatActivity() { if (Preferences["cache_disable"]) Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show() else { - if (downloadFolderManager.isDownloading(galleryID)) { //download in progress + if (DownloadManager.getInstance(context).isDownloading(galleryID)) { //download in progress DownloadService.cancel(this@MainActivity, galleryID) } else { - downloadFolderManager.addDownloadFolder(galleryID) + DownloadManager.getInstance(context).addDownloadFolder(galleryID) DownloadService.download(this@MainActivity, galleryID) } } @@ -1027,7 +1067,7 @@ class MainActivity : AppCompatActivity() { } } Mode.DOWNLOAD -> { - val downloads = downloadFolderManager.downloadFolderMap.keys.toList() + val downloads = DownloadManager.getInstance(this@MainActivity).downloadFolderMap.keys.toList() when { query.isEmpty() -> downloads.also { diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt index 50147dcd..7605a394 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt @@ -18,7 +18,6 @@ package xyz.quaver.pupil.ui -import android.app.DownloadManager import android.content.ComponentName import android.content.Intent import android.content.ServiceConnection @@ -26,7 +25,6 @@ import android.graphics.drawable.Animatable import android.graphics.drawable.Drawable import android.os.Bundle import android.os.IBinder -import android.util.Log import android.view.* import android.widget.Toast import androidx.appcompat.app.AlertDialog @@ -38,7 +36,6 @@ import androidx.recyclerview.widget.PagerSnapHelper import androidx.recyclerview.widget.RecyclerView import androidx.vectordrawable.graphics.drawable.Animatable2Compat import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat -import com.bumptech.glide.Glide import com.google.android.material.snackbar.Snackbar import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.android.synthetic.main.activity_reader.* @@ -55,7 +52,7 @@ import xyz.quaver.pupil.histories import xyz.quaver.pupil.services.DownloadService import xyz.quaver.pupil.util.Preferences import xyz.quaver.pupil.util.downloader.Cache -import xyz.quaver.pupil.util.downloader.DownloadFolderManager +import xyz.quaver.pupil.util.downloader.DownloadManager import java.util.* import kotlin.concurrent.schedule import kotlin.concurrent.timer @@ -83,12 +80,10 @@ class ReaderActivity : AppCompatActivity() { private val conn = object: ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { downloader = (service as DownloadService.Binder).service - Log.i("PUPILD", "CON") } override fun onServiceDisconnected(name: ComponentName?) { downloader = null - Log.i("PUPILD", "DIS") } } @@ -243,9 +238,9 @@ class ReaderActivity : AppCompatActivity() { timer.cancel() (reader_recyclerview?.adapter as? ReaderAdapter)?.timer?.cancel() - if (!DownloadFolderManager.getInstance(this).isDownloading(galleryID)) { + if (!DownloadManager.getInstance(this).isDownloading(galleryID)) { downloader?.cancel(galleryID) - DownloadFolderManager.getInstance(this).deleteDownloadFolder(galleryID) + DownloadManager.getInstance(this).deleteDownloadFolder(galleryID) } if (downloader != null) @@ -373,13 +368,13 @@ class ReaderActivity : AppCompatActivity() { } with(reader_fab_download) { - animateDownloadFAB(DownloadFolderManager.getInstance(this@ReaderActivity).getDownloadFolder(galleryID) != null) //If download in progress, animate button + animateDownloadFAB(DownloadManager.getInstance(this@ReaderActivity).getDownloadFolder(galleryID) != null) //If download in progress, animate button setOnClickListener { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false)) Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show() else { - val downloadManager = DownloadFolderManager.getInstance(this@ReaderActivity) + val downloadManager = DownloadManager.getInstance(this@ReaderActivity) if (downloadManager.isDownloading(galleryID)) { downloadManager.deleteDownloadFolder(galleryID) diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialog.kt index 8c05da09..e9569a0f 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialog.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialog.kt @@ -35,7 +35,7 @@ import net.rdrei.android.dirchooser.DirectoryChooserActivity import net.rdrei.android.dirchooser.DirectoryChooserConfig import xyz.quaver.pupil.R import xyz.quaver.pupil.util.* -import xyz.quaver.pupil.util.downloader.DownloadFolderManager +import xyz.quaver.pupil.util.downloader.DownloadManager import java.io.File @SuppressLint("InflateParams") @@ -115,7 +115,7 @@ class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) { }) externalFilesDirs.indexOfFirst { - it.canonicalPath == DownloadFolderManager.getInstance(context).downloadFolder.canonicalPath + it.canonicalPath == DownloadManager.getInstance(context).downloadFolder.canonicalPath }.let { index -> if (index < 0) buttons.last().first.isChecked = true diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt index 7624f2cf..32662680 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt @@ -39,6 +39,7 @@ import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog import xyz.quaver.pupil.ui.dialog.MirrorDialog import xyz.quaver.pupil.ui.dialog.ProxyDialog import xyz.quaver.pupil.util.* +import xyz.quaver.pupil.util.downloader.DownloadManager import java.io.BufferedReader import java.io.File import java.io.InputStreamReader diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt index 2420e32b..8ff8582a 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt @@ -275,13 +275,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont if (e.message?.contains("cancel", true) != false) return - Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})") - FirebaseCrashlytics.getInstance().apply { - log("FAIL ${call.request().tag()} (${e.message})") - setCustomKey("POS", "FAIL") - recordException(e) - } - cancel(galleryID) queue.add(galleryID) } diff --git a/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt b/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt index 47314d30..c94859d7 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt @@ -20,7 +20,6 @@ package xyz.quaver.pupil.util.downloader import android.content.Context import android.content.ContextWrapper -import android.util.Log import android.util.SparseArray import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -78,7 +77,7 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW }.getOrNull() ?: Metadata() val downloadFolder: FileX? - get() = DownloadFolderManager.getInstance(this).getDownloadFolder(galleryID) + get() = DownloadManager.getInstance(this).getDownloadFolder(galleryID) val cacheFolder: FileX get() = FileX(this, cacheDir, "imageCache/$galleryID").also { @@ -101,7 +100,6 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW kotlin.runCatching { if (!file.exists()) { - Log.i("PUPILD", "$file") file.createNewFile() } file.writeText(Json.encodeToString(metadata)) @@ -202,7 +200,6 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW @Suppress("BlockingMethodInNonBlockingContext") fun moveToDownload() = CoroutineScope(Dispatchers.IO).launch { val downloadFolder = downloadFolder ?: return@launch - Log.i("PUPILD", "MOVING $galleryID") metadata.imageList?.forEach { imageName -> imageName ?: return@forEach diff --git a/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadFolderManager.kt b/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt similarity index 69% rename from app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadFolderManager.kt rename to app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt index 65c7eba9..6cf27f85 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadFolderManager.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt @@ -32,14 +32,14 @@ import xyz.quaver.pupil.services.DownloadService import xyz.quaver.pupil.util.Preferences import xyz.quaver.pupil.util.formatDownloadFolder -class DownloadFolderManager private constructor(context: Context) : ContextWrapper(context) { +class DownloadManager private constructor(context: Context) : ContextWrapper(context) { companion object { - @Volatile private var instance: DownloadFolderManager? = null + @Volatile private var instance: DownloadManager? = null fun getInstance(context: Context) = instance ?: synchronized(this) { - instance ?: DownloadFolderManager(context).also { instance = it } + instance ?: DownloadManager(context).also { instance = it } } } @@ -55,22 +55,34 @@ class DownloadFolderManager private constructor(context: Context) : ContextWrapp } }.invoke() - val downloadFolderMap: MutableMap = { - val file = downloadFolder.getChild(".download") + private var prevDownloadFolder: FileX? = null + private var downloadFolderMapInstance: MutableMap? = null + val downloadFolderMap: MutableMap + @Synchronized + get() { + if (prevDownloadFolder != downloadFolder) { + prevDownloadFolder = downloadFolder + downloadFolderMapInstance = { + val file = downloadFolder.getChild(".download") - val data = if (file.exists()) - kotlin.runCatching { - file.readText()?.let { Json.decodeFromString>(it) } - }.onFailure { file.delete() }.getOrNull() - else - null + val data = if (file.exists()) + kotlin.runCatching { + file.readText()?.let { Json.decodeFromString>(it) } + }.onFailure { file.delete() }.getOrNull() + else + null + + data ?: { + file.createNewFile() + file.writeText("{}") + mutableMapOf() + }.invoke() + }.invoke() + } + + return downloadFolderMapInstance!! + } - data ?: { - file.createNewFile() - file.writeText("{}") - mutableMapOf() - }.invoke() - }.invoke() @Synchronized fun isDownloading(galleryID: Int): Boolean { @@ -90,7 +102,7 @@ class DownloadFolderManager private constructor(context: Context) : ContextWrapp return val name = runBlocking { - Cache.getInstance(this@DownloadFolderManager, galleryID).getGalleryBlock() + Cache.getInstance(this@DownloadManager, galleryID).getGalleryBlock() }?.formatDownloadFolder() ?: return val folder = downloadFolder.getChild(name) @@ -98,7 +110,7 @@ class DownloadFolderManager private constructor(context: Context) : ContextWrapp if (!folder.exists()) folder.mkdirs() - downloadFolderMap[galleryID] = name + downloadFolderMap[galleryID] = folder.name downloadFolder.getChild(".download").writeText(Json.encodeToString(downloadFolderMap)) }