Saltar al contenido

Android Kotlin: ¿Obtiene una FileNotFoundException con el nombre de archivo elegido en el selector de archivos?

Solución:

No recibió una ruta de archivo, recibió una Uri. Tienes que usar Uri API basadas como ContentResolver.openInputStream() para acceder a los contenidos en ese Uri ya que Android no otorga su aplicación directamente File acceso al archivo subyacente (también podría transmitirse desde Google Drive o descargarse directamente de Internet sin que su aplicación sepa que esto está sucediendo):

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    // Selected a file to load
    if ((requestCode == 111) && (resultCode == RESULT_OK)) {
        val selectedFilename = data?.data //The uri with the location of the file
        if (selectedFilename != null) {
            contentResolver.openInputStream(selectedFilename)?.bufferedReader()?.forEachLine {
                val toast = Toast.makeText(applicationContext, it, Toast.LENGTH_SHORT)
                toast.show()
            }
        } else {
            val msg = "Null filename data received!"
            val toast = Toast.makeText(applicationContext, msg, Toast.LENGTH_LONG)
            toast.show()
        }
    }
}

Aquí podemos asumir que obtenemos contenido del formato adecuado al pasar el tipo de mime adecuado a nuestra solicitud (ya que no es necesario que un archivo de texto termine exactamente en el .txt extensión como parte de su camino):

val intent = Intent()
    .setType("text/*")
    .setAction(Intent.ACTION_GET_CONTENT)

startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)

Lo que hará que cualquier archivo que no sea de texto no pueda seleccionarse automáticamente.

No puede abrir un archivo Java en un ÙRI convertido a una cadena, la sección “ruta” del URI no tiene relación con la ubicación de un archivo físico.

Utilizar una contentResolver para obtener un Java FileDescriptor para abrir el archivo.

val parcelFileDescriptor: ParcelFileDescriptor =
            contentResolver.openFileDescriptor(uri, "r")
    val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor

Este método es compatible con Android 10, donde las rutas de archivo de los directorios privados que no son de la aplicación no se pueden utilizar.

https://developer.android.com/training/data-storage/shared/documents-files

Si obtiene “msf: xxx” en URI, use la siguiente solución donde he creado un archivo temporal en el directorio de caché de la aplicación y eliminé el mismo archivo después de completar mi tarea:

if (id != null && id.startsWith("msf:")) {
                    final File file = new File(mContext.getCacheDir(), Constant.TEMP_FILE + Objects.requireNonNull(mContext.getContentResolver().getType(imageUri)).split("https://foroayuda.es/")[1]);
                    try (final InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); OutputStream output = new FileOutputStream(file)) {
                        final byte[] buffer = new byte[4 * 1024]; // or other buffer size
                        int read;

                        while ((read = inputStream.read(buffer)) != -1) {
                            output.write(buffer, 0, read);
                        }

                        output.flush();
                        return file;
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    return null;
                }

He solucionado este problema y funciona al 100% para msf. 🙂

También elimine el archivo temporal después de completar su trabajo:

private void deleteTempFile() {
        final File[] files = requireContext().getCacheDir().listFiles();
        if (files != null) {
            for (final File file : files) {
                if (file.getName().contains(Constant.TEMP_FILE)) {
                    file.delete();
                }
            }
        }
    }

Aquí el valor de TEMP_FILE es “temp”.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *