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

And*_*oid 89 android diskspace android-sdcard

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

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);
Run Code Online (Sandbox Code Playgroud)

而我得到的结果是:

11-15 10:27:18.844: E/(25822): Available MB : 7572
11-15 10:27:18.844: E/(25822): Format : 869MB
Run Code Online (Sandbox Code Playgroud)

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

Din*_*ati 172

以下是您的目的代码:

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();
    }
Run Code Online (Sandbox Code Playgroud)

获取RAM大小

ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;
Run Code Online (Sandbox Code Playgroud)

  • 不推荐使用`getBlockSize()`和`getBlockCount`. (2认同)
  • @DineshPrajapati感谢您的回答,我有查询,如果我使用Environment.getRootDirectory()而不是Environment.getDataDirectory来计算内部存储,我得到一些输出..这是指内部存储器其他内存.. (2认同)
  • @DineshPrajapati ..在MOTO G2上进行测试获取外部存储的错误数据 (2认同)

And*_*oid 38

这就是我这样做的方式:

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);
Run Code Online (Sandbox Code Playgroud)

  • 只需用`getBlockSizeLong`和`getAvailableBlocksLong`替换`getBlockSize`和`getAvailableBlocks`. (3认同)
  • 但这是贬低的:( (2认同)

Tzo*_*ker 26

从API 9开始,您可以:

long freeBytesInternal = new File(ctx.getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();
Run Code Online (Sandbox Code Playgroud)

  • File.getUsableSpace() 可能更好,因为您可能不是以 root 身份运行。 (2认同)
  • @DiscoS2 如果您的 minSdkVersion 小于 9,您将使用 StatFs。 (2认同)

and*_*per 23

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

File internalStorageFile=getFilesDir();
File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);
Run Code Online (Sandbox Code Playgroud)

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

有3种方法可以做到:

API 8及以下:

StatFs stat=new StatFs(file.getPath());
long availableSizeInBytes=stat.getBlockSize()*stat.getAvailableBlocks();
Run Code Online (Sandbox Code Playgroud)

API 9及以上版本:

long availableSizeInBytes=file.getFreeSpace();
Run Code Online (Sandbox Code Playgroud)

API 18及更高版本(如果前一个没问题则不需要):

long availableSizeInBytes=new StatFs(file.getPath()).getAvailableBytes(); 
Run Code Online (Sandbox Code Playgroud)

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

String formattedResult=android.text.format.Formatter.formatShortFileSize(this,availableSizeInBytes);
Run Code Online (Sandbox Code Playgroud)

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

NumberFormat.getInstance().format(availableSizeInBytes);
Run Code Online (Sandbox Code Playgroud)

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


小智 9

@Android-Droid - 你错误的Environment.getExternalStorageDirectory()指向外部存储器,它不必是SD卡,它也可以是内部存储器的挂载.看到:

查找外部SD卡位置


小智 7

试试这个简单的片段

    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];
}
Run Code Online (Sandbox Code Playgroud)


Sme*_*eet 6

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

Environment.getExternalStorageDirectory()的getPath();

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

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

 /**
     * 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;
}
Run Code Online (Sandbox Code Playgroud)


Kir*_*zin 5

快速添加外部存储器主题

不要被方法名所迷惑 externalMemoryAvailable()Dinesh Prajapati 回答中。

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())为您提供内存的当前状态,如果介质存在并安装在具有读/写访问权限的安装点。你会得到true甚至可以使用没有 SD 卡的设备,例如 Nexus 5。但在任何存储操作之前,它仍然是“必备”方法。

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

它不显示临时设备,例如 USB 闪存驱动器。

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

  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;
}
Run Code Online (Sandbox Code Playgroud)

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


小智 5

这就是我这样做的方式..

内部总内存

double totalSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getTotalSpace();
double totMb = totalSize / (1024 * 1024);
Run Code Online (Sandbox Code Playgroud)

内部均码

 double availableSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
    double freeMb = availableSize/ (1024 * 1024);
Run Code Online (Sandbox Code Playgroud)

外部可用内存和总内存

 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";
Run Code Online (Sandbox Code Playgroud)

  • 您的方法显示我总共 50 GB 中有 29 GB 可用空间。但是,我的标准文件应用程序(华为 P20 Lite)和 Google 的文件应用程序显示总共 64 GB 的空间中有 32 GB 可用。我是否遗漏了某些内容,或者您​​的方法是否从存储中排除了某些内容? (4认同)

Mru*_*ora 5

这里提到的解决方案都不能用于外部存储器。这是我的代码(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.getBlockSize();
    }
    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.
}
Run Code Online (Sandbox Code Playgroud)

现在,对于 ROM,我使用的路径为“/data”,对于系统存储,路径为“/system”。对于外部存储,我已经使用过ContextCompat.getExternalFilesDirs(context, null);,因此它也适用于 Android Q 和 Android R。我希望这能帮到您。