如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]

Posted

技术标签:

【中文标题】如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]【英文标题】:How to find the amount of free storage (disk space) left on Android? [duplicate] 【发布时间】:2011-10-30 05:03:09 【问题描述】:

我正在尝试找出运行我的应用程序的 android 手机上的可用磁盘空间。有没有办法以编程方式做到这一点?

谢谢,

【问题讨论】:

以重复形式关闭 - 较新的帖子可以回答 Android R 【参考方案1】:

示例:获得人类可读的大小,例如 1 Gb

字符串内存 = bytesToHuman(totalMemory())

/*************************************************************************************************
Returns size in bytes.

If you need calculate external memory, change this: 
    StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
to this: 
    StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());        
**************************************************************************************************/
    public long totalMemory()
    
        StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());   
        long   total  = (statFs.getBlockCount() * statFs.getBlockSize());
        return total;
    

    public long freeMemory()
    
        StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
        long   free   = (statFs.getAvailableBlocks() * statFs.getBlockSize());
        return free;
    

    public long busyMemory()
    
        StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());   
        long   total  = (statFs.getBlockCount() * statFs.getBlockSize());
        long   free   = (statFs.getAvailableBlocks() * statFs.getBlockSize());
        long   busy   = total - free;
        return busy;
    

将字节转换为人类可读的格式(如 1 Mb、1 Gb)

    public static String floatForm (double d)
    
       return new DecimalFormat("#.##").format(d);
    


    public static String bytesToHuman (long size)
    
        long Kb = 1  * 1024;
        long Mb = Kb * 1024;
        long Gb = Mb * 1024;
        long Tb = Gb * 1024;
        long Pb = Tb * 1024;
        long Eb = Pb * 1024;

        if (size <  Kb)                 return floatForm(        size     ) + " byte";
        if (size >= Kb && size < Mb)    return floatForm((double)size / Kb) + " Kb";
        if (size >= Mb && size < Gb)    return floatForm((double)size / Mb) + " Mb";
        if (size >= Gb && size < Tb)    return floatForm((double)size / Gb) + " Gb";
        if (size >= Tb && size < Pb)    return floatForm((double)size / Tb) + " Tb";
        if (size >= Pb && size < Eb)    return floatForm((double)size / Pb) + " Pb";
        if (size >= Eb)                 return floatForm((double)size / Eb) + " Eb";

        return "???";
    

【讨论】:

getAvailableBlocks()getBlockSize() 已被弃用并分别替换为 getAvailableBlocksLong()statFs.getBlockSizeLong() Environment.getRootDirectory() 表示您正在查询系统/操作系统分区的总、空闲和忙碌内存。要获取应用程序可用内存的统计信息,您应该查询数据分区。见***.com/a/35512682/483708。【参考方案2】:

试试StatFs.getAvailableBlocks。您需要使用 getBlockSize 将块数转换为 KB。

【讨论】:

对于 API 级别 >= 18 - StatFs.getAvailableBytes () 返回文件系统上空闲且可供应用程序使用的字节数。 getAvailableBlocks 已被 api 级别 18 弃用,新方法是 getAvailableBlocksLong【参考方案3】:

关于当前答案都没有解决的路径存在一些微妙之处。您必须根据您感兴趣的统计数据类型使用正确的路径。基于对 DeviceStorageMonitorService.java 的深入研究,它会在通知区域中生成磁盘空间不足警告以及 ACTION_DEVICE_STORAGE_LOW 的粘性广播,以下是一些路径你可以使用:

    要检查可用的内部磁盘空间,请使用通过 Environment.getDataDirectory() 获得的数据目录。这将为您提供数据分区上的可用空间。数据分区托管设备上所有应用的所有内部存储。

    要检查可用的外部 (SDCARD) 磁盘空间,请使用通过 Environment.getExternalStorageDirectory() 获得的外部存储目录。这将为您提供 SDCARD 上的可用空间。

    要检查包含操作系统文件的系统分区上的可用内存,请使用 Environment.getRootDirectory()。由于您的应用程序无法访问系统分区,因此此统计信息可能不是很有用。 DeviceStorageMonitorService 用于提供信息并将其输入日志。

    要检查临时文件/缓存内存,请使用 Environment.getDownloadCacheDirectory()。 DeviceStorageMonitorService 会在内存不足时尝试清理一些临时文件。

一些获取内部(/data)、外部(/sdcard)和操作系统(/system)空闲内存的示例代码:

// Get internal (data partition) free space
// This will match what's shown in System Settings > Storage for 
// Internal Space, when you subtract Total - Used
public long getFreeInternalMemory()

    return getFreeMemory(Environment.getDataDirectory());


// Get external (SDCARD) free space
public long getFreeExternalMemory()

    return getFreeMemory(Environment.getExternalStorageDirectory());


// Get Android OS (system partition) free space
public long getFreeSystemMemory()

    return getFreeMemory(Environment.getRootDirectory());


// Get free space for provided path
// Note that this will throw IllegalArgumentException for invalid paths
public long getFreeMemory(File path)

    StatFs stats = new StatFs(path.getAbsolutePath());
    return stats.getAvailableBlocksLong() * stats.getBlockSizeLong();

【讨论】:

你总结得很好,但是 getAvailableBlocks() 和 getBlockSize() 这两个方法都被弃用了。请更新您的答案。【参考方案4】:

根据@XXX 的回答,我创建了一个包含 StatFs 的要点代码 sn-p,以便于使用。 你可以找到它here as a GitHub gist。

【讨论】:

【参考方案5】:

在进行乘法之前将您的整数值类型转换为 long。两个大整数之间的乘法可能会溢出并给出否定结果。

public long sd_card_free()
    File path = Environment.getExternalStorageDirectory();
    StatFs stat = new StatFs(path.getPath());
    int availBlocks = stat.getAvailableBlocksLong();
    int blockSize = stat.getBlockSizeLong();
    long free_memory = (long)availBlocks * (long)blockSize;

    return free_memory;

【讨论】:

+1 这大概就是为什么getAvailableBlocks()getBlockSize()getAvailableBlocksLong()statFs.getBlockSizeLong()取代的原因。 从一开始就更好地为availBlocks和blockSize使用长变量。【参考方案6】:

用一点谷歌你可能已经找到了StatFs-class,它是:

[...] Unix statfs() 的包装器。

例如here 和这里:

import java.io.File;

import android.os.Environment;
import android.os.StatFs;

public class MemoryStatus 

    static final int ERROR = -1;

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

    static public long getAvailableInternalMemorySize() 
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();
        return availableBlocks * blockSize;
    

    static public long getTotalInternalMemorySize() 
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long totalBlocks = stat.getBlockCount();
        return totalBlocks * blockSize;
    

    static public long getAvailableExternalMemorySize() 
        if(externalMemoryAvailable()) 
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSize();
            long availableBlocks = stat.getAvailableBlocks();
            return availableBlocks * blockSize;
         else 
            return ERROR;
        
    

    static public long getTotalExternalMemorySize() 
        if(externalMemoryAvailable()) 
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSize();
            long totalBlocks = stat.getBlockCount();
            return totalBlocks * blockSize;
         else 
            return ERROR;
        
    

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

        if (size >= 1024) 
            suffix = "KiB";
            size /= 1024;
            if (size >= 1024) 
                suffix = "MiB";
                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();
    

Source for code above (Wayback Machine)

【讨论】:

第二个链接坏了 @youravgjoe 用 Wayback Machine 找回了它。【参考方案7】:
    File pathOS = Environment.getRootDirectory();//Os Storage
    StatFs statOS = new StatFs(pathOS.getPath());

    File pathInternal = Environment.getDataDirectory();// Internal Storage
  StatFs statInternal = new StatFs(pathInternal.getPath());

    File pathSdcard = Environment.getExternalStorageDirectory();//External(SD CARD) Storage
    StatFs statSdcard = new StatFs(pathSdcard.getPath());

    if((android.os.Build.VERSION.SDK_INT < 18)) 
        // Get Android OS (system partition) free space API 18 & Below
        int totalBlocksOS = statOS.getBlockCount();
        int blockSizeOS = statOS.getBlockSize();
        int availBlocksOS = statOS.getAvailableBlocks();
        long total_OS_memory = (long) totalBlocksOS * (long) blockSizeOS;
        long free_OS_memory = (long) availBlocksOS * (long) blockSizeOS;
        long Used_OS_memory = total_OS_memory - free_OS_memory;
        TotalOsMemory       =   total_OS_memory ;
        FreeOsMemory        =   free_OS_memory;
        UsedOsMemory        =   Used_OS_memory;

        // Get internal (data partition) free space API 18 & Below
        int totalBlocksInternal = statInternal.getBlockCount();
        int blockSizeInternal = statOS.getBlockSize();
        int availBlocksInternal = statInternal.getAvailableBlocks();
        long total_Internal_memory = (long) totalBlocksInternal * (long) blockSizeInternal;
        long free_Internal_memory = (long) availBlocksInternal * (long) blockSizeInternal;
        long Used_Intenal_memory = total_Internal_memory - free_Internal_memory;
        TotalInternalMemory =   total_Internal_memory;
        FreeInternalMemory  =   free_Internal_memory ;
        UsedInternalMemory  =   Used_Intenal_memory ;

        // Get external (SDCARD) free space for API 18 & Below
        int totalBlocksSdcard = statSdcard.getBlockCount();
        int blockSizeSdcard = statOS.getBlockSize();
        int availBlocksSdcard = statSdcard.getAvailableBlocks();
        long total_Sdcard_memory = (long) totalBlocksSdcard * (long) blockSizeSdcard;
        long free_Sdcard_memory = (long) availBlocksSdcard * (long) blockSizeSdcard;
        long Used_Sdcard_memory = total_Sdcard_memory - free_Sdcard_memory;
        TotalSdcardMemory   =   total_Sdcard_memory;
        FreeSdcardMemory    =   free_Sdcard_memory;
        UsedSdcardMemory    =   Used_Sdcard_memory;
    
    else 
        // Get Android OS (system partition) free space for API 18 & Above
        long   total_OS_memory          = (statOS.       getBlockCountLong()      * statOS.getBlockSizeLong());
        long   free_OS_memory           = (statOS.       getAvailableBlocksLong() * statOS.getBlockSizeLong());
        long Used_OS_memory = total_OS_memory - free_OS_memory;
        TotalOsMemory       =   total_OS_memory ;
        FreeOsMemory        =   free_OS_memory;
        UsedOsMemory        =   Used_OS_memory;

        // Get internal (data partition) free space for API 18 & Above
        long   total_Internal_memory    = (statInternal. getBlockCountLong()      * statInternal.getBlockSizeLong());
        long   free_Internal_memory     = (statInternal. getAvailableBlocksLong() * statInternal.getBlockSizeLong());
        long Used_Intenal_memory = total_Internal_memory - free_Internal_memory;
        TotalInternalMemory =   total_Internal_memory;
        FreeInternalMemory  =   free_Internal_memory ;
        UsedInternalMemory  =   Used_Intenal_memory ;

        // Get external (SDCARD) free space for API 18 & Above
        long   total_Sdcard_memory      = (statSdcard.   getBlockCountLong()      * statSdcard.getBlockSizeLong());
        long   free_Sdcard_memory       = (statSdcard.   getAvailableBlocksLong() * statSdcard.getBlockSizeLong());
        long Used_Sdcard_memory = tota*emphasized text*l_Sdcard_memory - free_Sdcard_memory;
        TotalSdcardMemory   =   total_Sdcard_memory;
        FreeSdcardMemory    =   free_Sdcard_memory;
        UsedSdcardMemory    =   Used_Sdcard_memory;
    

【讨论】:

private Long TotalOsMemory,FreeOsMemory,UsedOsMemory,TotalInternalMemory,FreeInternalMemory,UsedInternalMemory,TotalSdcardMemory,FreeSdcardMemory,UsedSdcardMemory;【参考方案8】:
/**
 * Returns the amount of free memory.
 * @return @code long - Free space.
 */
public long getFreeInternalMemory() 
    return getFreeMemory(Environment.getDataDirectory());


/**
 * Returns the free amount in SDCARD.
 * @return @code long - Free space.
 */
public long getFreeExternalMemory() 
    return getFreeMemory(Environment.getExternalStorageDirectory());


/**
 * Returns the free amount in OS.
 * @return @code long - Free space.
 */
public long getFreeSystemMemory() 
    return getFreeMemory(Environment.getRootDirectory());


/**
 * Returns the free amount in mounted path
 * @param path @link File - Mounted path.
 * @return @code long - Free space.
 */
public long getFreeMemory(File path) 
    if ((null != path) && (path.exists()) && (path.isDirectory())) 
        StatFs stats = new StatFs(path.getAbsolutePath());
        return stats.getAvailableBlocksLong() * stats.getBlockSizeLong();
    
    return -1;


/**
 * Convert bytes to human format.
 * @param totalBytes @code long - Total of bytes.
 * @return @link String - Converted size.
 */
public String bytesToHuman(long totalBytes) 
    String[] simbols = new String[] "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB";
    long scale = 1L;
    for (String simbol : simbols) 
        if (totalBytes < (scale * 1024L)) 
            return String.format("%s %s", new DecimalFormat("#.##").format((double)totalBytes / scale), simbol);
        
        scale *= 1024L;
    
    return "-1 B";

【讨论】:

【参考方案9】:

由于 blocksize 和 getAvailableBlocks

已弃用

这段代码可以用

根据 user802467 的上述回答进行注释

public long sd_card_free()
    File path = Environment.getExternalStorageDirectory();
    StatFs stat = new StatFs(path.getPath());
    long availBlocks = stat.getAvailableBlocksLong();
    long blockSize = stat.getBlockSizeLong();
    long free_memory = availBlocks * blockSize;

    return free_memory;

我们可以使用getAvailableBlocksLonggetBlockSizeLong

【讨论】:

【参考方案10】:

内存位置:

File[] roots = context.getExternalFilesDirs(null);
String path = roots[0].getAbsolutePath(); // PhoneMemory
String path = roots[1].getAbsolutePath(); // SCCard (if available)
String path = roots[2].getAbsolutePath(); // USB (if available)

用法

long totalMemory = StatUtils.totalMemory(path);
long freeMemory = StatUtils.freeMemory(path);

final String totalSpace = StatUtils.humanize(totalMemory, true);
final String usableSpace = StatUtils.humanize(freeMemory, true);

你可以用这个

public final class StatUtils 

    public static long totalMemory(String path) 
        StatFs statFs = new StatFs(path);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) 
            //noinspection deprecation
            return (statFs.getBlockCount() * statFs.getBlockSize());
         else 
            return (statFs.getBlockCountLong() * statFs.getBlockSizeLong());
        
    

    public static long freeMemory(String path) 
        StatFs statFs = new StatFs(path);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) 
            //noinspection deprecation
            return (statFs.getAvailableBlocks() * statFs.getBlockSize());
         else 
            return (statFs.getAvailableBlocksLong() * statFs.getBlockSizeLong());
        
    

    public static long usedMemory(String path) 
        long total = totalMemory(path);
        long free = freeMemory(path);
        return total - free;
    

    public static String humanize(long bytes, boolean si) 
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
        return String.format(Locale.ENGLISH, "%.1f %sB", bytes / Math.pow(unit, exp), pre);
    

【讨论】:

以上是关于如何查找 Android 上剩余的可用存储空间(磁盘空间)? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

java.io.IOException:Android 设备上没有剩余空间

使用 Phonegap,我如何检查剩余的可用磁盘空间?

如何使用 android 范围/共享存储获取可用空间?

获取 Android 上的所有总空间和可用空间

iPhone上的存储空间/高清空间通过代码

如何使用 mpdf 查找剩余页面空间