Android - 外部存储的可用空间无法正确显示

时间:2015-03-10 22:44:39

标签: java android storage

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

我写过一个应该帮助解决这些存储问题的课程:

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;
    }
}
然而,我的课对我没有帮助。会发生什么:视频被删除但hasLowSpace()仍然返回true。 I. e。

long freeSpace = new File(Environment.getExternalStorageDirectory(),
                "DashEyeApp").getFreeSpace();

不考虑删除视频所获得的可用空间。下面是日志的样本:

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中的这个错误。在带有自定义Android 4.4.4 ROM的Galaxy S1 GT-i9000上遇到同样的问题。

2 个答案:

答案 0 :(得分:1)

正如android开发人员所说&#34; getFreeSpace方法返回root&#34;可能可用的字节数。因此,如果不以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);
}

答案 1 :(得分:0)

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

您可以试试getUsableSpace()。