使用DownloadManager.setDestinationInExternalPublicDir创建自定义目录存储Firebase下载文件报错问题咨询
I've run into this exact issue before—here's what's going on and how to fix it:
The error pops up because DownloadManager.Request.setDestinationInExternalPublicDir() requires its first parameter to be one of Android's official standard directory constants (like Environment.DIRECTORY_DOWNLOADS or Environment.DIRECTORY_PICTURES). You can't pass a raw custom path like "/folder/innerFolder" directly here.
To save files to a custom folder, you need to manually create the folder first, then use setDestinationUri() to point the DownloadManager to your custom path. Here's the step-by-step solution:
1. Create Your Custom Folder
We'll make a subfolder inside a standard public directory (like Downloads) to stay compliant with Android's storage rules. For example, let's create a folder called FirebaseMedia/EventAssets inside the system Downloads directory:
// Define the custom folder path File customStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "FirebaseMedia/EventAssets" ); // Create the folder if it doesn't exist (creates parent folders automatically) if (!customStorageDir.exists()) { boolean folderCreated = customStorageDir.mkdirs(); if (!folderCreated) { Toast.makeText(SearchCase.this, "לא ניתן ליצור תי�рани אחסון", Toast.LENGTH_SHORT).show(); return; } }
2. Update the DownloadManager Request
Replace the problematic setDestinationInExternalPublicDir() call with setDestinationUri(), which lets you specify a full custom file path:
// Build the full path for the downloaded file File destinationFile = new File(customStorageDir, title); Uri destinationUri = Uri.fromFile(destinationFile); // Set the custom storage destination request.setDestinationUri(destinationUri);
3. Handle Permissions (Critical!)
- Android 9 (API 28) and below: Declare the
WRITE_EXTERNAL_STORAGEpermission in yourAndroidManifest.xmland request it at runtime from the user. - Android 10 (API 29) and above:
- Option 1: Add
android:requestLegacyExternalStorage="true"to your<application>tag inAndroidManifest.xml(works for API 29 only) - Option 2: Request the
MANAGE_EXTERNAL_STORAGEpermission (only use this if your app truly needs broad, unrestricted storage access)
- Option 1: Add
Full Modified Code Snippet
Here's how your updated onDataChange method will look:
@Override public void onDataChange(@NonNull DataSnapshot snapshot) { mStoredPictures = new ArrayList<>(); if (snapshot.exists()) { // Step 1: Create custom storage folder File customStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "FirebaseMedia/EventAssets" ); if (!customStorageDir.exists()) { boolean folderCreated = customStorageDir.mkdirs(); if (!folderCreated) { Toast.makeText(SearchCase.this, "לא ניתן ליצור תי�рани אחסון", Toast.LENGTH_SHORT).show(); return; } } for (DataSnapshot postSnapShot : snapshot.getChildren()) { StoredPicture storedPicture = postSnapShot.getValue(StoredPicture.class); mStoredPictures.add(storedPicture); String imageUrl = storedPicture.getmImageUrl(); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(imageUrl)); String title = URLUtil.guessFileName(imageUrl, null, null); request.setTitle(nameGet1 + "-" + idGet1); request.setDescription("----"); String cookie = CookieManager.getInstance().getCookie(imageUrl); request.addRequestHeader("cookie", cookie); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // Step 2: Set custom destination path File destinationFile = new File(customStorageDir, title); Uri destinationUri = Uri.fromFile(destinationFile); request.setDestinationUri(destinationUri); DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); downloadManager.enqueue(request); Toast.makeText(SearchCase.this, "מוריד תמונות/סרטונים...", Toast.LENGTH_SHORT).show(); } } }
After this change, your files will be saved to Internal Storage/Download/FirebaseMedia/EventAssets instead of the default Downloads folder, and you won't see that error anymore.
内容的提问来源于stack exchange,提问作者Maklonim

