将应用程序安装在SD卡而非内部存储器上时,DownloadManager会广播DownloadManager.ERROR_FILE_ERROR

时间:2018-08-30 20:33:18

标签: android kotlin android-download-manager android-external-storage

我有一个使用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)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

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