java download - Come controllare lo spazio disponibile sul dispositivo Android? sulla scheda SD?




programmare browser (9)

La risposta di Yaroslav darà la dimensione della scheda SD, non lo spazio disponibile. StatFs getAvailableBlocks() restituirà il numero di blocchi che sono ancora accessibili ai normali programmi. Ecco la funzione che sto usando:

public static float megabytesAvailable(File f) {
    StatFs stat = new StatFs(f.getPath());
    long bytesAvailable = (long)stat.getBlockSize() * (long)stat.getAvailableBlocks();
    return bytesAvailable / (1024.f * 1024.f);
}

Il codice sopra riportato fa riferimento ad alcune funzioni obsolete dal 13 agosto 2014. Di seguito, riproduco una versione aggiornata:

public static float megabytesAvailable(File f) {
    StatFs stat = new StatFs(f.getPath());
    long bytesAvailable = 0;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
        bytesAvailable = (long) stat.getBlockSizeLong() * (long) stat.getAvailableBlocksLong();
    else
        bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks();
    return bytesAvailable / (1024.f * 1024.f);
}

Questa domanda ha già una risposta qui:

Come posso verificare quanto MB o GB sono rimasti sul dispositivo Android? Sto usando JAVA e Android SDK 2.0.1.

Esiste un servizio di sistema che potrebbe esporre qualcosa di simile?


Google ha informazioni su questo nella pagina introduttiva - Vedi Query Free Space. Dicono che è possibile controllare lo spazio disponibile da getFreeSpace() ma dichiarano che questo è inaccurato e che ci si dovrebbe aspettare un po 'meno spazio libero di questo. Dicono:

Se il numero restituito è di qualche MB in più rispetto alla dimensione dei dati che si desidera salvare, o se il file system è pieno al di sotto del 90%, è probabile che sia sicuro procedere. Altrimenti, probabilmente non dovresti scrivere sullo spazio di archiviazione.

Inoltre danno il consiglio che spesso è più utile non controllare lo spazio libero e try catch un errore:

Non è necessario controllare la quantità di spazio disponibile prima di salvare il file. Puoi invece provare a scrivere il file subito, quindi prendere una IOException se si verifica uno. Potrebbe essere necessario farlo se non sai esattamente di quanto spazio hai bisogno. Ad esempio, se si modifica la codifica del file prima di salvarlo convertendo un'immagine PNG in JPEG, non si conoscerà in anticipo la dimensione del file.

Raccomanderei che solo per file di dimensioni molto grandi dovresti controllare in anticipo la memoria disponibile in modo da non perdere tempo a scaricare o creare un file che, ovviamente, è troppo grande da contenere. In entrambi i casi si dovrebbe sempre usare try catch quindi penso che l'unico argomento per verificare in anticipo lo spazio disponibile disponibile sia l'uso non necessario di risorse e il tempo è troppo.


Ho progettato alcune funzioni pronte all'uso per ottenere lo spazio disponibile in unità diverse. Puoi usare questi metodi semplicemente copiando qualcuno di loro nel tuo progetto.

/**
 * @return Number of bytes available on External storage
 */
public static long getAvailableSpaceInBytes() {
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();

    return availableSpace;
}


/**
 * @return Number of kilo bytes available on External storage
 */
public static long getAvailableSpaceInKB(){
    final long SIZE_KB = 1024L;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_KB;
}
/**
 * @return Number of Mega bytes available on External storage
 */
public static long getAvailableSpaceInMB(){
    final long SIZE_KB = 1024L;
    final long SIZE_MB = SIZE_KB * SIZE_KB;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_MB;
}

/**
 * @return Number of gega bytes available on External storage
 */
public static long getAvailableSpaceInGB(){
    final long SIZE_KB = 1024L;
    final long SIZE_GB = SIZE_KB * SIZE_KB * SIZE_KB;
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
    return availableSpace/SIZE_GB;
}

Prova questo codice

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount();
long megAvailable = bytesAvailable / 1048576;
System.out.println("Megs :"+megAvailable);

Da li

UPD: getBlockCount () - restituisce la dimensione della scheda SD; getAvailableBlocks () - restituisce il numero di blocchi che sono ancora accessibili ai programmi normali (grazie Joe)


public String TotalExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());   
    int Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576;

    String strI = Integer.toString(Total);
    return strI;
}

public String FreeExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
    int Free  = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576;
    String strI = Integer.toString(Free);
    return strI;
}

public String BusyExtMemory()
{
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());   
    int Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576;
    int Free  = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576;
    int Busy  = Total - Free;
    String strI = Integer.toString(Busy);
    return strI;
}

inoltre, se vuoi controllare lo spazio disponibile sulla memoria interna, usa:

File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());

...


Spero che questo codice possa aiutare gli altri. Testato funzionante bene. Grazie al membro di cui sopra per chiarirlo.

/**
 * Get the free disk available space in boolean to download requested file 
 * 
 * @return boolean value according to size availability
 */

protected static boolean isMemorySizeAvailableAndroid(long download_bytes, boolean isExternalMemory) {
    boolean isMemoryAvailable = false;
    long freeSpace = 0;

    // if isExternalMemory get true to calculate external SD card available size
    if(isExternalMemory){
        try {
            StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
            freeSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
            if(freeSpace > download_bytes){
                isMemoryAvailable = true;
            }else{
                isMemoryAvailable = false;
            }
        } catch (Exception e) {e.printStackTrace(); isMemoryAvailable = false;}
    }else{
        // find phone available size
        try {
            StatFs stat = new StatFs(Environment.getDataDirectory().getPath());
            freeSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
            if(freeSpace > download_bytes){
                isMemoryAvailable = true;
            }else{
                isMemoryAvailable = false;
            }
        } catch (Exception e) {e.printStackTrace(); isMemoryAvailable = false;}
    }

    return isMemoryAvailable;
}

Nuovi metodi sono stati introdotti dalla versione 18 dell'API.

Ho usato qualcosa di simile per la stima della dimensione della cache del disco grande (per la cache del downloader di Picasso OkHttp). Il metodo Helper era così:

private static final String BIG_CACHE_PATH = "my-cache-dir";
private static final float  MAX_AVAILABLE_SPACE_USE_FRACTION = 0.9f;
private static final float  MAX_TOTAL_SPACE_USE_FRACTION     = 0.25f;

static File createDefaultCacheDirExample(Context context) {
    File cache = new File(context.getApplicationContext().getCacheDir(), BIG_CACHE_PATH);
    if (!cache.exists()) {
        cache.mkdirs();
    }
    return cache;
}

/**
 * Calculates minimum of available or total fraction of disk space
 * 
 * @param dir
 * @return space in bytes
 */
@SuppressLint("NewApi")
static long calculateAvailableCacheSize(File dir) {
    long size = 0;
    try {
        StatFs statFs = new StatFs(dir.getAbsolutePath());
        int sdkInt = Build.VERSION.SDK_INT;
        long totalBytes;
        long availableBytes;
        if (sdkInt < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            int blockSize = statFs.getBlockSize();
            availableBytes = ((long) statFs.getAvailableBlocks()) * blockSize;
            totalBytes = ((long) statFs.getBlockCount()) * blockSize;
        } else {
            availableBytes = statFs.getAvailableBytes();
            totalBytes = statFs.getTotalBytes();
        }
        // Target at least 90% of available or 25% of total space
        size = (long) Math.min(availableBytes * MAX_AVAILABLE_SPACE_USE_FRACTION, totalBytes * MAX_TOTAL_SPACE_USE_FRACTION);
    } catch (IllegalArgumentException ignored) {
        // ignored
    }
    return size;
}

Ecco un commento dalla risposta di Steve Moseley (di ToolmakerSteve ) che mette le cose in prospettiva (in tutto onSaveInstanceState vs onPause, costi est vs saga dei costi ovest)

@VVK - Sono parzialmente in disaccordo. Alcuni modi per uscire da un'app non attivano onSaveInstanceState (oSIS). Ciò limita l'utilità di oSIS. Vale la pena supportare, per risorse OS minime, ma se un'app vuole restituire l'utente allo stato in cui si trovava, indipendentemente dall'uscita dall'app, è invece necessario utilizzare un approccio di memorizzazione permanente. Uso onCreate per verificare la presenza di bundle e, se manca, controlla la memoria permanente. Questo centralizza il processo decisionale. Posso recuperare da un arresto anomalo, uscire dal pulsante Indietro o dalla voce di menu personalizzata Esci o tornare all'utente dello schermo dopo molti giorni. - ToolmakerSteve 19 settembre 15 alle 10:38





java android