当应用程序安装在SD卡而不是内部存储上时,下载管理器广播DownloadManager.ERROR_FILE_ERROR



我有一个应用程序,可以使用DownloadManager下载多个文件。在 SD 卡上安装应用程序会导致广播接收器接收带有DownloadManager.ERROR_FILE_ERRORinCOLUMN_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)
}
}
}

我用于下载的文件名使用冒号作为分隔符,但冒号在 FAT 文件系统上不是有效字符。将分隔符更改为连字符解决了问题。

最新更新