Fix downloads not working when no storage location set

This commit is contained in:
Niels van Velzen
2026-06-18 16:41:03 +02:00
committed by Niels van Velzen
parent 122c1801d8
commit f90b3e543b
7 changed files with 33 additions and 39 deletions
-9
View File
@@ -19,15 +19,6 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage"
tools:node="remove" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<queries>
@@ -9,33 +9,33 @@ import androidx.documentfile.provider.DocumentFile
import org.jellyfin.mobile.R
import org.jellyfin.mobile.data.entity.DownloadFiles
import org.jellyfin.mobile.downloads.DownloadStatus
import java.io.File
import timber.log.Timber
class StorageManager(
private val context: Context,
private val appPreferences: AppPreferences
) {
private val defaultStorageLocation
get() = Environment.getExternalStorageDirectory().absolutePath + File.separator + context.getString(R.string.app_name_short)
val defaultStorageLocation
get() = Environment.getExternalStorageDirectory().resolve(context.getString(R.string.app_name_short)).toUri()
init {
ensureNoMedia(getStorageLocation())
fun getStorageLocation() = appPreferences.storageLocation?.toUri()?.let {
DocumentFile.fromTreeUri(context, it)
}
fun getStorageLocation(): DocumentFile = appPreferences.storageLocation?.toUri()?.let {
DocumentFile.fromTreeUri(context, it)
} ?: DocumentFile.fromFile(File(defaultStorageLocation))
fun changeStorageLocation(location: Uri): Boolean {
if (appPreferences.storageLocation?.toUri() == location) return true
fun changeStorageLocation(location: Uri) {
if (appPreferences.storageLocation?.toUri() == location) return
return runCatching {
context.contentResolver.takePersistableUriPermission(
location,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
)
val documentFile = DocumentFile.fromTreeUri(context, location) ?: error("Invalid location $location")
context.contentResolver.takePersistableUriPermission(
documentFile.uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
)
ensureNoMedia(documentFile)
appPreferences.storageLocation = documentFile.uri.toString()
appPreferences.storageLocation = location.toString()
getStorageLocation()?.let(::ensureNoMedia)
}.onFailure { err ->
Timber.e(err, "Failed to change storage location to $location")
}.isFailure
}
fun verify(download: DownloadFiles): Boolean {
@@ -110,7 +110,7 @@ class DownloadManager(
if (deleteFiles) {
val storageLocation = storageManager.getStorageLocation()
storageLocation.findFile(download.path)?.delete()
storageLocation?.findFile(download.path)?.delete()
}
downloadDao.delete(id)
@@ -119,8 +119,8 @@ class DownloadQueue(
private suspend fun prepareFiles(api: ApiClient, downloadWithFiles: DownloadFiles): List<QueuedFile> {
val storageLocation = storageManager.getStorageLocation()
val itemLocation = storageLocation.findFile(downloadWithFiles.download.path)
?: storageLocation.createDirectory(downloadWithFiles.download.path)
val itemLocation = storageLocation?.findFile(downloadWithFiles.download.path)
?: storageLocation?.createDirectory(downloadWithFiles.download.path)
?: error("Unable to find or create folder ${downloadWithFiles.download.path}")
return buildList {
@@ -56,7 +56,7 @@ class DownloadsViewModel : ViewModel(), KoinComponent {
viewModelScope.launch {
val fileUri = withContext(Dispatchers.IO) {
val storageLocation = storageManager.getStorageLocation()
val itemLocation = storageLocation.findFile(download.path)
val itemLocation = storageLocation?.findFile(download.path)
if (itemLocation != null && itemLocation.isDirectory) {
val filename = download.item.path?.replace(Regex("^.*[\\\\/]"), "")
if (filename != null) itemLocation.findFile(filename)?.uri else null
@@ -42,11 +42,11 @@ class SettingsFragment : Fragment(), BackPressInterceptor {
private val storageLocationPicker = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
if (uri != null) {
storageManager.changeStorageLocation(uri)
val changed = storageManager.changeStorageLocation(uri)
// Update preference
if (::downloadLocationPreference.isInitialized) {
downloadLocationPreference.summary = storageManager.getStorageLocation().name
if (changed && ::downloadLocationPreference.isInitialized) {
downloadLocationPreference.summary = storageManager.getStorageLocation()?.name
downloadLocationPreference.requestRebindAndHighlight()
}
}
@@ -281,10 +281,10 @@ class SettingsFragment : Fragment(), BackPressInterceptor {
val location = storageManager.getStorageLocation()
titleRes = R.string.pref_download_location
summary = location.name
summary = location?.name ?: getString(R.string.menu_item_none)
onClick {
storageLocationPicker.launch(location.uri)
storageLocationPicker.launch(location?.uri ?: storageManager.defaultStorageLocation)
false
}
}
@@ -102,11 +102,14 @@ suspend fun MainActivity.requestDownload(itemIds: Collection<UUID>) {
}
}
if (permissionResult) {
val server = mainViewModel.serverState.value.server ?: return
val user = mainViewModel.userState.value.user ?: return
downloadManager.enqueueItems(server, user, itemIds)
// Automatically use a default download location
if (appPreferences.storageLocation == null) {
}
val server = mainViewModel.serverState.value.server ?: return
val user = mainViewModel.userState.value.user ?: return
downloadManager.enqueueItems(server, user, itemIds)
}
fun Activity.isAutoRotateOn() = Settings.System.getInt(contentResolver, ACCELEROMETER_ROTATION, 0) == 1