Android APIv29 FileNotFoundException EACCES (Permiso denegado)

9

No puedo acceder al almacenamiento cuando compilo para targetSdkVersion v29.

Aquí está mi configuración de gradle:

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

TEN WRITE_EXTERNAL_STORAGEEN CUENTA que se otorga el permiso y la misma configuración funciona bien cuando se construye para targetSdkVersion 28.

Aquí está mi implementación:

        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 
        }

y aquí está la excepción:

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 alguien tenga una respuesta, ¿qué me estoy perdiendo aquí?

Actualizar:

Aquí es de donde baseFolderviene. Tenga en cuenta que getExternalStorageDirectoryes un método obsoleto.

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

Gracias

Dinu
fuente
Intente usar esta biblioteca para premisiones github.com/googlesamples/easypermissions
Ruben Meiring
Como ya mencioné, se otorgan los permisos necesarios para escribir almacenamiento externo y la misma configuración funciona al compilar con targetSdkVersion 28. ¡Esto no es un problema de permiso!
Dinu
Su premission adyacentes, de acuerdo con el error no se puede obtener a premsiion Acess el archivo / almacenamiento / emulado / 0 / Chirp Auto Tester / 2019_10_17 10: 44: 43.raw: ha fallado: EACCES (permiso denegado) , Si Android 10 uso almacenamiento con alcance
Ruben Meiring
¿Cómo explicas que funciona cuando se construye para targetSdkVersion 28entonces? Según el error, sí, es un problema relacionado con los permisos, pero no porque no se otorguen los permisos.
Dinu
2
No tiene acceso al sistema de archivos a ubicaciones arbitrarias en almacenamiento externo y extraíble. La limitación de almacenamiento extraíble se agregó en Android 4.4. La limitación de almacenamiento externo se agregó en Android 10.
CommonsWare

Respuestas:

15

A partir de Android 11, el permiso de almacenamiento se revoca y los desarrolladores tendrían que considerar formas alternativas de acceder al almacenamiento que necesitan a través de SAF o Media Store . Por el momento, puede seguir usando lo que está usando agregando lo siguiente en su manifiesto dentro de las etiquetas de la aplicación:

android:requestLegacyExternalStorage="true"

Es posible que desee considerar cambiar su minSDK a 19 y usarlo getExternalFilesDir()para obtener una ruta que no requiera ningún permiso.

Nikos Hidalgo
fuente
Todavía no funciona pero definitivamente estoy mirando en la dirección correcta, ahora estoy obteniendo ENOENT (No such file or directory), sin embargo, el directorio definitivamente existe. getExternalFilesDir()suena sobre la decisión correcta para solucionar el problema.
Dinu
1
Solo una actualización rápida, terminé usando getExternalFilesDir()por ahora.
Dinu
2

Cuando su aplicación se dirige a Build.VERSION_CODES.Q, la ruta devuelta por este método ya no es directamente accesible para las aplicaciones.

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

Para más detalles visite Docs

Praveen
fuente
-1

necesita solicitar permiso Manifest.permission.WRITE_EXTERNAL_STORAGE nuevamente.

antes de 9.0, solo solicita Manifest.permission.READ_EXTERNAL_STORAGE y también obtendrá Manifest.permission.WRITE_EXTERNAL_STORAGE, pero comience con 9.0, solo puede obtener un permiso que haya solicitado nuevamente.

Perdona mi pobre inglés.

Gerry_Liang
fuente
Este no es un problema de solicitud de permiso, lo mencioné un par de veces, se otorgan los permisos WRITE y READ EXTERNAL_STORAGE. Consulte la respuesta de Nikos para obtener detalles sobre por qué aún no puede acceder al almacenamiento externo, incluso si se otorgan permisos. Y no te preocupes por tu inglés, es genial.
Dinu
/ ** * 申请 相册 权限 , 去 打开 相册 * / public void galleryPicture () {if (ContextCompat.checkSelfPermission (mContext, Manifest.permission.READ_EXTERNAL_STORAGE)! = PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions (mContext, new String (mContext, new String) {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE); } else {openPic (mContext, CODE_GALLERY_REQUEST); }}
Gerry_Liang