Não é possível criar o diretório no Android 10

10

Não consigo criar o diretório no android 10. Ele está funcionando em dispositivos até o Android Oreo.

Eu tentei duas maneiras de criar pastas.

Usando File.mkdir() :

   File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pastebin");
                    if (!f.isFile()) {
                        if (!(f.isDirectory())) {
                               success =  f.mkdir();
                        }

Aqui, a variável success é sempre falsa, o que significa que o diretório não é criado.

Usando Files.createDirectory() :

   File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pastebin");
                    if (!f.isFile()) {
                        if (!(f.isDirectory())) {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                try {
                                    Files.createDirectory(Paths.get(f.getAbsolutePath()));
                                } catch (IOException e) {
                                    e.printStackTrace();
                                    Toast.makeText(getApplicationContext(), R.string.unable_to_download, Toast.LENGTH_LONG).show();
                                }
                            } else {
                                f.mkdir();
                            }
                        }

o que causa essa exceção:

pzy64.pastebinpro W/System.err: java.nio.file.AccessDeniedException: /storage/emulated/0/Pastebin
pzy64.pastebinpro W/System.err:     at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:391)
pzy64.pastebinpro W/System.err:     at java.nio.file.Files.createDirectory(Files.java:674)

Eu implementei as permissões de tempo de execução e

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

estão todos prontos.

pz64_
fonte

Respostas:

27

Como foi divulgado pela primeira vez em março de 2019, você não tem mais acesso por padrão a locais arbitrários no armazenamento externo ou armazenamento removível no Android 10+. Isso inclui Environment.getExternalStorageDirectory()e outros métodos em Environment(por exemplo getExternalStoragePublicDirectory(),.

Para o Android 10, você pode adicionar android:requestLegacyExternalStorage="true"ao seu <application>elemento no manifesto. Isso leva você ao modelo de armazenamento herdado, e seu código de armazenamento externo existente funcionará. Porém, isso não funcionará no Android R e superior, portanto, essa é apenas uma correção de curto prazo.

Suas escolhas são:

  • Use métodos Context, como getExternalFilesDir(), para acessar diretórios em armazenamento externo nos quais seu aplicativo pode gravar. Você não precisa de permissões para usar esses diretórios no Android 4.4 ou superior. No entanto, os dados que você armazena são removidos quando o aplicativo é desinstalado.

  • Use o Storage Access Framework, como ACTION_OPEN_DOCUMENTe ACTION_CREATE_DOCUMENT.

  • Se o seu conteúdo for mídia, você pode usá-lo MediaStorepara colocá-la em locais de mídia padrão.

CommonsWare
fonte
1
você está dizendo que não há como criar meu próprio diretório no Android Q?
Xihuny 24/10/19
1
@ Xihuny: Você pode criar subdiretórios getExternalFilesDir()e locais semelhantes fornecidos por Context. Você não pode criar subdiretórios a partir das raízes do armazenamento externo ou removível diretamente, usando APIs do sistema de arquivos.
CommonsWare 24/10/19
1
Não quero fazer isso porque os arquivos serão removidos quando o usuário desinstalar o aplicativo.
Xihuny 25/10/19
1
@Xihuny: Em seguida, use o Storage Access Framework e permita que o usuário escolha onde, no dispositivo do usuário, coloca o conteúdo do usuário.
CommonsWare 25/10/19
1
Eu tentei, mas não consegui criar meu próprio diretório. Existe uma maneira de criar meu próprio diretório nomeado personalizado usando o SAF?
Xihuny 25/10/19
3

Para o Android 10, você pode adicionar

android:requestLegacyExternalStorage="true"

ao seu elemento no manifesto. Isso leva você ao modelo de armazenamento herdado, e seu código de armazenamento externo existente funcionará. Essa correção não funcionará no Android R e superior, portanto, essa é apenas uma correção de curto prazo.

Sujit Jamdade
fonte
1

Desde o Q beta 4, é possível desativar esse recurso:

visando a API 28 (ou inferior) usando o atributo de manifesto requestLegacyExternalStorage:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting Android Q. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>
Amit_android
fonte
-1

Isso funciona para mim e acho que é funcional no Android 10>

            ContentResolver resolver = getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/Folder Example");
            String path = String.valueOf(resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues));
            File folder = new File(path);
            boolean isCreada = folder.exists();
            if(!isCreada) {
                folder.mkdirs();
            }
JP711
fonte
Você está consultando um e File, portanto, precisará adicionar android:requestLegacyExternalStorage="true"ao segmentar o Android 10>. Nesse caso, você também pode continuar usando getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).
HB.
getExternalStoragePublicDirectory está obsoleto no nível 29 da API
JP711
Sim e? Como a documentação indica When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible, por isso, se você tiver android:requestLegacyExternalStorage="true"no seu manifesto, ainda poderá usá-lo.
HB.
"Sim e?" e, como a documentação declara, Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENTeu sou novo nisso, mas minha pergunta seria: minha proposta está errada ou por que o voto negativo? Não sei muito bem como isso funciona, é melhor continuar getExternalStoragePublicDirectory?
JP711
1
Você não precisa criar uma pasta. Quando você escreve Urina pasta, ela é criada automaticamente.
HB.