I am trying to download a file using the DownloadManager
class.
public void downloadFile(View view) {
String urlString = "your_url_here";
try {
// Get file name from the url
String fileName = urlString.substring(urlString.lastIndexOf("/") + 1);
// Create Download Request object
DownloadManager.Request request = new DownloadManager.Request(Uri.parse((urlString)));
// Display download progress and status message in notification bar
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// Set description to display in notification
request.setDescription("Download " + fileName + " from " + urlString);
// Set title
request.setTitle("DownloadManager");
// Set destination location for the downloaded file
request.setDestinationUri(Uri.parse("file://" + Environment.getExternalStorageDirectory() + "/" + fileName));
// Download the file if the Download manager is ready
did = dManager.enqueue(request);
} catch (Exception e) {
}
}
// BroadcastReceiver to receive intent broadcast by DownloadManager
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Query q = new Query();
q.setFilterById(did);
Cursor cursor = dManager.query(q);
if (cursor.moveToFirst()) {
String message = "";
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
message = "Download successful";
} else if (status == DownloadManager.STATUS_FAILED) {
message = "Download failed";
}
tvMessage.setText(message);
}
}
};
I am using dexter
to obtain permissions
Dexter.withActivity(this)
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
I also have both in my manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
But I still get this error while trying to download files (ONLY on Oreo). It works on android 7
No permission to write to /storage/emulated/0/download: Neither user 10205 nor current process has android.permission.WRITE_EXTERNAL_STORAGE.
You only need internet permission.
<uses-permission android:name="android.permission.INTERNET" />
and
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
if you want to store and read this downloaded file.
The internet permission is required:
<uses-permission android:name="android.permission.INTERNET" />
You can use getExternalFilesDir
if you want to save file without any storage permission.
As stated in the documentation:
getExternalFilesDir
Added in API level 8
File getExternalFilesDir (String type)
Returns the absolute path to the directory on the primary
shared/external storage device where the application can place
persistent files it owns. These files are internal to the
applications, and not typically visible to the user as media.
This is like getFilesDir()
in that these files will be deleted when the
application is uninstalled, however there are some important
differences: Shared storage may not always be available, since
removable media can be ejected by the user. Media state can be checked
using getExternalStorageState(File)
. There is no security enforced
with these files. For example, any application holding
WRITE_EXTERNAL_STORAGE
can write to these files.
If a shared storage device is emulated (as determined by isExternalStorageEmulated(File)
),
it's contents are backed by a private user data partition, which means
there is little benefit to storing data here instead of the private
directories returned by getFilesDir()
, etc.
Starting in KITKAT, no permissions are required to read or write to the returned path; it's always accessible to the calling app. This only applies to paths generated for package name of the calling application.
To access paths
belonging to other packages, WRITE_EXTERNAL_STORAGE
and/or
READ_EXTERNAL_STORAGE
are required. On devices with multiple users (as
described by UserManager
), each user has their own isolated shared
storage. Applications only have access to the shared storage for the
user they're running as.
The returned path may change over time if
different shared storage media is inserted, so only relative paths
should be persisted.
https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)
This link may be useful:
Save files on device storage
You are getting this error because your app is running in Android 6.0(API level 23). From API level >= 23 you will need to check for the permission in run time. Your code is just fine for below level 23. So please check first if your user has given the permission to use the storage:
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.e("Permission error","You have permission");
return true;
}
If not then prompt the request:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Total things looks like this:
public boolean haveStoragePermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.e("Permission error","You have permission");
return true;
} else {
Log.e("Permission error","You have asked for permission");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //you dont need to worry about these stuff below api level 23
Log.e("Permission error","You already have the permission");
return true;
}
}
And receive the result by callback:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
//you have the permission now.
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(myurl));
request.setTitle("Vertretungsplan");
request.setDescription("wird heruntergeladen");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
String filename = URLUtil.guessFileName(myurl, null, MimeTypeMap.getFileExtensionFromUrl(myurl));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
DownloadManager manager = (DownloadManager) c.getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
}