Android 12中DownloadManager下载至自定义公共目录失败求助
Android 12中DownloadManager下载到自定义公共目录报错解决方法
问题背景
在Android 12系统中,尝试将文件通过指定URL下载到自定义公共目录/storage/emulated/0/Download/demo,应用启动时已成功创建该目录,但调用DownloadManager时触发IllegalStateException,提示Not one of standard directories: /demo,下载无法完成。
错误原因
调用setDestinationInExternalPublicDir()方法时,第一个参数传入了"/demo",但该方法要求第一个参数必须是Android系统定义的标准公共目录常量(比如Environment.DIRECTORY_DOWNLOADS),而非自定义子目录路径。传入的"/demo"不属于系统标准目录,因此触发异常。
解决方法
1. 正确设置下载路径
使用setDestinationInExternalPublicDir()时,第一个参数传入系统标准目录(如Environment.DIRECTORY_DOWNLOADS),第二个参数传入子目录+文件名的组合,DownloadManager会自动处理子目录的创建(手动提前创建也不影响)。
2. 修正后的代码
public int downloadUrl() { String url = "https://www.whatsappimages.in/wp-content/uploads/2021/07/Top-HD-sad-quotes-for-whatsapp-status-in-hindi-Pics-Images-Download-Free.gif"; // 定义目标文件路径:Download/demo/test.jpg String subPath = "demo/test.jpg"; DownloadManager mgr = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse(url); DownloadManager.Request request = new DownloadManager.Request(uri); request.setAllowedNetworkTypes( DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(false) .setTitle("Demo") .setDescription("Something useful. No, really.") // 第一个参数传系统标准目录,第二个参数传子路径 .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, subPath); mgr.enqueue(request); return 0; }
3. 权限说明
- Android 10及以上:无需申请
WRITE_EXTERNAL_STORAGE权限,DownloadManager会自动处理文件写入权限。 - Android 9及以下:需要在Manifest中添加
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>,并动态申请权限。
创建类似Downloads、DCIM的公共目录
Android系统的公共目录(如Downloads、DCIM、Pictures等)是系统预定义的,应用无法直接创建与系统同级的公共目录,但可以在这些标准目录下创建自定义子目录:
- 使用系统API创建子目录
// 在Downloads目录下创建demo子目录 File demoDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "demo"); if (!demoDir.exists()) { boolean isCreated = demoDir.mkdirs(); if (isCreated) { Log.d(TAG, "子目录创建成功:" + demoDir.getAbsolutePath()); } }
- 让目录被系统媒体扫描识别
如果希望自定义子目录中的文件能被系统相册、文件管理器识别,可以发送媒体扫描广播:
// 扫描指定目录 MediaScannerConnection.scanFile(this, new String[]{demoDir.getAbsolutePath()}, null, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { Log.d(TAG, "目录已被系统扫描:" + path); } });
内容的提问来源于stack exchange,提问作者Teapot
相关产品推荐
相关产品推荐

