Android APIv29 FileNotFoundException EACCES (permissão negada)

9

Não consigo acessar o armazenamento ao criar para o targetSdkVersion v29.

Aqui está a minha configuração gradle:

    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    ...
        minSdkVersion 15
        targetSdkVersion 29

OBSERVAÇÃO: a WRITE_EXTERNAL_STORAGEpermissão é concedida e a mesma configuração funciona bem ao construir para targetSdkVersion 28.

Aqui está a minha implementação:

        val outputFolder = File(baseFolder + File.separator + "Output Folder")
        if (!outputFolder.exists()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Files.createDirectory(outputFolder.toPath()) //This allways returns false with targetSdkVersion 29
            } else {
                if (!outputFolder.mkdirs()) {
                    Log.e("SaveRaw", "Unable to create folder for audio recording")
                }
            }
        }

        outputFile = File("$baseFolder/Output Folder/$filename")
        try {
            fileOutputStream = FileOutputStream(outputFile)
        } catch (e: FileNotFoundException) {
            e.printStackTrace() // allways throwing exception here, even if Output Folder exists 
        }

e aqui está a exceção:

W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Chirp Auto Tester/2019_10_17 10:44:43.raw: open failed: EACCES (Permission denied)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:496)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)

Espero que alguém tenha uma resposta, o que estou perdendo aqui?

Atualizar:

Aqui é de onde baseFoldervem. Observe que esse getExternalStorageDirectoryé um método obsoleto.

        val baseFolder: String = if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Environment.getExternalStorageDirectory().absolutePath
        } else {
            context.filesDir.absolutePath
        }

obrigado

Dinu
fonte
Tente usar esta biblioteca para ver as premissas github.com/googlesamples/easypermissions
Ruben Meiring
Como já mencionei, as permissões necessárias para a gravação de armazenamento externo são concedidas e a mesma instalação funciona ao criar com targetSdkVersion 28. Este não é um problema de permissão!
Dinu
Sua premissa adjacente, de acordo com o erro, não é possível acessar o arquivo / storage / emulated / 0 / Chirp Auto Tester / 2019_10_17 10: 44: 43.raw: open falhou: EACCES (permissão negada) , se o Android 10 usar escopo de armazenamento
Ruben Meiring
Como você explica que está funcionando quando está construindo para targetSdkVersion 28então? De acordo com o erro, sim, é um problema relacionado à permissão, mas não porque as permissões não são concedidas.
Dinu
2
Você não tem acesso do sistema de arquivos a locais arbitrários no armazenamento externo e removível. A limitação de armazenamento removível foi adicionada no Android 4.4. A limitação de armazenamento externo foi adicionada no Android 10.
CommonsWare

Respostas:

15

A partir do Android 11, a permissão de armazenamento está sendo revogada e os desenvolvedores precisam considerar maneiras alternativas de acessar o armazenamento de que precisam através do SAF ou do Media Store . Por enquanto, você pode continuar usando o que está usando adicionando o seguinte no manifesto nas tags do aplicativo:

android:requestLegacyExternalStorage="true"

Você pode considerar alterar seu minSDK para 19 e usá getExternalFilesDir()-lo para obter um caminho que não requer nenhuma permissão.

Nikos Hidalgo
fonte
Ainda não está funcionando, mas definitivamente olhando na direção certa, agora estou conseguindo ENOENT (No such file or directory), no entanto, o diretório definitivamente existe. getExternalFilesDir()soa sobre a decisão certa de corrigir o problema.
Dinu
1
Apenas uma atualização rápida, acabei usando getExternalFilesDir()por enquanto.
Dinu
2

Quando seu aplicativo é direcionado para Build.VERSION_CODES.Q, o caminho retornado desse método não fica mais diretamente acessível aos aplicativos.

    val path = getExternalFilesDir(Environment.DIRECTORY_PICTURES.toString() + 
    File.separator + "Output Folder")
    val file = File(getExternalFilesDir(null), "filename.jpg")

Para mais detalhes, visite o Documentos

Praveen
fonte
-1

você precisa solicitar permissão Manifest.permission.WRITE_EXTERNAL_STORAGE novamente.

antes da 9.0, você solicita apenas Manifest.permission.READ_EXTERNAL_STORAGE e também recebe Manifest.permission.WRITE_EXTERNAL_STORAGE, mas, a partir da 9.0, você pode obter apenas uma permissão que você requereu.

Perdoe meu inglês pobre.

Gerry_Liang
fonte
Este não é um problema de permissão de solicitação, mencionei isso algumas vezes, ambas as permissões WRITE e READ EXTERNAL_STORAGE são concedidas. Consulte a resposta do Nikos para obter detalhes sobre por que você ainda não pode acessar o armazenamento externo, mesmo que as permissões sejam concedidas. E não se preocupe com o seu inglês, é ótimo.
Dinu
/ ** * 申请 相册 相册 * / public void galleryPicture () {if (ContextCompat.checkSelfPermission (mContext, Manifest.permission.READ_EXTERNAL_STORAGE)! = PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions (mContext) {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE); } else {openPic (mContext, CODE_GALLERY_REQUEST); }}
Gerry_Liang 23/10/19