Get permission to write to SD card on Android 6+

Asked

Viewed 11,327 times

0

I’m creating an app that reads and writes files on Android, it turns out I can’t get permission to record on the device’s external storage. After researching I saw that I need to call this screen to get permission, but I do not know what it calls there. Pedido de permissão em tempo de execução

Aparentemente um OpenFile padrão do Marshmallow

Selecionando o armazenamento externo (Cartão SD)

Permitendo acesso ao App para gravação no Cartão SD

These images I found on the web and I’ve also seen apps like Word or esFileExplorer asking.

So I’m asking for write and external reading permissions on my Mainactivity’s Oncreate this way:

if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        ActivityCompat.requestPermissions(this,
                        new String[]{
                                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.READ_EXTERNAL_STORAGE
                        }, 0);
    }
}

To read files from both Emulated/0/sdcard/ (internal storage) and /mnt/media_rw/C4B3_13EE/ (external storage (SD card installed on the device)) I can upload the file to my application

Now to write is a little more complicated, in Emulated/0/sdcard/ up to you, but in /mnt/media_rw/C4B3_13EE/ gives an Exception, see:

E/TAG: /mnt/media_rw/C4B3_13EE/Pasta Personal/Documents/Textosaída.txt: open failed: EACCES (Permission denied)

My code for writing is just below

FileOutputStream outputStream;
    File file = new File("/mnt/media_rw/C4B3_13EE/Pasta Pessoal/Documentos/TextoSaída.txt");
    try {
        outputStream = new FileOutputStream(file);
        outputStream.write(textView.getText().toString().getBytes());
        outputStream.close();
        Log.e("TAG", file.getAbsolutePath() + " Arquivo Criado");
    } catch (IOException e) {
        Log.e("TAG", file.getAbsolutePath() + " Arquivo NÃO Criado");
        Log.e("TAG", e.getMessage());
        e.printStackTrace();
}
MediaScannerConnection.scanFile(this,new String[] {file.getAbsolutePath()}, null, null);
  • You only need to ask for permission at runtime, use the lib Reactivepermissions de Max Cruz: https://github.com/MaxCruz/reactive_permissions.

  • This lib only asks for permissions. I’m asking for permissions. the problem is that it actually gives Permission denied

  • To be sure that the problem is the "runtime permissions" on the definitions -> applications choose your application and manually assign.

  • Done. The Storage switch is enabled

  • The error continues?

  • Yes. It was already enabled before. My application asks for runtime permissions correctly.

  • I will reopen the question. The problem has another cause. The folders in sdcard were created by your application?

  • 1

    Ok, it seems that I could find a way to record, using the Storage Access Framework, I will search a little more and test and if solve the problem I answer

Show 3 more comments

1 answer

1

Well, it was hard enough, but I did it. I found that in version 4.4 (Kitkat) android was introduced a SAF (Storage Access Structure), on the android website Veloper explain better and have the snippets I used to solve part of my problem, see:

  1. I was using the Intent ACTION_GET_CONTENT (which obtains a copy of the desired file), to get the file I wanted to edit, however google advises to use the ACTION_OPEN_DOCUMENT, if I want to have a persistent access (Create, in case of folder, edit, delete), even in SD card.

With this done, I appeared another challenge, when save the edited file, Windows notepad does not "see" the line breaks that we put on android. To solve this question I made this little code:

String texto = textView.getText().toString();
String separador = "\n";
String[] linhas = texto.split(separador);

With each line obtained at the time of writing I only modified a little the snippet of the section Editing a document, placing a foreach:

for (String linha : linhas)
    fileOutputStream.write((linha + "\r\n").getBytes());

So the native Windows notepad can read each line individually.

Note: If you make any changes to any file while the android device is connected in MTP mode, you should remove it (or switch to just loading) and re-connect it to the computer. Same procedure applies to Linux (at least on Ubuntu 16 I had to perform).

Sources:
https://developer.android.com/guide/topics/providers/document-provider.html?hl=pt-br https://stackoverflow.com/questions/11247253/extract-a-line-from-an-edittext

Browser other questions tagged

You are not signed in. Login or sign up in order to post.