Android ottiene dimensioni gratuite della memoria interna / esterna


98

Voglio ottenere la dimensione della memoria libera sulla memoria interna / esterna del mio dispositivo a livello di programmazione. Sto usando questo pezzo di codice:

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 il risultato che ottengo è:

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

Il problema è che voglio avere la memoria libera di SdCard che è 1,96GBadesso. Come posso correggere questo codice in modo da ottenere la dimensione gratuita?


A partire dal livello API 18 hanno rinominato il metodo per terminare con Long. Probabilmente dovresti aggiungere un controllo del livello API prima di esso
Jayshil Dave

Tutte le soluzioni ho provato a non lavorare con nessuno, quando eseguo la formattazione come memoria interna ... puoi farmi piacere, come ottenere questo?
Yogesh Rathi

Risposte:


182

Di seguito è riportato il codice per il tuo scopo:

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

Ottieni dimensioni RAM

ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;

2
getBlockSize()e getBlockCountsono deprecati.
Nima G

2
@DineshPrajapati Grazie per la risposta, ho una domanda, se uso Environment.getRootDirectory () invece di Environment.getDataDirectory per il calcolo della memoria interna, sto ottenendo un output .. questo si riferisce alla memoria interna altra memoria ..
AK Joshi

3
@DineshPrajapati .. Testato su MOTO G2 Ottenere dati errati per l'archiviazione esterna
AK Joshi

1
Usa Long alla fine per i nuovi livelli API (> 18)
Gun2sh

1
Grazie mille per aver condiviso la conoscenza
Kishan Soni

40

Questo è il modo in cui l'ho fatto:

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

2
ma questo è obsoleto :(
abbasalim

@ ArMo372, avete scoperto il codice sostitutivo per questo?
SimpleCoder

3
Basta sostituire getBlockSizee getAvailableBlockscon getBlockSizeLonge getAvailableBlocksLong.
smg

1
questo non sta ottenendo il giusto spazio disponibile. Questo sta ottenendo 1141 invece di 1678 @smg

1
La soluzione non funziona quando
formatto

27

Dall'API 9 puoi fare:

long freeBytesInternal = new File(ctx.getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();

2
File.getUsableSpace () è probabilmente migliore perché probabilmente non stai eseguendo come root.
Marco

Le File.getUsableSpace()sembra un metodo più semplice da usare piuttosto che utilizzare StatFs. Perché dovrei usare StatFs@MarkCarter?
StuStirling

1
@ DiscoS2 Useresti StatFs se il tuo minSdkVersion è inferiore a 9.
Contrassegna

1
Come monitorereste anche le modifiche allo spazio di archiviazione?
sviluppatore Android

24

Per ottenere tutte le cartelle di archiviazione disponibili (comprese le schede SD), devi prima ottenere i file di archiviazione:

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

Quindi puoi ottenere la dimensione disponibile di ciascuno di essi.

Ci sono 3 modi per farlo:

API 8 e inferiore:

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

API 9 e successive:

long availableSizeInBytes=file.getFreeSpace();

API 18 e successive (non necessaria se la precedente è ok):

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

Per ottenere una bella stringa formattata di ciò che hai ora, puoi usare:

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

oppure puoi usarlo nel caso in cui desideri vedere il numero esatto di byte ma bene:

NumberFormat.getInstance().format(availableSizeInBytes);

Tieni presente che penso che la memoria interna potrebbe essere la stessa della prima memoria esterna, poiché la prima è quella emulata.


EDIT: utilizzando StorageVolume su Android Q e versioni successive, penso che sia possibile ottenere lo spazio libero di ciascuno, usando qualcosa come:

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

Non sono sicuro che sia corretto e non riesco a trovare un modo per ottenere la dimensione totale di ciascuno, quindi ne ho scritto qui e ho chiesto informazioni qui .


1
Come ottenere spazio libero su scheda SD rimovibile (o unità flash USB OTG) sui dispositivi con API 23? new StatFs (file.getPath ()). getAvailableBytes () o file.getUsableSpace () fornisce 972546048 byte indipendentemente dalla dimensione di archiviazione reale su Nexus 5 (Marshmallow 6.0.1).
assente il

@isabsent Nexus 5 non dispone di slot per schede SD. Come l'hai controllato?
sviluppatore Android

L'ho controllato con un'unità flash USB OTG.
assente il

@isabsent non l'ho mai usato. Scusate. Funziona bene su API 22 e inferiori?
sviluppatore Android

1
@Smeet È possibile provarlo su Android 6 o superiore? Se è così, forse è un problema come questo: code.google.com/p/android/issues/detail?id=200326
sviluppatore Android


7

Prova questo semplice snippet

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

Grazie, ma ho l' java.lang.ArrayIndexOutOfBoundsException: length=5; index=-2147483648errore, sembra che il digitGroupsrisultato sia -2147483648.
Acuna

La soluzione non funziona quando
formatto

6

È molto facile scoprire lo spazio di archiviazione disponibile se si ottiene un percorso di archiviazione interno ed esterno. Anche il percorso di archiviazione esterno del telefono è davvero molto facile da scoprire usando

Environment.getExternalStorageDirectory (). GetPath ();

Quindi mi sto solo concentrando su come scoprire i percorsi di archiviazione rimovibile esterna come sdcard rimovibile, USB OTG (non testato USB OTG perché non ho USB OTG).

Il metodo di seguito fornirà un elenco di tutti i possibili percorsi di archiviazione rimovibili esterni.

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

Come ricordo, l'uso di nomi di costanti per la gestione dei percorsi potrebbe non funzionare su alcuni dispositivi, poiché alcuni potrebbero avere i propri percorsi. Spero che non sia questo il caso. +1 per lo sforzo.
sviluppatore Android

1
@androiddeveloper Grazie caro per aver votato. Ho bisogno del supporto di tutti per testare questo codice nel tuo dispositivo perché non ho tutti i dispositivi ma ho testato in 4 dispositivi diversi e funziona bene. Si prega di commentare qui non funziona sul cellulare di nessun corpo.
Smeet

La soluzione non funziona quando
formatto

4

Aggiunta rapida all'argomento Memoria esterna

Non essere confuso dal nome del metodo externalMemoryAvailable()nella risposta di Dinesh Prajapati.

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())fornisce lo stato corrente della memoria, se il supporto è presente e montato nel suo punto di montaggio con accesso in lettura / scrittura. Otterrai trueanche dispositivi senza schede SD, come Nexus 5. Ma è comunque un metodo "indispensabile" prima di qualsiasi operazione con l'archiviazione.

Per verificare se è presente una scheda SD sul tuo dispositivo puoi utilizzare il metodo ContextCompat.getExternalFilesDirs()

Non mostra i dispositivi transitori, come le unità flash USB.

Inoltre, tieni presente che ContextCompat.getExternalFilesDirs()su Android 4.3 e versioni precedenti restituirà sempre solo 1 voce (scheda SD se disponibile, altrimenti Interna). Puoi leggere di più al riguardo qui .

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

nel mio caso è stato sufficiente, ma non dimenticare che alcuni dispositivi Android potrebbero avere 2 schede SD, quindi se hai bisogno di tutte, regola il codice sopra.


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 ha introdotto Android O e versioni successive che possono fornire byte gratuiti e totali nella memoria esterna / interna. Per informazioni dettagliate sul codice sorgente, puoi leggere il mio articolo seguente. puoi usare la riflessione per versioni inferiori a Android O

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


2

Questo è il modo in cui l'ho fatto ..

memoria totale interna

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

Dimensione libera interna

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

Memoria esterna libera e 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";

0

A proposito di menory esterno, c'è un altro modo:
File external = Environment.getExternalStorageDirectory(); free:external.getFreeSpace(); total:external.getTotalSpace();


0

Dopo aver verificato diverse soluzioni, scrivi il codice da solo, questo è il codice completo per la ricerca

  • Memoria esterna totale
  • Memoria esterna gratuita
  • Memoria esterna usata
  • Memoria interna totale
  • Memoria interna usata
  • Memoria interna gratuita

'' ''

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

}}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.