Android obtém tamanho livre de memória interna / externa

98

Desejo obter o tamanho da memória livre no armazenamento interno / externo do meu dispositivo de forma programática. Estou usando este código:

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);

e o resultado que estou obtendo é:

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

O problema é que quero obter a memória livre do SdCard que está 1,96GBagora. Como posso corrigir este código para obter o tamanho gratuito?

Android-Droid
fonte
No nível 18 da API, eles renomearam o método para terminar com Long. Provavelmente, você precisaria adicionar uma verificação de nível de API antes disso
Jayshil Dave
All Solution tentei não funcionar ninguém, quando formato como armazenamento interno ... pode me agradar, como faço para conseguir isso?
Yogesh Rathi

Respostas:

182

Abaixo está o código para sua finalidade:

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();
    }

Obter tamanho de RAM

ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;
Dinesh Prajapati
fonte
2
getBlockSize()e getBlockCountestão obsoletos.
Nima G
2
@DineshPrajapati Obrigado pela resposta, eu tenho uma pergunta, se eu usar Environment.getRootDirectory () em vez de Environment.getDataDirectory para calcular o armazenamento interno, estou recebendo alguma saída .. isso se refere à memória interna outra memória ..
AK Joshi
3
@DineshPrajapati .. Testado no MOTO G2 Obtendo dados errados para armazenamento externo
AK Joshi,
1
Use Long no final para níveis de API mais recentes (> 18)
Gun2sh
1
Muito obrigado por compartilhar conhecimento
Kishan Soni
40

Foi assim que fiz:

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
fonte
2
mas está obsoleto :(
abbasalim
@ ArMo372, vocês descobriram o código de substituição para isso?
SimpleCoder
3
Basta substituir getBlockSizee getAvailableBlockspor getBlockSizeLonge getAvailableBlocksLong.
smg de
1
isso não está obtendo o espaço disponível certo. Está ficando 1141 em vez de 1678 @smg
1
A solução não funciona quando formato como armazenamento interno ... você pode me agradar, como fazer isso
Yogesh Rathi
27

Desde a API 9, você pode fazer:

long freeBytesInternal = new File(ctx.getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();
Tzoiker
fonte
2
File.getUsableSpace () é provavelmente melhor porque você provavelmente não está executando como root.
Marcar
Os File.getUsableSpace()parece com um método mais fácil de usar em vez de usar StatFs. Por que eu usaria StatFs@MarkCarter?
StuStirling de
1
@ DiscoS2 Você usaria StatFs se minSdkVersion fosse menor que 9.
Marcar em
1
Como você também monitoraria as mudanças de armazenamento?
desenvolvedor Android de
24

Para obter todas as pastas de armazenamento disponíveis (incluindo cartões SD), primeiro você obtém os arquivos de armazenamento:

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

Então você pode obter o tamanho disponível de cada um deles.

Existem 3 maneiras de fazer isso:

API 8 e inferior:

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

API 9 e superior:

long availableSizeInBytes=file.getFreeSpace();

API 18 e superior (não necessário se o anterior estiver ok):

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

Para obter uma string formatada legal do que você tem agora, você pode usar:

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

ou você pode usar isso no caso de desejar ver o número exato de bytes, mas muito bem:

NumberFormat.getInstance().format(availableSizeInBytes);

Observe que acho que o armazenamento interno pode ser o mesmo que o primeiro armazenamento externo, já que o primeiro é o emulado.


EDIT: Usando StorageVolume no Android Q e acima, acho que é possível obter o espaço livre de cada um, usando algo como:

    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)}")
        }
    }

Não tenho certeza se isso está correto e não consigo encontrar uma maneira de obter o tamanho total de cada um, então escrevi sobre isso aqui e perguntei sobre isso aqui .

desenvolvedor android
fonte
1
Como obter espaço livre no cartão SD removível (ou unidade flash USB OTG) em dispositivos com API 23? new StatFs (file.getPath ()). getAvailableBytes () ou file.getUsableSpace () fornece 972546048 bytes, independentemente do tamanho real de armazenamento no Nexus 5 (Marshmallow 6.0.1).
ausente em
@isabsent Nexus 5 não tem slot para cartão SD. Como você verificou isso?
desenvolvedor Android de
Eu verifiquei com uma unidade flash USB OTG.
ausente em
@isabsent Eu nunca usei. Desculpe. Funciona bem na API 22 e versões anteriores?
desenvolvedor Android de
1
@Smeet É possível experimentar no Android 6 ou superior? Em caso afirmativo, talvez seja um problema como este: code.google.com/p/android/issues/detail?id=200326
desenvolvedor Android
9

@ Android-Droid - você tem Environment.getExternalStorageDirectory()pontos errados para armazenamento externo que não precisa ser cartão SD, também pode ser montado na memória interna. Vejo:

Encontre um local externo para cartão SD

Sharp80
fonte
7

Experimente este trecho simples

    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
fonte
Obrigado, mas tenho o java.lang.ArrayIndexOutOfBoundsException: length=5; index=-2147483648erro, parece que o digitGroupsresultado é -2147483648.
Acuna de
A solução não funciona quando formato como armazenamento interno ... você pode me agradar, como fazer isso
Yogesh Rathi
6

É muito fácil descobrir o armazenamento disponível se você obtiver um caminho de armazenamento interno ou externo. Além disso, o caminho de armazenamento externo do telefone é realmente muito fácil de descobrir usando

Environment.getExternalStorageDirectory (). GetPath ();

Então, estou apenas me concentrando em como descobrir os caminhos de armazenamento externo removível como sdcard removível, USB OTG (não testei USB OTG porque não tenho USB OTG).

O método abaixo fornecerá uma lista de todos os caminhos de armazenamento removíveis externos possíveis.

 /**
     * 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
fonte
Pelo que me lembro, o uso de nomes constantes para o tratamento de caminhos pode não funcionar em alguns dispositivos, pois alguns podem ter seus próprios caminhos. Espero que não seja o caso. 1 pelo esforço.
desenvolvedor Android de
1
@androiddeveloper Obrigado, querido, por votar. Preciso do suporte de todos para testar este código em seu dispositivo porque não tenho todos os dispositivos, mas testei em 4 dispositivos diferentes e funcionando bem. Por favor, comente aqui não está funcionando no celular de nenhum corpo.
Smeet de
A solução não funciona quando formato como armazenamento interno ... você pode me agradar, como fazer isso
Yogesh Rathi
4

Adição rápida ao tópico de memória externa

Não se confunda com o nome do método externalMemoryAvailable()na resposta de Dinesh Prajapati.

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())fornece o estado atual da memória, se a mídia estiver presente e montada em seu ponto de montagem com acesso de leitura / gravação. Você se truevingará em dispositivos sem cartões SD, como o Nexus 5. Mas ainda é um método 'obrigatório' antes de qualquer operação com armazenamento.

Para verificar se há um cartão SD no seu dispositivo, você pode usar o método ContextCompat.getExternalFilesDirs()

Não mostra dispositivos transitórios, como unidades flash USB.

Também esteja ciente de que ContextCompat.getExternalFilesDirs()no Android 4.3 e inferior sempre retornará apenas 1 entrada (cartão SD se estiver disponível, caso contrário, interno). Você pode ler mais sobre isso aqui .

  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;
}

no meu caso foi o suficiente, mas não se esqueça que alguns dos dispositivos Android podem ter 2 cartões SD, então se você precisar de todos eles - ajuste o código acima.

Kirill Karmazin
fonte
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
        }
    }
}

A classe StorageStatsManager introduziu o Android O e superior, que pode fornecer bytes gratuitos e totais no armazenamento externo / interno. Para detalhes com o código-fonte, você pode ler meu artigo a seguir. você pode usar reflexão para menor do que o Android O

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

Brijesh Gupta
fonte
2

É assim que eu fiz ..

memória total interna

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

Tamanho livre interno

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

Memória externa livre e total

 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
fonte
0

Sobre menory externo, há outra maneira:
File external = Environment.getExternalStorageDirectory(); free:external.getFreeSpace(); total:external.getTotalSpace();

Edward Anderson
fonte
0

Depois de verificar o código de escrita de diferentes soluções, este é um código completo para encontrar

  • Memória Externa Total
  • Memória Externa Livre
  • Memória Externa Usada
  • Memória Interna TotaL
  • Memória interna usada
  • Memória Interna Livre

'' ''

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
fonte