Aprenda a implementar la biblioteca Storage Chooser en Android para crear fácilmente un selector de archivos / carpetas.

Cómo crear un selector de archivos/carpetas con un selector de almacenamiento en Android +4.4 usando la libreria Storage Chooser

¿Quiere implementar un selector de archivos/carpetas para su aplicación de Android? Seguramente no desea crear uno usted mismo, sino que le gustaría confiar en una biblioteca de terceros para esto. Aunque hay muchas bibliotecas que le permiten implementar dicha función, Storage Chooser es sin duda una opción bastante agradable si desea dar a sus usuarios la opción de elegir, desde qué almacenamiento de su dispositivo le gustaría elegir un archivo. /directorio. Storage Chooser es un selector de directorio y biblioteca de selector de archivos bonito y simple para dispositivos 4.4+ (Kitkat o más nuevos). Hay demasiados selectores de almacenamiento, pero este es demasiado material. Fácil de implementar y no requiere mucho de su valioso tiempo para configurar todas las otras cosas necesarias que todo desarrollador busca, como:

  • guardar ruta a sharedPreference
  • evento cuando se selecciona la ruta y actuar sobre esa ruta
  • y mucho más.

También hay algunas características realmente agradables que pensé que serían útiles:

  • Muestra una descripción general rápida de los almacenamientos presentes y su memoria disponible antes de elegir para que los usuarios sepan qué almacenamiento elegir.
  • puede elegir entre diseños planos y elegantes.
  • Vista de carpeta de creación en línea (no es otro cuadro de diálogo para manejar)
  • Localización completa. Quiero decir, literalmente, todas las cadenas se pueden localizar en el idioma que desee.
  • Umbral de memoria: una restricción o un brindis que muestra cuando la memoria del usuario es menor que la memoria de operaciones definida.
  • y pronto se añadirán más.

En este artículo, te mostraremos cómo implementar este Selector de almacenamiento / Selector de archivos / Selector de carpetas fácilmente en su aplicación de Android.

1. Agregar biblioteca como dependencia

Para instalar esta biblioteca en su proyecto, agrega el repositorio JitPack a su proyecto y agregue la dependencia en su archivo build.gradle de esta manera y sincronice su proyecto:

android {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

dependencies {
    implementation 'com.github.codekidX:storage-chooser:2.0.4.4'
}

Para obtener más información sobre esta biblioteca, visite el repositorio oficial en Github aquí.

2. Migrar a AndroidX

Si tienes dependencias de Maven que no se hayan migrado al espacio de nombres de AndroidX, el sistema de compilación de Android Studio también migra esas dependencias cuando configuras las siguientes dos  marcas true en tu archivo gradle.propertiesDeberá agregar las siguientes propiedades al archivo gradle.properties y sincronizar su proyecto:

android.useAndroidX=true
android.enableJetifier=true

3. Uso del selector de almacenamiento

Después de instalar la biblioteca, solo necesitarás crear una instancia de la clase StorageChooser.Builder y personalizarla según tus necesidades:

Selector de archivos

El siguiente código inicializa un Selector de almacenamiento que le permite elegir desde dónde desea seleccionar un archivo en su dispositivo:

// 1. Inicializar diálogo
final StorageChooser chooser = new StorageChooser.Builder()
    // Especificar el contexto del diálogo
    .withActivity(MainActivity.this)
    .withFragmentManager(getFragmentManager())
    .withMemoryBar(true)
    .allowCustomPath(true)
    // Defina el modo como el SELECTOR DE ARCHIVO
    .setType(StorageChooser.FILE_PICKER)
    .build();

// 2. ¡Maneje lo que debería suceder cuando el usuario selecciona el directorio!
chooser.setOnSelectListener(new StorageChooser.OnSelectListener() {
    @Override
    public void onSelect(String path) {
        // p.ej /storage/emulated/0/Documents/file.txt
        Log.i(path);
    }
});

// 3. ¡Muestre el selector de archivos siempre que lo necesite!
chooser.show();

El selector de archivos admite la selección múltiple sin ningún código adicional, el usuario solo tendrá que seleccionar más tiempo el primer elemento y listo.

Selector de carpetas/directorios

El siguiente código inicializa un Selector de almacenamiento que le permite elegir desde dónde desea seleccionar un directorio / carpeta en su dispositivo:

// 1. Inicializar diálogo
final StorageChooser chooser = new StorageChooser.Builder()
    // Specify context of the dialog
    .withActivity(MainActivity.this)
    .withFragmentManager(getFragmentManager())
    .withMemoryBar(true)
    .allowCustomPath(true)
    // Defina el modo como el CARPETA / ELEGIDOR DE DIRECTORIO
    .setType(StorageChooser.DIRECTORY_CHOOSER)
    .build();

// 2. ¡Maneje lo que debería suceder cuando el usuario selecciona el directorio!
chooser.setOnSelectListener(new StorageChooser.OnSelectListener() {
    @Override
    public void onSelect(String path) {
        // e.g /storage/emulated/0/Documents
        Log.i(path);
    }
});

// 3.¡Muestre el selector de archivos siempre que lo necesite!
chooser.show();

Para obtener información detallada sobre más opciones de la biblioteca, no olvide consultar la documentación en el repositorio oficial de Github . No olvide que necesitará los permisos READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE otorgados en su aplicación.

4. Ejemplos completos

Nuestro ejemplo incluirá la gestión de los permisos, específicamente los permisos READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGEde Android. Si no solicitas los permisos, verás la siguiente excepción a través de un Toast en su aplicación: El almacenamiento que ha elegido no es accesible. Básicamente causado por la falta de permisos en su aplicación, por eso incluiremos un ejemplo de cómo solicitar los permisos en Android 6+. También deberá agregar el siguiente atributo:

android:configChanges="orientation|screenSize"

A la actividad en la que desea implementar el Selector de almacenamiento, por ejemplo en el archivo AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ourcodeworld.sandboxkitkat44">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Habiendo dicho eso, mostremos los ejemplos completos para cada caso:

A. Ejemplo de selector de archivos

En este ejemplo tendremos una actividad principal, cuya maquetación en el activity_main.xmlarchivo tendrá el siguiente contenido:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button_filepicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Pick a file" />
</LinearLayout>

Y el código de la actividad principal será el siguiente:

package com.yourcompany.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.codekidlabs.storagechooser.StorageChooser;

public class MainActivity extends AppCompatActivity {

    public static final int FILEPICKER_PERMISSIONS = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button filepickerBtn = findViewById(R.id.button_filepicker);
        filepickerBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            //On click function
            public void onClick(View view) {
                String[] PERMISSIONS = {
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                };

                if(hasPermissions(MainActivity.this, PERMISSIONS)){
                    ShowFilepicker();
                }else{
                    ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS, FILEPICKER_PERMISSIONS);
                }
            }
        });
    }

    /**
     * Method that displays the filepicker of the StorageChooser.
     */
    public void ShowFilepicker(){
        // 1. Initialize dialog
        final StorageChooser chooser = new StorageChooser.Builder()
            .withActivity(MainActivity.this)
            .withFragmentManager(getFragmentManager())
            .withMemoryBar(true)
            .allowCustomPath(true)
            .setType(StorageChooser.FILE_PICKER)
            .build();

        // 2. Retrieve the selected path by the user and show in a toast !
        chooser.setOnSelectListener(new StorageChooser.OnSelectListener() {
            @Override
            public void onSelect(String path) {
                Toast.makeText(MainActivity.this, "The selected path is : " + path, Toast.LENGTH_SHORT).show();
            }
        });

        // 3. Display File Picker !
        chooser.show();
    }

    /**
     * Helper method that verifies whether the permissions of a given array are granted or not.
     *
     * @param context
     * @param permissions
     * @return {Boolean}
     */
    public static boolean hasPermissions(Context context, String... permissions) {
        if (context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Callback that handles the status of the permissions request.
     * 
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case FILEPICKER_PERMISSIONS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(
                        MainActivity.this,
                        "Permission granted! Please click on pick a file once again.",
                        Toast.LENGTH_SHORT
                    ).show();
                } else {
                    Toast.makeText(
                        MainActivity.this,
                        "Permission denied to read your External storage :(",
                        Toast.LENGTH_SHORT
                    ).show();
                }

                return;
            }
        }
    }
}

B. Ejemplo de selector de carpetas

En este ejemplo tendremos una actividad principal, cuya maquetación en el archivo activity_main.xml tendrá el siguiente contenido:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button_folderpicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Pick a directory" />
</LinearLayout>

Y el código de la actividad principal será el siguiente:

package com.yourcompany.yourapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.codekidlabs.storagechooser.StorageChooser;

public class MainActivity extends AppCompatActivity {

    public static final int FOLDERPICKER_PERMISSIONS = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button folderpickerBtn = findViewById(R.id.button_folderpicker);
        folderpickerBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            //On click function
            public void onClick(View view) {
                String[] PERMISSIONS = {
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                };

                if(hasPermissions(MainActivity.this, PERMISSIONS)){
                    ShowDirectoryPicker();
                }else{
                    ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS, FOLDERPICKER_PERMISSIONS);
                }
            }
        });
    }

    /**
     * Method that displays the directory chooser of the StorageChooser.
     */
    public void ShowDirectoryPicker(){
        // 1. Initialize dialog
        final StorageChooser chooser = new StorageChooser.Builder()
            .withActivity(MainActivity.this)
            .withFragmentManager(getFragmentManager())
            .withMemoryBar(true)
            .allowCustomPath(true)
            .setType(StorageChooser.DIRECTORY_CHOOSER)
            .build();

        // 2. Retrieve the selected path by the user and show in a toast !
        chooser.setOnSelectListener(new StorageChooser.OnSelectListener() {
            @Override
            public void onSelect(String path) {
                Toast.makeText(MainActivity.this, "The selected path is : " + path, Toast.LENGTH_SHORT).show();
            }
        });

        // 3. Display File Picker !
        chooser.show();
    }

    /**
     * Helper method that verifies whether the permissions of a given array are granted or not.
     *
     * @param context
     * @param permissions
     * @return {Boolean}
     */
    public static boolean hasPermissions(Context context, String... permissions) {
        if (context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Callback that handles the status of the permissions request.
     *
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case FOLDERPICKER_PERMISSIONS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(
                        MainActivity.this,
                        "Permission granted! Please click on pick a file once again.",
                        Toast.LENGTH_SHORT
                    ).show();
                } else {
                    Toast.makeText(
                        MainActivity.this,
                        "Permission denied to read your External storage :(",
                        Toast.LENGTH_SHORT
                    ).show();
                }

                return;
            }
        }
    }
}

Que te diviertas ❤️!


Ingeniero de Software Senior en EPAM Anywhere. Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores