118 votes

Android obtient la taille libre de la mémoire interne/externe

Je veux obtenir la taille de la mémoire libre sur le stockage interne/externe de mon appareil de manière programmatique. J'utilise ce morceau de code :

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount();
long megAvailable = bytesAvailable / 1048576;
Log.e("","Available MB : "+megAvailable);

File path = Environment.getDataDirectory();
StatFs stat2 = new StatFs(path.getPath());
long blockSize = stat2.getBlockSize();
long availableBlocks = stat2.getAvailableBlocks();
String format =  Formatter.formatFileSize(this, availableBlocks * blockSize);
Log.e("","Format : "+format);

et le résultat que j'obtiens est :

11-15 10:27:18.844: E/(25822): Available MB : 7572
11-15 10:27:18.844: E/(25822): Format : 869MB

Le problème est que je veux récupérer la mémoire libre de la SdCard qui est 1,96GB en ce moment. Comment puis-je corriger ce code pour obtenir la taille gratuite ?

1 votes

Depuis le niveau 18 de l'API, la méthode a été renommée pour se terminer par Long. Il faudrait probablement ajouter une vérification du niveau d'API précédent.

0 votes

Toutes les solutions que j'ai essayées ne fonctionnent pas, quand je fais le formatage en tant que stockage interne ... pouvez-vous m'aider, comment faire pour réaliser cela ?

0 votes

Fermé en tant que duplicate - un post plus récent a des réponses jusqu'à Android R

8voto

Ness Tyagi Points 1160

Essayez ce simple extrait

    public static String readableFileSize() {
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
        availableSpace = (long) stat.getBlockSizeLong() * (long) stat.getAvailableBlocksLong();
    else
        availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();

    if(availableSpace <= 0) return "0";
    final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(availableSpace)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(availableSpace/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}

0 votes

Merci, mais j'ai le java.lang.ArrayIndexOutOfBoundsException: length=5; index=-2147483648 erreur, il semble que digitGroups Le résultat est -2147483648.

0 votes

Solution ne fonctionne pas quand je fais le formatage comme stockage interne ... pouvez-vous me s'il vous plaît, comment faire pour réaliser ceci

6voto

Smeet Points 1897

Il est très facile de connaître le stockage disponible si vous obtenez un chemin de stockage interne et externe. Il est également très facile de connaître le chemin de stockage externe du téléphone en utilisant la fonction

Environment.getExternalStorageDirectory().getPath() ;

Je me concentre donc sur la façon de trouver les chemins d'accès à un stockage externe amovible comme une carte SD, USB OTG (je n'ai pas testé USB OTG car je n'en ai pas).

La méthode ci-dessous donne une liste de tous les chemins possibles de stockage externe amovible.

 /**
     * This method returns the list of removable storage and sdcard paths.
     * I have no USB OTG so can not test it. Is anybody can test it, please let me know
     * if working or not. Assume 0th index will be removable sdcard path if size is
     * greater than 0.
     * @return the list of removable storage paths.
     */
    public static HashSet<String> getExternalPaths()
    {
    final HashSet<String> out = new HashSet<String>();
    String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
    String s = "";
    try
    {
        final Process process = new ProcessBuilder().command("mount").redirectErrorStream(true).start();
        process.waitFor();
        final InputStream is = process.getInputStream();
        final byte[] buffer = new byte[1024];
        while (is.read(buffer) != -1)
        {
            s = s + new String(buffer);
        }
        is.close();
    }
    catch (final Exception e)
    {
        e.printStackTrace();
    }

    // parse output
    final String[] lines = s.split("\n");
    for (String line : lines)
    {
        if (!line.toLowerCase(Locale.US).contains("asec"))
        {
            if (line.matches(reg))
            {
                String[] parts = line.split(" ");
                for (String part : parts)
                {
                    if (part.startsWith("/"))
                    {
                        if (!part.toLowerCase(Locale.US).contains("vold"))
                        {
                            out.add(part.replace("/media_rw","").replace("mnt", "storage"));
                        }
                    }
                }
            }
        }
    }
    //Phone's external storage path (Not removal SDCard path)
    String phoneExternalPath = Environment.getExternalStorageDirectory().getPath();

    //Remove it if already exist to filter all the paths of external removable storage devices
    //like removable sdcard, USB OTG etc..
    //When I tested it in ICE Tab(4.4.2), Swipe Tab(4.0.1) with removable sdcard, this method includes
    //phone's external storage path, but when i test it in Moto X Play (6.0) with removable sdcard,
    //this method does not include phone's external storage path. So I am going to remvoe the phone's
    //external storage path to make behavior consistent in all the phone. Ans we already know and it easy
    // to find out the phone's external storage path.
    out.remove(phoneExternalPath);

    return out;
}

0 votes

Si je me souviens bien, l'utilisation de noms constants pour la gestion des chemins peut ne pas fonctionner sur certains appareils, car certains peuvent avoir leurs propres chemins. J'espère que ce n'est pas le cas. +1 pour l'effort.

1 votes

@androiddeveloper Merci d'avoir voté. J'ai besoin du soutien de tous pour tester ce code dans votre appareil parce que je n'ai pas tous les appareils, mais testé dans 4 appareils différents et de travail bien. S'il vous plaît commenter ici ne fonctionne pas dans le mobile de tout le monde.

0 votes

Solution ne fonctionne pas quand je fais le formatage comme stockage interne ... pouvez-vous me s'il vous plaît, comment faire pour réaliser ceci

6voto

makvine Points 19

C'est la façon dont je l'ai fait

Mémoire totale interne

double totalSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getTotalSpace();
double totMb = totalSize / (1024 * 1024);

Taille libre interne

 double availableSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
    double freeMb = availableSize/ (1024 * 1024);

Mémoire externe libre et totale

 long freeBytesExternal =  new File(getExternalFilesDir(null).toString()).getFreeSpace();
       int free = (int) (freeBytesExternal/ (1024 * 1024));
        long totalSize =  new File(getExternalFilesDir(null).toString()).getTotalSpace();
        int total= (int) (totalSize/ (1024 * 1024));
       String availableMb = free+"Mb out of "+total+"MB";

4 votes

Votre méthode montre que j'ai 29 Go de libres sur un total de 50 Go. Cependant, mon application de fichiers standard (Huawei P20 Lite) et l'application de fichiers de Google indiquent 32 Go libres sur un total de 64 Go. Est-ce que je rate quelque chose ou est-ce que votre méthode exclut quelque chose du stockage ?

5voto

Kirill Karmazin Points 959

Ajout rapide au sujet de la mémoire externe

Ne vous laissez pas tromper par le nom de la méthode externalMemoryAvailable() dans la réponse de Dinesh Prajapati.

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) vous donne l'état actuel de la mémoire, si le support est présent et monté à son point de montage avec un accès en lecture/écriture. Vous obtiendrez true même sur les appareils sans carte SD, comme le Nexus 5. Mais c'est quand même une méthode indispensable avant toute opération sur le stockage.

Pour vérifier si votre appareil est équipé d'une carte SD, vous pouvez utiliser la méthode suivante ContextCompat.getExternalFilesDirs()

Il n'affiche pas les dispositifs transitoires, tels que les clés USB.

Sachez également que ContextCompat.getExternalFilesDirs() sur Android 4.3 et inférieur toujours ne renvoie qu'une seule entrée (carte SD si elle est disponible, sinon interne). Vous pouvez en savoir plus aquí .

  public static boolean isSdCardOnDevice(Context context) {
    File[] storages = ContextCompat.getExternalFilesDirs(context, null);
    if (storages.length > 1 && storages[0] != null && storages[1] != null)
        return true;
    else
        return false;
}

dans mon cas, c'était suffisant, mais n'oubliez pas que certains appareils Android peuvent avoir 2 cartes SD, donc si vous avez besoin de toutes les cartes - ajustez le code ci-dessus.

5voto

Mrudul Tora Points 380

Aucune des solutions mentionnées ici ne peut être utilisée pour la mémoire externe. Voici mon code (pour la RAM, la ROM, le stockage système et le stockage externe). Vous pouvez calculer le stockage libre en utilisant (stockage total - stockage utilisé). Et aussi, on ne doit pas utiliser Environment.getExternalStorageDirectory() pour le stockage externe. Il ne s'agit pas nécessairement d'une carte SD externe. De plus, cette solution fonctionnera avec toutes les versions d'Android (testée pour les API 16-30 sur des appareils réels et des émulateurs).

    // Divide by (1024*1024*1024) to get in GB, by (1024*1024) to get in MB, by 1024 to get in KB..

    // RAM
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    manager.getMemoryInfo(memoryInfo);
    long totalRAM=memoryInfo.totalMem;
    long availRAM=memoryInfo.availMem;  // remember to convert in GB,MB or KB.
    long usedRAM=totalRAM-availRAM;

    // ROM
    getTotalStorageInfo(Environment.getDataDirectory().getPath());
    getUsedStorageInfo(Environment.getDataDirectory().getPath());

    // System Storage
    getTotalStorageInfo(Environment.getRootDirectory().getPath());
    getUsedStorageInfo(Environment.getRootDirectory().getPath());

    // External Storage (SD Card)
    File[] files = ContextCompat.getExternalFilesDirs(context, null);
    if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.JELLY_BEAN_MR2){
        if (files.length == 1) {
            Log.d("External Storage Memory","is present");
            getTotalStorageInfo(files[0].getPath());
            getUsedStorageInfo(files[0].getPath());
        }
    } else {
        if (files.length > 1 && files[0] != null && files[1] != null) {
            Log.d("External Storage Memory","is present");
            long t=getTotalStorageInfo(files[1].getPath());
            long u=getUsedStorageInfo(files[1].getPath());
            System.out.println("Total External Mem: "+t+" Used External Mem: "+u+" Storage path: "+files[1].getPath());
        }
    }
}

public long getTotalStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long t;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        t = statFs.getTotalBytes();
    } else {
        t = statFs.getBlockCount() * statFs.getBlockSize();
    }
    return t;    // remember to convert in GB,MB or KB.
}

public long getUsedStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long u;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        u = statFs.getTotalBytes() - statFs.getAvailableBytes();
    } else {
        u = statFs.getBlockCount() * statFs.getBlockSize() - statFs.getAvailableBlocks() * statFs.getBlockSize();
    }
    return u;  // remember to convert in GB,MB or KB.
}

Maintenant, ici, pour la ROM, j'ai utilisé le chemin "/data" et pour le stockage système, le chemin est "/system". Et pour le stockage externe, j'ai utilisé ContextCompat.getExternalFilesDirs(context, null); Il fonctionnera donc aussi sur Android Q et Android R. J'espère que cela vous aidera.

1 votes

Dans la méthode getTotalStorageInfo, la condition else devrait être t = statFs.getBlockCount() * statFs.getBlockSize() ;

0 votes

@praveenb Merci de le signaler. Je l'ai corrigé maintenant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X