Android获得内部/外部内存的免费大小

时间:2011-11-15 08:28:53

标签: android android-sdcard diskspace

我想以编程方式获取设备内部/外部存储空闲内存的大小。我正在使用这段代码:

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

我得到的结果是:

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

问题是我想获得SdCard的免费记忆,现在是1,96GB。如何修复此代码,以便获得免费大小?

13 个答案:

答案 0 :(得分:166)

以下是您的目的代码:

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

获取RAM大小

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

答案 1 :(得分:35)

这就是我这样做的方式:

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 :(得分:24)

从API 9开始,您可以:

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

答案 3 :(得分:21)

要获取所有可用的存储文件夹(包括SD卡),首先要获取存储文件:

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

然后你可以得到每个的可用大小。

有三种方法可以做到:

API 8及以下:

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

API 9及以上版本:

long availableSizeInBytes=file.getFreeSpace();

API 18及以上(如果前一个没问题则不需要):

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

要获得一个很好的格式化字符串,您可以使用:

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

或者您可以使用它,以防您希望查看确切的字节数但很好:

NumberFormat.getInstance().format(availableSizeInBytes);

请注意,我认为内部存储可能与第一个外部存储相同,因为第一个是模拟的存储。

答案 4 :(得分:9)

@Android-Droid - 你错了Environment.getExternalStorageDirectory()指向外部存储器,它不一定是SD卡,也可以是内部存储器的挂载。参见:

Find an external SD card location

答案 5 :(得分:6)

如果您获得内部存储路径和外部存储路径,则很容易找到可用的存储空间。手机的外部存储路径也非常容易找到

  

Environment.getExternalStorageDirectory()的getPath();

所以我只专注于如何找到外部可移动存储的路径,如可移动SD卡,USB OTP(未测试USB OTG,因为我没有USB OTG)。

下面的方法将列出所有可能的外部可移动存储路径。

type

答案 6 :(得分:6)

试试这个简单的代码段

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

答案 7 :(得分:3)

快速添加到外部存储器主题

不要对Dinesh Prajapati的答案中的方法名externalMemoryAvailable()感到困惑。

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())为您提供内存的当前状态,如果介质存在并以其读/写访问权限挂载在其挂载点。 即使在没有SD卡的设备上,你也会获得true,例如Nexus 5.但在使用存储操作之前,它仍然是一种“必备”方法。

要检查设备上是否有SD卡,您可以使用方法ContextCompat.getExternalFilesDirs()

它不会显示瞬态设备,例如USB闪存驱动器。

另请注意,Android 4.3及更低版本的ContextCompat.getExternalFilesDirs() 始终仅返回1个条目(如果SD卡可用,则为内部)。您可以阅读更多相关信息here

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

在我的情况下这已经足够了,但不要忘记一些Android设备可能有2张SD卡,所以如果你需要所有这些 - 请调整上面的代码。

答案 8 :(得分:1)

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

StorageStatsManager类引入了Android O及更高版本,可以为您提供外部/内部存储中的可用字节和总字节。有关源代码的详细信息,您可以阅读我的以下文章。您可以使用反射低于Android O的方式

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

答案 9 :(得分:0)

关于外部理论,还有另一种方式:
File external = Environment.getExternalStorageDirectory(); free:external.getFreeSpace(); total:external.getTotalSpace();

答案 10 :(得分:0)

这就是我做到的方式。

内部总内存

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

内部自由尺寸

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

外部可用内存和总内存

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

答案 11 :(得分:0)

我自己检查了不同的解决方案后,编写了完整的代码来查找

  • 外部存储器总数
  • 免费的外部存储器
  • 已用外部存储器
  • TotaL内部存储器
  • 已使用的内部存储器
  • 内部可用内存

''''

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

}}

答案 12 :(得分:0)

此处提到的解决方案均不能用于外部存储器。这是我的代码(用于RAM,ROM,系统存储和外部存储)。您可以使用(总存储空间-已用存储空间)来计算可用存储空间。而且,一定不能使用Environment.getExternalStorageDirectory()进行外部存储。它不一定指向外部SD卡。此外,该解决方案还可以与所有Android版本一起使用(已在真实设备和仿真器上针对API 16-30进行了测试)。

    // Divide by (1024*1024*1024) to get in GB, by (1024*1024) to get in MB, by 1024 to get in KB..

    // RAM
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    manager.getMemoryInfo(memoryInfo);
    long totalRAM=memoryInfo.totalMem;
    long availRAM=memoryInfo.availMem;  // remember to convert in GB,MB or KB.
    long usedRAM=totalRAM-availRAM;

    // ROM
    getTotalStorageInfo(Environment.getDataDirectory().getPath());
    getUsedStorageInfo(Environment.getDataDirectory().getPath());

    // System Storage
    getTotalStorageInfo(Environment.getRootDirectory().getPath());
    getUsedStorageInfo(Environment.getRootDirectory().getPath());

    // External Storage (SD Card)
    File[] files = ContextCompat.getExternalFilesDirs(context, null);
    if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.JELLY_BEAN_MR2){
        if (files.length == 1) {
            Log.d("External Storage Memory","is present");
            getTotalStorageInfo(files[0].getPath());
            getUsedStorageInfo(files[0].getPath());
        }
    } else {
        if (files.length > 1 && files[0] != null && files[1] != null) {
            Log.d("External Storage Memory","is present");
            long t=getTotalStorageInfo(files[1].getPath());
            long u=getUsedStorageInfo(files[1].getPath());
            System.out.println("Total External Mem: "+t+" Used External Mem: "+u+" Storage path: "+files[1].getPath());
        }
    }
}

public long getTotalStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long t;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        t = statFs.getTotalBytes();
    } else {
        t = statFs.getBlockCount() * statFs.getBlockCount();
    }
    return t;    // remember to convert in GB,MB or KB.
}

public long getUsedStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long u;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        u = statFs.getTotalBytes() - statFs.getAvailableBytes();
    } else {
        u = statFs.getBlockCount() * statFs.getBlockSize() - statFs.getAvailableBlocks() * statFs.getBlockSize();
    }
    return u;  // remember to convert in GB,MB or KB.
}

现在对于ROM,我已将路径用作“ / data”,对于系统存储路径,将其用作“ / system”。对于外部存储,我使用了ContextCompat.getExternalFilesDirs(context, null);,因此它也可以在Android Q和Android R上运行。希望对您有帮助。