且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在Android Oreo API 26及更高版本上检查设备的存储空间是否不足

更新时间:2023-01-04 13:38:15

正如问题中正确指出的,API 26 Context#getCacheDir() 来释放应用程序缓存中的空间.

As correctly stated in the question, the API 26 Intent.ACTION_DEVICE_STORAGE_LOW is deprecated and Context#getCacheDir() is advised to be used instead to free up space from you application's cache.

此操作存在多个问题(下文列举),但首先:请注意,保持高速缓存合理小"(例如1 MB)是一种很好的做法,我引用:

There are multiple problems with this (enumerated below), but first: note that it is good practice to keep cache 'reasonably small' (e.g. 1 MB), I quote:

getCacheDir()

返回一个文件,该文件代表应用程序的临时缓存文件的内部目录.请确保在不再需要每个文件后将其删除,并对在任何给定时间使用的内存量实施合理的大小限制,例如1MB.

Returns a File representing an internal directory for your app's temporary cache files. Be sure to delete each file once it is no longer needed and implement a reasonable size limit for the amount of memory you use at any given time, such as 1MB.

警告:如果系统存储空间不足,则可能会在没有警告的情况下删除您的缓存文件.

Caution: If the system runs low on storage, it may delete your cache files without warning.

(源)

因此,这里存在三个问题:

So, there are three problems here:

  1. 我们应该清除缓存,但是它可能已经相当小(例如1 MB),因此清除缓存可能不会释放足够的空间,使空闲存储再次变为OK(类似于已弃用的因此,清除缓存似乎无济于事,所以我将不介绍如何执行此操作的详细信息.

    So, clearing the cache doesn't seem to help, so I won't go into the details of how to do that.

    但是,按照此答案,我们可以假设系统在空闲存储空间为10%时进入了我们要检测的低存储状态.根据链接的答案,这个数字是Android的默认值,但是并没有阻止设备制造商(或ROM开发人员)更改它.

    However, as per this answer, we could assume that at 10% free storage the system enters the low storage state that we want to detect. This number is Android's default, but there's little preventing a device manufacturer (or ROM developer) from changing it, according to the linked answer.

    在这一点上,对我来说,这10%是一个神奇的数字,我想知道是否可以通过编程确定该阈值.如果您知道怎么做,请编辑我的答案,自己发布答案或对我的答案发表评论.

    要使用 getCacheDir()进行此操作,可以使用以下代码:

    To do this using getCacheDir(), you could use the following:

    Java,来自 Context (例如 Activity ):

    Java, from a Context (e.g. Activity):

    File cacheDir = getCacheDir();
    if (cacheDir.getUsableSpace() * 100 / cacheDir.getTotalSpace() <= 10) { // Alternatively, use cacheDir.getFreeSpace()
      // Handle storage low state
    } else {
      // Handle storage ok state
    }
    

    科特琳,来自 Context (例如 Activity ):

    Kotlin, from a Context (e.g. Activity):

    if (cacheDir.usableSpace * 100 / cacheDir.totalSpace <= 10) { // Alternatively, use cacheDir.freeSpace
      // Handle storage low state
    } else {
      // Handle storage ok state
    }
    

    现在,是使用可用空间还是可用空间,这对我来说还不是很清楚.差异在此处进行了描述.

    Now, whether to use the usable space or free space, that's not entirely clear to me. The difference is described here.

    深入研究Android源代码后,我发现无法访问我的代码的系统服务,该服务会检查存储空间是否不足: StorageManager#getStorageLowBytes ,我都无法访问.如果这可以通过某些非骇客的方式实现,那将是获得低存储字节阈值的一种方式.在那里,您可以看到源使用 getUsableSpace(),因此这也是我为代码段选择该代码而不是 getFreeSpace()的原因.

    Diving into the Android source I found a system service, that I cannot access in my code, that checks for low storage: DeviceStorageMonitorService. It gets its lowBytes variable from StorageManager#getStorageLowBytes, which I cannot access either. If that would be possible in some non-hacky way, that would be a way to get the low storage bytes threshold. There you see the source uses getUsableSpace(), so that's why I chose that instead of getFreeSpace() too for my code snippets.