Android obtient une taille gratuite de mémoire interne / externe

98

Je souhaite obtenir la taille de la mémoire libre sur le stockage interne / externe de mon appareil par programmation. 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 obtenir la mémoire libre de SdCard qui est en 1,96GBce moment. Comment puis-je corriger ce code pour pouvoir obtenir la taille gratuite?

Android-Droid
la source
À partir du niveau d'API 18, ils ont renommé la méthode pour se terminer par Long. Vous devrez probablement ajouter une vérification du niveau d'API avant cela
Jayshil Dave
Toute la solution J'ai essayé de ne travailler avec personne, quand je formate en tant que stockage interne ... pouvez-vous me plaire, comment y parvenir?
Yogesh Rathi

Réponses:

182

Vous trouverez ci-dessous le code correspondant à votre objectif:

public static boolean externalMemoryAvailable() {
        return android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED);
    }

    public static String getAvailableInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        return formatSize(availableBlocks * blockSize);
    }

    public static String getTotalInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long totalBlocks = stat.getBlockCountLong();
        return formatSize(totalBlocks * blockSize);
    }

    public static String getAvailableExternalMemorySize() {
        if (externalMemoryAvailable()) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSizeLong();
            long availableBlocks = stat.getAvailableBlocksLong();
            return formatSize(availableBlocks * blockSize);
        } else {
            return ERROR;
        }
    }

    public static String getTotalExternalMemorySize() {
        if (externalMemoryAvailable()) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSizeLong();
            long totalBlocks = stat.getBlockCountLong();
            return formatSize(totalBlocks * blockSize);
        } else {
            return ERROR;
        }
    }

    public static String formatSize(long size) {
        String suffix = null;

        if (size >= 1024) {
            suffix = "KB";
            size /= 1024;
            if (size >= 1024) {
                suffix = "MB";
                size /= 1024;
            }
        }

        StringBuilder resultBuffer = new StringBuilder(Long.toString(size));

        int commaOffset = resultBuffer.length() - 3;
        while (commaOffset > 0) {
            resultBuffer.insert(commaOffset, ',');
            commaOffset -= 3;
        }

        if (suffix != null) resultBuffer.append(suffix);
        return resultBuffer.toString();
    }

Obtenir la taille de la RAM

ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;
Dinesh Prajapati
la source
2
getBlockSize()et getBlockCountsont obsolètes.
Nima G
2
@DineshPrajapati Merci pour la réponse, j'ai une question, si j'utilise Environment.getRootDirectory () au lieu de Environment.getDataDirectory pour calculer le stockage interne, j'obtiens une sortie .. cela se réfère à la mémoire interne autre mémoire ..
AK Joshi
3
@DineshPrajapati .. Testé sur MOTO G2 Obtention de données erronées pour le stockage externe
AK Joshi
1
Utilisez Long à la fin pour les nouveaux niveaux d'API (> 18)
Gun2sh
1
Merci beaucoup pour le partage des connaissances
Kishan Soni
40

Voici comment je l'ai fait:

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable;
if (android.os.Build.VERSION.SDK_INT >= 
    android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
    bytesAvailable = stat.getBlockSizeLong() * stat.getAvailableBlocksLong();
}
else {
    bytesAvailable = (long)stat.getBlockSize() * (long)stat.getAvailableBlocks();
}
long megAvailable = bytesAvailable / (1024 * 1024);
Log.e("","Available MB : "+megAvailable);
Android-Droid
la source
2
mais ceci est obsolète :(
abbasalim
@ ArMo372, avez-vous trouvé le code de remplacement pour ça?
SimpleCoder
3
Remplacez simplement getBlockSizeet getAvailableBlockspar getBlockSizeLonget getAvailableBlocksLong.
smg
1
cela n'obtient pas le bon espace disponible. Cela obtient 1141 au lieu de 1678 @smg
1
La solution ne fonctionne pas lorsque je formate en tant que stockage interne ... pouvez-vous me plaire, comment faire pour y parvenir
Yogesh Rathi
27

Depuis l'API 9, vous pouvez faire:

long freeBytesInternal = new File(ctx.getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();
Tzoiker
la source
2
File.getUsableSpace () est probablement meilleur car vous ne travaillez probablement pas en tant que root.
Mark
Les File.getUsableSpace()ressemble à une méthode plus facile à utiliser plutôt que d' utiliser StatFs. Pourquoi utiliser StatFs@MarkCarter?
StuStirling
1
@ DiscoS2 Vous utiliseriez des StatFs si votre minSdkVersion est inférieure à 9.
Marquez
1
Comment surveilleriez-vous également les changements de stockage?
développeur android
24

Pour obtenir tous les dossiers de stockage disponibles (y compris les cartes SD), vous obtenez d'abord les fichiers de stockage:

File internalStorageFile=getFilesDir();
File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);

Ensuite, vous pouvez obtenir la taille disponible de chacun d'entre eux.

Il y a 3 façons de le faire:

API 8 et inférieur:

StatFs stat=new StatFs(file.getPath());
long availableSizeInBytes=stat.getBlockSize()*stat.getAvailableBlocks();

API 9 et supérieur:

long availableSizeInBytes=file.getFreeSpace();

API 18 et supérieur (non nécessaire si la précédente est correcte):

long availableSizeInBytes=new StatFs(file.getPath()).getAvailableBytes(); 

Pour obtenir une belle chaîne formatée de ce que vous avez maintenant, vous pouvez utiliser:

String formattedResult=android.text.format.Formatter.formatShortFileSize(this,availableSizeInBytes);

ou vous pouvez l'utiliser au cas où vous souhaiteriez voir le nombre d'octets exact mais bien:

NumberFormat.getInstance().format(availableSizeInBytes);

Notez que je pense que le stockage interne pourrait être le même que le premier stockage externe, puisque le premier est celui émulé.


EDIT: En utilisant StorageVolume sur Android Q et supérieur, je pense qu'il est possible d'obtenir l'espace libre de chacun, en utilisant quelque chose comme:

    val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
    AsyncTask.execute {
        for (storageVolume in storageVolumes) {
            val uuid: UUID = storageVolume.uuid?.let { UUID.fromString(it) } ?: StorageManager.UUID_DEFAULT
            val allocatableBytes = storageManager.getAllocatableBytes(uuid)
            Log.d("AppLog", "allocatableBytes:${android.text.format.Formatter.formatShortFileSize(this,allocatableBytes)}")
        }
    }

Je ne suis pas sûr que ce soit correct, et je ne peux pas trouver un moyen d'obtenir la taille totale de chacun, alors j'ai écrit à ce sujet ici et posé des questions à ce sujet ici .

développeur android
la source
1
Comment obtenir de l'espace libre sur une carte SD amovible (ou un lecteur flash USB OTG) sur des appareils avec l'API 23? new StatFs (file.getPath ()). getAvailableBytes () ou file.getUsableSpace () donne 972546048 octets quelle que soit la taille de stockage réelle sur Nexus 5 (Marshmallow 6.0.1).
isabsent le
@isabsent Nexus 5 n'a pas d'emplacement pour carte SD. Comment l'avez-vous vérifié?
développeur android
Je l'ai vérifié avec un lecteur flash USB OTG.
isabsent le
@isabsent je ne l'ai jamais utilisé. Désolé. Fonctionne-t-il bien sur l'API 22 et les versions antérieures?
développeur android
1
@Smeet Est-il possible que vous l'essayiez sur Android 6 ou supérieur? Si tel est le cas, c'est peut-être un problème comme celui-ci: code.google.com/p/android/issues/detail?id=200326
développeur android
9

@ Android-Droid - vous vous trompez de Environment.getExternalStorageDirectory()points de stockage externe qui ne doit pas nécessairement être une carte SD, il peut également être monté sur la mémoire interne. Voir:

Trouver un emplacement de carte SD externe

Sharp80
la source
7

Essayez cet extrait de code simple

    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];
}
Ness Tyagi
la source
Merci, mais j'ai l' java.lang.ArrayIndexOutOfBoundsException: length=5; index=-2147483648erreur, semble que le digitGroupsrésultat est -2147483648.
Acuna
La solution ne fonctionne pas lorsque je formate en tant que stockage interne ... pouvez-vous me plaire, comment y parvenir
Yogesh Rathi
6

Il est très facile de connaître le stockage disponible si vous obtenez un chemin de stockage interne et externe. Le chemin de stockage externe du téléphone est également très facile à découvrir à l'aide

Environment.getExternalStorageDirectory (). GetPath ();

Je me concentre donc simplement sur la façon de trouver les chemins du stockage amovible externe comme la carte SD amovible, l'USB OTG (non testé USB OTG car je n'ai pas d'USB OTG).

La méthode ci-dessous donnera une liste de tous les chemins de stockage amovibles externes possibles.

 /**
     * 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;
}
Smeet
la source
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.
développeur android
1
@androiddeveloper Merci cher d'avoir voté. J'ai besoin du support de tous pour tester ce code sur votre appareil car je n'ai pas tous les appareils, mais testé sur 4 appareils différents et fonctionne bien. S'il vous plaît commenter ici ne fonctionne pas dans le mobile d'aucun corps.
Smeet
La solution ne fonctionne pas lorsque je formate en tant que stockage interne ... pouvez-vous me plaire, comment faire pour y parvenir
Yogesh Rathi
4

Ajout rapide à la rubrique Mémoire externe

Ne soyez pas confus 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 truemême sur les appareils sans carte SD, comme le Nexus 5. Mais c'est toujours une méthode «incontournable» avant toute opération avec stockage.

Pour vérifier s'il y a une carte SD sur votre appareil, vous pouvez utiliser la méthode ContextCompat.getExternalFilesDirs()

Il n'affiche pas les périphériques transitoires, tels que les clés USB.

Sachez également que ContextCompat.getExternalFilesDirs()sur Android 4.3 et les versions antérieures, il ne renverra toujours qu'une seule entrée (carte SD si elle est disponible, sinon interne). Vous pouvez en savoir plus ici .

  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 en avez besoin, ajustez le code ci-dessus.

Kirill Karmazin
la source
2
@RequiresApi(api = Build.VERSION_CODES.O)
private void showStorageVolumes() {
    StorageStatsManager storageStatsManager = (StorageStatsManager) getSystemService(Context.STORAGE_STATS_SERVICE);
    StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
    if (storageManager == null || storageStatsManager == null) {
        return;
    }
    List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
    for (StorageVolume storageVolume : storageVolumes) {
        final String uuidStr = storageVolume.getUuid();
        final UUID uuid = uuidStr == null ? StorageManager.UUID_DEFAULT : UUID.fromString(uuidStr);
        try {
            Log.d("AppLog", "storage:" + uuid + " : " + storageVolume.getDescription(this) + " : " + storageVolume.getState());
            Log.d("AppLog", "getFreeBytes:" + Formatter.formatShortFileSize(this, storageStatsManager.getFreeBytes(uuid)));
            Log.d("AppLog", "getTotalBytes:" + Formatter.formatShortFileSize(this, storageStatsManager.getTotalBytes(uuid)));
        } catch (Exception e) {
            // IGNORED
        }
    }
}

La classe StorageStatsManager a introduit Android O et supérieur, ce qui peut vous donner un octet gratuit et total dans le stockage externe / interne. Pour plus de détails sur le code source, vous pouvez lire mon article suivant. vous pouvez utiliser la réflexion pour une version inférieure à Android O

https://medium.com/cashify-engineering/how-to-get-storage-stats-in-android-o-api-26-4b92eca6805b

Brijesh Gupta
la source
2

C'est comme ça que 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";
makvine
la source
0

A propos du menory externe, il existe un autre moyen:
File external = Environment.getExternalStorageDirectory(); free:external.getFreeSpace(); total:external.getTotalSpace();

Edward Anderson
la source
0

Après avoir vérifié différentes solutions, écrivez moi-même le code, il s'agit du code complet à rechercher

  • Mémoire externe totale
  • Mémoire externe libre
  • Mémoire externe utilisée
  • Mémoire interne TotaL
  • Mémoire interne utilisée
  • Mémoire interne libre

'' ''

object DeviceMemoryUtil {
private const val error: String = "Something went wrog"
private const val noExternalMemoryDetected = "No external Storage detected"
private var totalExternalMemory: Long = 0
private var freeExternalMemory: Long = 0
private var totalInternalStorage: Long = 0
private var freeInternalStorage: Long = 0

/**
 * Checks weather external memory is available or not
 */
private fun externalMemoryAvailable(): Boolean {
    return Environment.getExternalStorageState() ==
            Environment.MEDIA_MOUNTED
}

/**
 *Gives total external memory
 * @return String Size of external memory
 * @return Boolean True if memory size is returned
 */
fun getTotalExternalMemorySize(): Pair<String?, Boolean> {
    val dirs: Array<File> = ContextCompat.getExternalFilesDirs(CanonApplication.getCanonAppInstance(), null)
    return if (externalMemoryAvailable()) {
        if (dirs.size > 1) {
            val stat = StatFs(dirs[1].path)
            val blockSize = stat.blockSizeLong
            val totalBlocks = stat.blockCountLong
            var totalExternalSize = totalBlocks * blockSize
            totalExternalMemory = totalExternalSize
            Pair(formatSize(totalExternalSize), true)
        } else {
            Pair(error, false)
        }
    } else {
        Pair(noExternalMemoryDetected, false)
    }
}

/**
 * Gives free external memory size
 * @return String Size of free external memory
 * @return Boolean True if memory size is returned
 */
fun getAvailableExternalMemorySize(): Pair<String?, Boolean> {
    val dirs: Array<File> = ContextCompat.getExternalFilesDirs(CanonApplication.getCanonAppInstance(), null)
    if (externalMemoryAvailable()) {
        return if (dirs.size > 1) {
            val stat = StatFs(dirs[1].path)
            val blockSize = stat.blockSizeLong
            val availableBlocks = stat.availableBlocksLong
            var freeExternalSize = blockSize * availableBlocks
            freeExternalMemory = freeExternalSize
            Pair(formatSize(freeExternalSize), true)
        } else {
            Pair(error, false)
        }
    } else {
        return Pair(noExternalMemoryDetected, false)
    }
}

/**
 * Gives used external memory size
 *  @return String Size of used external memory
 * @return Boolean True if memory size is returned
 */
fun getUsedExternalMemorySize(): Pair<String?, Boolean> {
    return if (externalMemoryAvailable()) {
        val totalExternalSize = getTotalExternalMemorySize()
        val freeExternalSize = getAvailableExternalMemorySize()
        if (totalExternalSize.second && freeExternalSize.second) {
            var usedExternalVolume = totalExternalMemory - freeExternalMemory
            Pair(formatSize(usedExternalVolume), true)
        } else {
            Pair(error, false)
        }
    } else {
        Pair(noExternalMemoryDetected, false)
    }
}

/**
 *Formats the long to size of memory in gb,mb etc.
 * @param size Size of memory
 */
fun formatSize(size: Long): String? {
    return android.text.format.Formatter.formatFileSize(CanonApplication.getCanonAppInstance(), size)
}

/**
 * Gives total internal memory size
 *  @return String Size of total internal memory
 * @return Boolean True if memory size is returned
 */
fun getTotalInternalStorage(): Pair<String?, Boolean> {
    if (showStorageVolumes()) {
        return Pair(formatSize(totalInternalStorage), true)
    } else {
        return Pair(error, false)
    }

}

/**
 * Gives free or available internal memory size
 *  @return String Size of free internal memory
 * @return Boolean True if memory size is returned
 */
fun getFreeInternalStorageVolume(): Pair<String?, Boolean> {
    return if (showStorageVolumes()) {
        Pair(formatSize(freeInternalStorage), true)
    } else {
        Pair(error, false)
    }
}

/**
 *For calculation of internal storage
 */
private fun showStorageVolumes(): Boolean {
    val storageManager = CanonApplication.canonApplicationInstance.applicationContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageStatsManager = CanonApplication.canonApplicationInstance.applicationContext.getSystemService(Context.STORAGE_STATS_SERVICE) as StorageStatsManager
    if (storageManager == null || storageStatsManager == null) {
        return false
    }
    val storageVolumes: List<StorageVolume> = storageManager.storageVolumes
    for (storageVolume in storageVolumes) {
        var uuidStr: String? = null
        storageVolume.uuid?.let {
            uuidStr = it
        }
        val uuid: UUID = if (uuidStr == null) StorageManager.UUID_DEFAULT else UUID.fromString(uuidStr)
        return try {
            freeInternalStorage = storageStatsManager.getFreeBytes(uuid)
            totalInternalStorage = storageStatsManager.getTotalBytes(uuid)
            true
        } catch (e: Exception) {
            // IGNORED
            false
        }
    }
    return false
}

fun getTotalInternalExternalMemory(): Pair<Long?, Boolean> {
    if (externalMemoryAvailable()) {
        if (getTotalExternalMemorySize().second) {
            if (getTotalInternalStorage().second) {
                return Pair(totalExternalMemory + totalInternalStorage, true)
            } else {
                return Pair(0, false)
            }
        }
        return Pair(0, false)
    } else {
        if (getTotalInternalStorage().second) {
            return Pair(totalInternalStorage, true)
        } else {
            return Pair(0, false)
        }
    }

}

fun getTotalFreeStorage(): Pair<Long,Boolean> {
    if (externalMemoryAvailable()){
        if(getFreeInternalStorageVolume().second){
            getFreeInternalStorageVolume()
            getAvailableExternalMemorySize()
                return Pair(freeExternalMemory + freeInternalStorage,true)
        }
        else{
            return Pair(0,false)
        }
    }
    else {
        if (getFreeInternalStorageVolume().second){
            getFreeInternalStorageVolume()
            return Pair(freeInternalStorage,true)
        }
      else{
            return Pair(0,false)
        }
    }

}}
Sahil Bansal
la source