I am on Android 11. I just want to be able to create a file in /storage/emulated/0/Download
directory on my phone. So, this is the public Download folder that I need to create a file on.
I don't need access to read/modify/delete other files in /storage/emulated/0/Download
. i just want my app to be able to create and replace a file of its own at /storage/emulated/0/Download
. Thats it!
Question:
- Do I need to go by the Storage Access Framework for this?
- Do I need any special permission for this?
- Or is it possible get access to
/storage/emulated/0/Documents
without going through the hassle of Android SAF?
My app is able to create a file at /storage/emulated/0/Download
using Android 10 but it fails to do that since Android 11.
My use case is very simple. I just want to create a file at /storage/emulated/0/Download
and keep appending more data to the file by replacing it with a new one from time to time.
Running the following code on Android 11 fails for me:
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file = new File(path, "Somefile.txt");
String location = file.getAbsolutePath();
try {
file.createNewFile();
byte[] data1 = {1,1,0,0};
OutputStream fo = new FileOutputStream(file);
fo.write(data1);
fo.close();
Log.i(TAG, "The file is created at " location);
} catch (IOException e) {
Log.e(TAG, "Exception creating file");
return location;
}
CodePudding user response:
Do I need to go by the Storage Access Framework for this?
No.
Do I need any special permission for this?
No, though you will need WRITE_EXTERNAL_STORAGE
for older devices.
Or is it possible get access to /storage/emulated/0/Documents without going through the hassle of Android SAF?
Environment.getExternalStoragePublicDirectory()
is being undeprecated, so it is safe to use that to access Environment.DIRECTORY_DOWNLOADS
. That should give you the same access that you have with MediaStore
:
You can create files there
You can read and write your own files1 there
You have no access to other apps' files there
1 For the purposes of this bullet, "your own" refers to your current app installation — if the user uninstalls and reinstalls your app, files from the old installation of your app are no longer considered to be "your own".
So, for example, this activity works just fine without any permissions in a targetSdkVersion 31
project:
package com.commonsware.downloadtest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writeToDownloads();
}
private void writeToDownloads() {
try {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File target = new File(dir, "test.txt");
PrintWriter out = new PrintWriter(new FileWriter(target));
out.println("hello, world!");
out.flush();
out.close();
} catch (Exception e) {
Log.e("DownloadTest", "Exception writing to Downloads/", e);
}
}
}
Now, this code sucks, in that it does not handle older devices, does the I/O on the main application thread, etc. However, it writes data to the designated file, on a Samsung A50 running Android 11.
Note that this will give an exception if the file already exists. So, for example, I thought that this example did not work, until I realized that I already had test.txt
in Downloads/
from some experiment that I did a month ago. Once I deleted that file, the sample worked fine.