androidandroid-download-managerandroid-securityexception

DownloadManager throws SecurityException on Android Q


Download Manager gets the error below on Android 10 devices. The target version is 29.

I added android:requestLegacyExternalStorage="true" tag to the Manifest, but it didn't work.

java.lang.SecurityException: Unsupported path /storage/emulated/0/Contents/Awesome App.apk

Here is the code

public static void startDownload(Context context, String url, String token, String subPath) {

    DownloadManager.Request request;
    DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
    Uri uri = Uri.parse(url);  // A url to download a file

    try {
        request = new DownloadManager.Request(uri);
        request.addRequestHeader("X-Auth-Token", token);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
        return;
    }

    request.setVisibleInDownloadsUi(true);
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

    try {
        File downloadFileDir = new File(Environment
                .getExternalStorageDirectory().getAbsolutePath() + "/Contents");

        if (downloadFileDir != null) {
            if (!downloadFileDir.exists()) {
                downloadFileDir.mkdirs();
            }

            File file = new File(downloadFileDir.getAbsolutePath() + File.separator + subPath);
            // subPath is name of the file to download. e.g. Awesome App.apk
            if (file.exists()) {
                file.delete();
            }

            Uri localUri = Uri.fromFile(file);
            request.setDestinationUri(localUri);
            if (localUri != null) {
                request.setMimeType(MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(localUri.toString())));
            }
        }
    } catch (SecurityException e) {
        e.printStackTrace();
    }

    request.setTitle(subPath);
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

    try {
        manager.enqueue(request);
    } catch (SecurityException e) {
        e.printStackTrace();
        //Got exception here
    }
}

Solution

  • /storage/emulated/0/Contents/Awesome App.apk

    In an Android 10 device the DownloadManager will not download to your own directories on external storage.

    You need to use one of the already available public directories like Document, Download, DCIM, Music and so on.

    So you can let download to

    /storage/emulated/0/Music/Contents/Awesome App.apk
    

    No need to create your subdirectory yourself as the download manager will do it.

    You app does not need any permission to let the download manager execute its task.