How to Download File Using DownloadManager in API 29 or Android Q?

3 min read 06-10-2024
How to Download File Using DownloadManager in API 29 or Android Q?


Downloading Files in Android Q (API 29) with DownloadManager: A Comprehensive Guide

Downloading files is a common task in Android applications. In Android Q (API 29) and later, Google introduced significant changes to the way DownloadManager works. This article will guide you through the process of using DownloadManager to download files in a secure and efficient manner, adhering to the new guidelines.

The Problem:

Android Q introduced stricter security measures for file downloads. Traditional approaches using DownloadManager in older Android versions may no longer be effective, resulting in errors and potential security vulnerabilities.

Rephrased:

You can't download files in your Android app the same way you used to. Google made things more secure, and now you need to update your code to follow their new rules.

Scenario and Original Code (API 28 and Earlier):

Let's imagine you want to download a PDF file from a URL. In previous Android versions (API 28 and earlier), you might have used this code:

DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "my_file.pdf");
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadManager.enqueue(request);

Understanding the Changes in API 29:

In Android Q (API 29), the following changes have been implemented:

  • Foreground Service: To initiate a download, your app needs to run in a foreground service. This ensures transparency for users and allows for proper system management of downloads.
  • Scoped Storage: File access is restricted to app-specific directories. You can no longer directly access the external storage (e.g., Environment.DIRECTORY_DOWNLOADS).

Updated Code for API 29 and Later:

Here's how you can implement file downloads in API 29 using DownloadManager with the necessary changes:

// 1. Create a foreground service
// Start a foreground service, providing a notification to the user
// ... (implementation of foreground service)

// 2. Prepare the DownloadManager.Request
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));

// 3. Set Destination (using content URI)
request.setDestinationUri(getContentResolver().insert(
    MediaStore.Downloads.EXTERNAL_CONTENT_URI,
    new ContentValues(
        "title", "my_file.pdf" // Set file name
        // Add other optional attributes like MIME type, etc.
    )
));

// 4. Add Additional Properties
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 
request.setAllowedOverRoaming(false);

// 5. Enqueue the Download
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadManager.enqueue(request);

// 6. Monitor Download Progress (Optional)
long downloadId = downloadManager.enqueue(request); // Get the download ID
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);

Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
    // Get download status (e.g., DownloadManager.STATUS_SUCCESSFUL, STATUS_FAILED)
    int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
    // Handle download progress, errors, and completion
}
cursor.close();

Explanation:

  1. Foreground Service: Ensure your download operation runs within a foreground service. This provides transparency and proper management for the user.
  2. Request Preparation: The DownloadManager.Request object sets up the download parameters.
  3. Destination with Content URI: You must use MediaStore.Downloads.EXTERNAL_CONTENT_URI to specify the download destination. This ensures proper file management and avoids security issues.
  4. Optional Properties: Set additional properties like allowed network types, notification visibility, and roaming restrictions.
  5. Enqueuing the Download: Use DownloadManager.enqueue to start the download process.
  6. Monitoring Download Progress: (Optional) Retrieve the download ID and use DownloadManager.Query to monitor download progress, status, and handle completion or errors.

Additional Tips and Considerations:

  • Permissions: Ensure you have the necessary permissions to access external storage.
  • Notification Design: Provide clear and informative download notifications to the user.
  • Error Handling: Implement robust error handling to manage download failures and inform the user appropriately.
  • Download Management: Use DownloadManager's features like remove(downloadId) to control the download process.

Conclusion:

By understanding and adapting your code to the new requirements of Android Q and later, you can ensure secure and efficient file downloads in your Android applications. Using DownloadManager with the correct techniques provides a reliable and user-friendly experience for your users.

References: