How to check if the device has Low Storage on Android Oreo API 26 and Above

不问归期 提交于 2020-12-29 13:23:08

问题


How can I check if the device has low storage on Android 8 Oreo. I saw in the Android Documentation that the Intent.ACTION_DEVICE_STORAGE_LOW is deprecated in API 26.

This constant was deprecated in API level 26. if your app targets O or above, this broadcast will no longer be delivered to any BroadcastReceiver defined in your manifest. Instead, apps are strongly encouraged to use the improved getCacheDir() behavior so the system can automatically free up storage when needed. - Android Documentation

They are encouraging me use getCacheDir() instead.

But I don't understand much of it, as getCacheDir() seems to return the system cache directory path as a FILE object, which can only be used to clear cache or some such.

But I need to check whether the device is running low on device storage. I hope someone will help me in this


回答1:


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.

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

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.

(source)

So, there are three problems here:

  1. We should clear the cache, but it is probably already reasonably small (e.g. 1 MB), so clearing it will probably not free enough space for the free storage to become OK again (similar to the also deprecated Intent.ACTION_DEVICE_STORAGE_OK that previously could be used for this)
  2. As quoted, the cache quite possibly has already been cleared by the system, because the storage is low and the system may clear your application's cache if it so decides. Therefore, clearing it yourself possibly does not free up any storage.
  3. The documentation does not specify at all how to actually detect if the device is low on storage.

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

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.

At this point, to me, this 10% is a magic number and I'd like to know if I can determine this threshold programmatically. If you know how, please edit my answer, post an answer yourself or comment on my answer.

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

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
}

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.

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.




回答2:


Answered by greenapps in the comments:

Once getCacheDir() delivered the path to the used storage you can use that path to determine size and free space of that 'partition'

getCacheDir() delivers a directory in internal storage



来源:https://stackoverflow.com/questions/47310419/how-to-check-if-the-device-has-low-storage-on-android-oreo-api-26-and-above

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!