Java Android-外部存储的可用空间未正确显示

Java Android-外部存储的可用空间未正确显示,java,android,storage,Java,Android,Storage,它是这样的:我正在开发一个应用程序,记录视频块。当它检测到可用空间落在某个树下时,它会尝试删除旧视频,直到可用存储量超过阈值。如果可用存储低于另一个阈值(低于第一个阈值),应用程序将停止录制并显示一个对话框,通知存储不足 我已经编写了一个类,可以帮助解决这些存储问题: package net.ghetu.dasheye; import java.io.File; import java.util.Collections; import java.util.Vector; import and

它是这样的:我正在开发一个应用程序,记录视频块。当它检测到可用空间落在某个树下时,它会尝试删除旧视频,直到可用存储量超过阈值。如果可用存储低于另一个阈值(低于第一个阈值),应用程序将停止录制并显示一个对话框,通知存储不足

我已经编写了一个类,可以帮助解决这些存储问题:

package net.ghetu.dasheye;

import java.io.File;
import java.util.Collections;
import java.util.Vector;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

class StorageManager extends Thread {

    private static final String TAG = "StorageManager";

    private static File mediaStorageDir = new File(
            Environment.getExternalStorageDirectory(), "DashEyeApp");
    private static long totalSpace = mediaStorageDir.getTotalSpace();
    private static long full99 = (long) (0.01 * totalSpace);
    private static long full97 = (long) (0.03 * totalSpace);
    private boolean isStopped = false;
    private Vector<VideoItem> directoryEntries = null;

    private GlobalState mAppState;
    private PreviewService mPreviewService;

    public void setStopped() {
        isStopped = true;
    }

    public StorageManager(Context appState, PreviewService previewService) {
        mAppState = (GlobalState) appState;
        mPreviewService = previewService;
    }

    public static boolean hasRunOutOufSpace() {
        long freeSpace = Environment.getExternalStorageDirectory()
                .getFreeSpace();
        if (freeSpace <= full99)
            return true;
        return false;
    }

    public static boolean hasLowSpace() {
        long freeSpace = new File(Environment.getExternalStorageDirectory(),
                "DashEyeApp").getFreeSpace();
        Log.d(TAG,
                "Free space: "
                        + Long.toString((long) (freeSpace / (1024 * 1024)))
                        + "MB");
        if (freeSpace <= full97)
            return true;
        return false;
    }

    @Override
    public void run() {
        super.run();
        while (!isStopped) {
            if (hasLowSpace()) {
                if (hasRunOutOufSpace()) {
                    if (mPreviewService != null) {
                        if (mAppState.isRecording()) {
                            mPreviewService.stopRecording();
                            mPreviewService.displayStorageDialog();
                            isStopped = true;
                        } else {
                            mPreviewService.displayStorageDialog();
                            isStopped = true;
                        }
                    }
                } else {
                    if (mAppState.detectLoopModeActive()) {
                        Log.d(TAG, "Making space ...");

                        directoryEntries = getAllVideos();
                        Log.d(TAG,     Integer.toString(directoryEntries.size()));

                        if (directoryEntries.size() > 1) {

                            directoryEntries.get(directoryEntries.size() - 1)
                                    .getmFile().delete();
                            directoryEntries
                                    .remove(directoryEntries.size() - 1);

                        }
                        directoryEntries.clear();
                    }
                }
            }

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private Vector<VideoItem> getAllVideos() {
        Vector<VideoItem> directoryEntries = new Vector<VideoItem>();
        File files[] = mediaStorageDir.listFiles();
        if (files != null) {
            if (files.length > 0) {
                for (File file : files) {
                    if (VideoDetector.isVideo(file))
                        directoryEntries.add(new VideoItem(file));
                }

                Collections.sort(directoryEntries,
                        VideoItem.VideoDateComparatorDesc);
            }
        }    

        files = null;
        Log.d(TAG,
                "Fetching files: " + directoryEntries.size() + " files US: "
                        + mediaStorageDir.getUsableSpace() + " FS: "
                        + mediaStorageDir.getFreeSpace());
        return directoryEntries;
    }
}
不考虑删除视频所获得的可用空间。下面是日志示例:

03-11 00:19:54.995: D/StorageManager(2863): Free space: 236MB
03-11 00:19:54.995: D/StorageManager(2863): Making space ...
03-11 00:19:55.015: D/StorageManager(2863): Fetching files: 3 files US: 248168448 FS: 248168448
03-11 00:19:55.015: D/StorageManager(2863): 3
03-11 00:20:00.015: D/StorageManager(2863): Free space: 230MB
03-11 00:20:00.015: D/StorageManager(2863): Making space ...
03-11 00:20:00.030: D/StorageManager(2863): Fetching files: 2 files US: 242081792 FS: 242081792
03-11 00:20:00.030: D/StorageManager(2863): 2
请注意,可用空间会减少,而文件夹中的视频数量也会减少。

你知道为什么会这样吗?在这一点上,我是绝望的,并愿意尝试一切。在三星Galaxy i9305上的Android 4.4.4中遇到此错误。在Galaxy S1 GT-i9000上有相同的问题,该Galaxy S1 GT-i9000带有定制的Android 4.4.4 ROM。

正如Android开发人员所说的“getFreeSpace方法返回可能可供root用户使用的字节数”。因此,如果不以root身份运行,则无法使用它。所以我有一个方法来计算可用的块字节

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

Android Doc说getFreeSpace()方法返回root用户可能可用的字节数,而getUsableSpace()返回非root用户可用的空闲字节数


您可以尝试getUsableSpace()。

Hm,是否显示不正确?那么,如果你的手机显示230MB,那么它有多少空闲空间呢?它应该有更多的空间。如果您签出日志,它首先有236MB,包含3个文件,删除一个文件后,它的大小小于这一大小(230MB)。删除文件应该会释放空间,尽管看起来不会。为什么要使用Long.toString?为什么不使用String.valueOf?也许我还不清楚:问题是getFreeSpace()返回错误的值。
public static float megabytesAvailable(File f) {
    StatFs stat = new StatFs(f.getPath());
    long bytesAvailable = (long)stat.getBlockSizeLong() * (long)stat.getAvailableBlocksLong();
    return bytesAvailable / (1024.f * 1024.f);
}