Android SD Card Write Permission using SAF (Storage Access Framework)
G

1

24

After a lot of findings about how to write(and rename) a file in SD Card (android 5 and above), I think the new SAF provided by android will be required to take permission from user to write SD card file.

I have seen in this File Manger Application ES File Explorer that initially it takes read and write permission the following way as shown in pictures.

enter image description here

Picture 2

After selecting sd card, the write permission is granted.

So in the same way I tried to use SAF, but failed in renaming a file. My code:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rename = (Button) findViewById(R.id.rename);

    startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), 42);
}

@Override
public void onActivityResult(int requestCode,int resultCode,Intent resultData) {
    if (resultCode != RESULT_OK)
        return;
    Uri treeUri = resultData.getData();
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
    grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}

public void renameclick(View v) {
    File ff = new File("/storage/sdcard1/try1.jpg");
    try {
        ff.createNewFile();
    } catch (Exception e) {
        Log.d("error", "creating");
        e.printStackTrace();
    }
}

Still after running the code I get EAacces permission denied.

Gloriagloriana answered 26/4, 2016 at 10:46 Comment(0)
G
31

Letting the user choose the "SD card" or even the "Internal storage" SAF root give your application access to the corresponding storage, but only through the SAF API, not directly via the filesystem. For example you code could be translated into something like :

public void writeFile(DocumentFile pickedDir) {
    try {
        DocumentFile file = pickedDir.createFile("image/jpeg", "try2.jpg");
        OutputStream out = getContentResolver().openOutputStream(file.getUri());
        try {

            // write the image content

        } finally {
            out.close();
        }

    } catch (IOException e) {
        throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
    }
}

In recent version of Android, accessing data outside your application using java.io.File is almost completely deprecated.

Goodrich answered 26/4, 2016 at 12:56 Comment(5)
But then whenever i need to create or rename a file, SAF picker will openGloriagloriana
Once you have the tree URI, you can do anything you want with the files and directories it includes. You don't need to ask the user each time if 1) You use takePersistableUriPermission() and 2) You store the URI somewhere, so that you can retrieve it on application startupGoodrich
How could we have access to subdirectories of pickedDir while createFile only gets MimeType and name as the arguments. How could we convert java.io.file kind path to a DocumentFile?Abyssal
@Abyssal you can do something like that: DocumentFile pickedTree = DocumentFile.fromFile(App.getContext(), uriTree); for (DocumentFile file : pickedTree.listFiles()) { if (file.isDirectory()) file.createFile(mimeType, fileName); }Uncommercial
How to write to a file which is present in some sub directory in SD Card.Gujarat

© 2022 - 2025 — McMap. All rights reserved.