首页 > 解决方案 > 下载管理器不适用于 Android 10 (Q)

问题描述

很长一段时间以来,我一直在努力解决这个问题......我正在更新一个使用 DownloadManger 执行简单任务的应用程序,例如将文件下载到外部存储公共目录,即:

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)

从 Android api 19-28 开始一切正常。它在 API 29 (Q/10) 上进行测试时会出现问题。Android 实现了范围存储,因此弃用了 getExternalStoragePublicDirectory... 因此,我需要找出一个兼容的解决方案来支持 API 19-29。我不能使用内部应用程序存储,因为 DownloadManager 会抛出 SecurityException。Androids 文档声明我可以使用 DownloadManager.Request setDestinationUri,它甚至提到了我可以使用的 Android Context.getExternalFilesDir(String)Q。但是,当我这样做时,路径仍然是模拟路径:

/storage/emulated/0/Android/data/com.my.package.name/files/Download/myFile.xml

我从下载管理器收到一个回调,说下载已完成(使用正确的 ID),但是我无法从保存它的区域获取下载。我检查文件是否存在并返回 false:

new File("/storage/emulated/0/Android/data/com.my.package.name/files/Download/myFile.xml").exists();

任何帮助表示赞赏

为上下文添加代码。所以设置下载管理器

    private void startDownload() {
        IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        registerReceiver(downloadReceiver, filter);

        String remoteURL= getString(R.string.remote_url);

        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(remoteUrl));
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setTitle(getString(R.string.download_title));
        request.setDescription(getString(R.string.download_description));
        request.setDestinationUri(Uri.fromFile(new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "myFile.xml")));

        DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        mainDownloadID= manager.enqueue(request);
    }

检查文件是否存在:

new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "myFile.xml").exists(); //this returns false in the onReceive (and download IDs match)

标签: androiddownloadandroid-download-managerandroid-10.0scoped-storage

解决方案


是的,它的范围存储,但即使您可以使用下载管理器在 Q+ 中下载文件,也无需这样做android:requestLegacyExternalStorage="true"

我正在这样做。

  1. 显现
  • -->
  1. 下载管理器

     val fileName =
         Constants.FILE_NAME + Date().time
    
     val downloadUri = Uri.parse(media.url)
     val request = DownloadManager.Request(
         downloadUri
     )
     request.setAllowedNetworkTypes(
         DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE
     )
         .setAllowedOverRoaming(true).setTitle("Some name")
         .setDescription("Downloading file")
         .setDestinationInExternalPublicDir(
             Environment.DIRECTORY_DOWNLOADS, File.separator + FOLDER + File.separator + fileName
         )
    
    
     Toast.makeText(
         context,
         "Download successfully to ${downloadUri?.path}",
         Toast.LENGTH_LONG
     ).show()
    
     downloadManager.enqueue(request)
    

因此,它会在 Q 下方询问写权限,但在 Q 和 Q+ 中,它会在不询问 /Download/folder 目录中的权限的情况下下载。


推荐阅读