У меня есть приложение, которое загружает несколько файлов, используя DownloadManager
. При установке приложения на SD-карту приемник вещания получает намерение с DownloadManager.ERROR_FILE_ERROR
в COLUMN_REASON
.
При установке во внутреннем хранилище приложение работает правильно. Установка атрибута манифеста android:installLocation="internalOnly"
не вынуждает пользователя, испытывающего проблему, к внутренней установке.
Возвращаемое значение Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
зависит от места установки.
На внутренней памяти это выглядит так, как ожидалось: /storage/emulated/0/Download
На внешнем хранилище это не: /storage/<random_looking_series_of_numbers_and_letters>/Download
Цель - переместить файлы из каталога загрузок в каталог файлов приложения. Позже эти файлы будут скопированы из их местоположений в каталоге файлов в более конкретные места по мере необходимости, но останутся в каталоге файлов. Однако при попытке второй копии создается исключение, что исходный файл не существует.
fun generateDownloadRequest(url: String, destination: String): DownloadManager.Request {
val uri = Uri.parse(url)
val request = DownloadManager.Request(uri)
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
request.setTitle(destination)
request.setDescription("Downloading ${destination.substringAfterLast(":")}.")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, destination)
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdirs()
return request
}
class DownloadBroadcastReceiver : BroadcastReceiver() {
private var doOnReceived: (Long) -> Unit = {}
fun setDoOnReceived(action: (Long) -> Unit) {
doOnReceived = action
}
override fun onReceive(context: Context?, intent: Intent?) {
val downloadedId = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
downloadedId?.let {
if (it == -1L) return@let
doOnReceived(it)
}
}
}