672 lines
19 KiB
Markdown
672 lines
19 KiB
Markdown
# StorageInfo 存储空间详细信息使用示例
|
||
|
||
## 新增功能说明
|
||
|
||
`StorageInfo` 类已增强,新增以下功能:
|
||
- **Apps & Data 大小**: 应用程序和用户数据占用的存储空间
|
||
- **System 大小**: 系统分区占用的存储空间
|
||
- **Free 大小**: 可用的存储空间
|
||
- **Cache 大小**: 缓存占用的存储空间
|
||
- **存储分解信息**: 详细的存储空间使用情况分析
|
||
- **存储摘要**: 格式化的完整存储信息
|
||
|
||
## 核心数据类
|
||
|
||
### StorageBreakdown
|
||
```kotlin
|
||
data class StorageBreakdown(
|
||
val totalSpace: Long, // 总空间(字节)
|
||
val usedSpace: Long, // 已使用空间(字节)
|
||
val freeSpace: Long, // 可用空间(字节)
|
||
val systemSize: Long, // 系统占用(字节)
|
||
val appsAndDataSize: Long, // 应用和数据占用(字节)
|
||
val cacheSize: Long, // 缓存占用(字节)
|
||
val otherSize: Long // 其他占用(字节)
|
||
) {
|
||
val usedPercentage: Double // 已使用百分比
|
||
val freePercentage: Double // 可用百分比
|
||
}
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
### 1. 获取基本存储信息
|
||
|
||
```kotlin
|
||
val storageInfo = StorageInfo(context)
|
||
|
||
// 直接访问属性获取大小
|
||
val appsDataSize = storageInfo.applicationsAndDataSize
|
||
println("Apps & Data: ${storageInfo.formatBytes(appsDataSize)}")
|
||
|
||
val systemSize = storageInfo.systemSize
|
||
println("System: ${storageInfo.formatBytes(systemSize)}")
|
||
|
||
val freeSpace = storageInfo.internalStorageAvailableSpace
|
||
println("Free: ${storageInfo.formatBytes(freeSpace)}")
|
||
|
||
val cacheSize = storageInfo.cacheSize
|
||
println("Cache: ${storageInfo.formatBytes(cacheSize)}")
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
Apps & Data: 18.5 GB
|
||
System: 8.2 GB
|
||
Free: 32.1 GB
|
||
Cache: 1.2 GB
|
||
```
|
||
|
||
### 2. 获取格式化的存储信息
|
||
|
||
```kotlin
|
||
val storageInfo = StorageInfo(context)
|
||
|
||
// 直接获取格式化的字符串
|
||
val appsData = storageInfo.getFormattedAppsAndDataSize()
|
||
val system = storageInfo.getFormattedSystemSize()
|
||
val free = storageInfo.getFormattedFreeSpace()
|
||
val cache = storageInfo.getFormattedCacheSize()
|
||
|
||
println("Apps & Data: $appsData")
|
||
println("System: $system")
|
||
println("Free: $free")
|
||
println("Cache: $cache")
|
||
```
|
||
|
||
### 3. 获取完整的存储分解信息
|
||
|
||
```kotlin
|
||
val storageInfo = StorageInfo(context)
|
||
|
||
// 获取详细的存储分解
|
||
val breakdown = storageInfo.getInternalStorageBreakdown()
|
||
|
||
println("=== Storage Breakdown ===")
|
||
println("Total: ${storageInfo.formatBytes(breakdown.totalSpace)}")
|
||
println("Used: ${storageInfo.formatBytes(breakdown.usedSpace)} (${String.format("%.1f%%", breakdown.usedPercentage)})")
|
||
println("Free: ${storageInfo.formatBytes(breakdown.freeSpace)} (${String.format("%.1f%%", breakdown.freePercentage)})")
|
||
println()
|
||
println("Breakdown:")
|
||
println(" System: ${storageInfo.formatBytes(breakdown.systemSize)}")
|
||
println(" Apps & Data: ${storageInfo.formatBytes(breakdown.appsAndDataSize)}")
|
||
println(" Cache: ${storageInfo.formatBytes(breakdown.cacheSize)}")
|
||
println(" Other: ${storageInfo.formatBytes(breakdown.otherSize)}")
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
=== Storage Breakdown ===
|
||
Total: 128.00 GB
|
||
Used: 85.4 GB (66.7%)
|
||
Free: 42.6 GB (33.3%)
|
||
|
||
Breakdown:
|
||
System: 8.2 GB
|
||
Apps & Data: 18.5 GB
|
||
Cache: 1.2 GB
|
||
Other: 57.5 GB
|
||
```
|
||
|
||
### 4. 获取存储使用百分比
|
||
|
||
```kotlin
|
||
val storageInfo = StorageInfo(context)
|
||
|
||
// 获取使用百分比
|
||
val usedPercentage = storageInfo.getUsagePercentage()
|
||
println("Storage Used: ${String.format("%.1f%%", usedPercentage)}")
|
||
|
||
// 获取可用百分比
|
||
val freePercentage = storageInfo.getFreePercentage()
|
||
println("Storage Free: ${String.format("%.1f%%", freePercentage)}")
|
||
|
||
// 判断存储状态
|
||
when {
|
||
usedPercentage > 90 -> println("Warning: Storage almost full!")
|
||
usedPercentage > 80 -> println("Storage is getting full")
|
||
usedPercentage > 50 -> println("Storage usage is moderate")
|
||
else -> println("Plenty of storage available")
|
||
}
|
||
```
|
||
|
||
### 5. 获取完整的存储摘要
|
||
|
||
```kotlin
|
||
val storageInfo = StorageInfo(context)
|
||
|
||
// 获取格式化的完整摘要
|
||
val summary = storageInfo.getStorageSummary()
|
||
println(summary)
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
=== Internal Storage ===
|
||
Total: 128.00 GB
|
||
Used: 85.4 GB (66.7%)
|
||
Free: 42.6 GB (33.3%)
|
||
|
||
=== Storage Breakdown ===
|
||
System: 8.2 GB
|
||
Apps & Data: 18.5 GB
|
||
Cache: 1.2 GB
|
||
Other: 57.5 GB
|
||
|
||
=== External Storage ===
|
||
Total: 256.00 GB
|
||
Used: 128.3 GB
|
||
Free: 127.7 GB
|
||
Emulated: Yes
|
||
Removable: No
|
||
|
||
=== Storage Features ===
|
||
Encrypted: Yes
|
||
Encryption Type: FBE
|
||
File System: ext4
|
||
|
||
=== Partition Scheme ===
|
||
A/B Updates: Yes
|
||
Dynamic Partitions: Yes
|
||
Virtual A/B: Yes
|
||
```
|
||
|
||
### 6. 在 Jetpack Compose 中显示存储信息
|
||
|
||
```kotlin
|
||
@Composable
|
||
fun StorageInfoCard() {
|
||
val context = LocalContext.current
|
||
val storageInfo = remember { StorageInfo(context) }
|
||
val breakdown = remember { storageInfo.getInternalStorageBreakdown() }
|
||
|
||
Card(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(16.dp),
|
||
elevation = CardDefaults.cardElevation(4.dp)
|
||
) {
|
||
Column(modifier = Modifier.padding(16.dp)) {
|
||
Text(
|
||
text = "Storage Information",
|
||
style = MaterialTheme.typography.titleLarge,
|
||
fontWeight = FontWeight.Bold
|
||
)
|
||
|
||
Spacer(modifier = Modifier.height(16.dp))
|
||
|
||
// 存储使用进度条
|
||
StorageProgressBar(
|
||
used = breakdown.usedSpace,
|
||
total = breakdown.totalSpace,
|
||
usedPercentage = breakdown.usedPercentage
|
||
)
|
||
|
||
Spacer(modifier = Modifier.height(16.dp))
|
||
|
||
// 总览
|
||
InfoSection(title = "Overview") {
|
||
InfoRow(
|
||
"Total",
|
||
storageInfo.formatBytes(breakdown.totalSpace)
|
||
)
|
||
InfoRow(
|
||
"Used",
|
||
"${storageInfo.formatBytes(breakdown.usedSpace)} (${String.format("%.1f%%", breakdown.usedPercentage)})"
|
||
)
|
||
InfoRow(
|
||
"Free",
|
||
"${storageInfo.formatBytes(breakdown.freeSpace)} (${String.format("%.1f%%", breakdown.freePercentage)})"
|
||
)
|
||
}
|
||
|
||
Spacer(modifier = Modifier.height(12.dp))
|
||
|
||
// 详细分解
|
||
InfoSection(title = "Breakdown") {
|
||
StorageBreakdownItem(
|
||
"System",
|
||
breakdown.systemSize,
|
||
breakdown.totalSpace,
|
||
Color(0xFF2196F3)
|
||
)
|
||
StorageBreakdownItem(
|
||
"Apps & Data",
|
||
breakdown.appsAndDataSize,
|
||
breakdown.totalSpace,
|
||
Color(0xFF4CAF50)
|
||
)
|
||
StorageBreakdownItem(
|
||
"Cache",
|
||
breakdown.cacheSize,
|
||
breakdown.totalSpace,
|
||
Color(0xFFFFC107)
|
||
)
|
||
StorageBreakdownItem(
|
||
"Other",
|
||
breakdown.otherSize,
|
||
breakdown.totalSpace,
|
||
Color(0xFF9E9E9E)
|
||
)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun StorageProgressBar(
|
||
used: Long,
|
||
total: Long,
|
||
usedPercentage: Double
|
||
) {
|
||
Column {
|
||
Row(
|
||
modifier = Modifier.fillMaxWidth(),
|
||
horizontalArrangement = Arrangement.SpaceBetween
|
||
) {
|
||
Text(
|
||
text = "Storage Usage",
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||
)
|
||
Text(
|
||
text = String.format("%.1f%%", usedPercentage),
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
fontWeight = FontWeight.Bold
|
||
)
|
||
}
|
||
|
||
Spacer(modifier = Modifier.height(8.dp))
|
||
|
||
LinearProgressIndicator(
|
||
progress = (usedPercentage / 100).toFloat(),
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.height(8.dp)
|
||
.clip(RoundedCornerShape(4.dp)),
|
||
color = when {
|
||
usedPercentage > 90 -> Color(0xFFF44336)
|
||
usedPercentage > 80 -> Color(0xFFFF9800)
|
||
else -> Color(0xFF4CAF50)
|
||
}
|
||
)
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun StorageBreakdownItem(
|
||
label: String,
|
||
size: Long,
|
||
total: Long,
|
||
color: Color
|
||
) {
|
||
val storageInfo = StorageInfo(LocalContext.current)
|
||
val percentage = if (total > 0) (size.toDouble() / total * 100) else 0.0
|
||
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(vertical = 4.dp),
|
||
horizontalArrangement = Arrangement.SpaceBetween,
|
||
verticalAlignment = Alignment.CenterVertically
|
||
) {
|
||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||
Box(
|
||
modifier = Modifier
|
||
.size(12.dp)
|
||
.background(color, CircleShape)
|
||
)
|
||
Spacer(modifier = Modifier.width(8.dp))
|
||
Text(
|
||
text = label,
|
||
style = MaterialTheme.typography.bodyMedium
|
||
)
|
||
}
|
||
|
||
Text(
|
||
text = "${storageInfo.formatBytes(size)} (${String.format("%.1f%%", percentage)})",
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
fontWeight = FontWeight.Medium
|
||
)
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun InfoSection(title: String, content: @Composable () -> Unit) {
|
||
Column {
|
||
Text(
|
||
text = title,
|
||
style = MaterialTheme.typography.titleMedium,
|
||
fontWeight = FontWeight.SemiBold,
|
||
color = MaterialTheme.colorScheme.primary
|
||
)
|
||
Spacer(modifier = Modifier.height(8.dp))
|
||
content()
|
||
}
|
||
}
|
||
|
||
@Composable
|
||
fun InfoRow(label: String, value: String) {
|
||
Row(
|
||
modifier = Modifier
|
||
.fillMaxWidth()
|
||
.padding(vertical = 4.dp),
|
||
horizontalArrangement = Arrangement.SpaceBetween
|
||
) {
|
||
Text(
|
||
text = label,
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||
)
|
||
Text(
|
||
text = value,
|
||
style = MaterialTheme.typography.bodyMedium,
|
||
fontWeight = FontWeight.Medium,
|
||
textAlign = TextAlign.End,
|
||
modifier = Modifier.weight(1f, fill = false)
|
||
)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7. 存储空间监控
|
||
|
||
```kotlin
|
||
class StorageMonitor(private val context: Context) {
|
||
private val storageInfo = StorageInfo(context)
|
||
|
||
/**
|
||
* 检查存储状态
|
||
*/
|
||
fun checkStorageStatus(): StorageStatus {
|
||
val freeSpace = storageInfo.internalStorageAvailableSpace
|
||
val usedPercentage = storageInfo.getUsagePercentage()
|
||
|
||
return when {
|
||
freeSpace < 1024 * 1024 * 1024 -> // < 1 GB
|
||
StorageStatus.CRITICAL
|
||
usedPercentage > 90 ->
|
||
StorageStatus.LOW
|
||
usedPercentage > 80 ->
|
||
StorageStatus.WARNING
|
||
else ->
|
||
StorageStatus.HEALTHY
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取存储建议
|
||
*/
|
||
fun getStorageRecommendation(): String {
|
||
val status = checkStorageStatus()
|
||
val cacheSize = storageInfo.cacheSize
|
||
|
||
return when (status) {
|
||
StorageStatus.CRITICAL -> {
|
||
"Critical: Storage almost full! Clear ${storageInfo.formatBytes(cacheSize)} cache immediately."
|
||
}
|
||
StorageStatus.LOW -> {
|
||
"Warning: Low storage space. Consider clearing cache or removing unused apps."
|
||
}
|
||
StorageStatus.WARNING -> {
|
||
"Storage is getting full. You may want to free up some space."
|
||
}
|
||
StorageStatus.HEALTHY -> {
|
||
"Storage is healthy. ${storageInfo.getFormattedFreeSpace()} available."
|
||
}
|
||
}
|
||
}
|
||
|
||
enum class StorageStatus {
|
||
HEALTHY, WARNING, LOW, CRITICAL
|
||
}
|
||
}
|
||
|
||
// 使用示例
|
||
val monitor = StorageMonitor(context)
|
||
val status = monitor.checkStorageStatus()
|
||
val recommendation = monitor.getStorageRecommendation()
|
||
|
||
println("Storage Status: $status")
|
||
println("Recommendation: $recommendation")
|
||
```
|
||
|
||
### 8. 计算可安装应用数量
|
||
|
||
```kotlin
|
||
fun estimateInstallableApps(context: Context): Int {
|
||
val storageInfo = StorageInfo(context)
|
||
val freeSpace = storageInfo.internalStorageAvailableSpace
|
||
|
||
// 平均应用大小约 50 MB
|
||
val averageAppSize = 50 * 1024 * 1024L
|
||
|
||
// 保留 2 GB 作为系统缓冲
|
||
val reservedSpace = 2L * 1024 * 1024 * 1024
|
||
val availableForApps = maxOf(0L, freeSpace - reservedSpace)
|
||
|
||
return (availableForApps / averageAppSize).toInt()
|
||
}
|
||
|
||
// 使用示例
|
||
val estimatedApps = estimateInstallableApps(context)
|
||
println("You can install approximately $estimatedApps more apps")
|
||
```
|
||
|
||
### 9. 存储趋势分析
|
||
|
||
```kotlin
|
||
class StorageTrendAnalyzer(private val context: Context) {
|
||
private val storageInfo = StorageInfo(context)
|
||
private val prefs = context.getSharedPreferences("storage_trend", Context.MODE_PRIVATE)
|
||
|
||
/**
|
||
* 记录当前存储使用情况
|
||
*/
|
||
fun recordCurrentUsage() {
|
||
val used = storageInfo.internalStorageUsedSpace
|
||
val timestamp = System.currentTimeMillis()
|
||
|
||
prefs.edit()
|
||
.putLong("last_used", used)
|
||
.putLong("last_timestamp", timestamp)
|
||
.apply()
|
||
}
|
||
|
||
/**
|
||
* 计算每日平均增长
|
||
*/
|
||
fun getDailyGrowth(): Long {
|
||
val currentUsed = storageInfo.internalStorageUsedSpace
|
||
val lastUsed = prefs.getLong("last_used", 0)
|
||
val lastTimestamp = prefs.getLong("last_timestamp", 0)
|
||
|
||
if (lastUsed == 0L || lastTimestamp == 0L) {
|
||
return 0L
|
||
}
|
||
|
||
val daysPassed = (System.currentTimeMillis() - lastTimestamp) / (24 * 60 * 60 * 1000)
|
||
if (daysPassed == 0L) return 0L
|
||
|
||
val growth = currentUsed - lastUsed
|
||
return growth / daysPassed
|
||
}
|
||
|
||
/**
|
||
* 预估空间耗尽时间
|
||
*/
|
||
fun estimateDaysUntilFull(): Int {
|
||
val dailyGrowth = getDailyGrowth()
|
||
if (dailyGrowth <= 0) return Int.MAX_VALUE
|
||
|
||
val freeSpace = storageInfo.internalStorageAvailableSpace
|
||
val reservedSpace = 1L * 1024 * 1024 * 1024 // 保留 1 GB
|
||
val usableSpace = maxOf(0L, freeSpace - reservedSpace)
|
||
|
||
return (usableSpace / dailyGrowth).toInt()
|
||
}
|
||
}
|
||
|
||
// 使用示例
|
||
val analyzer = StorageTrendAnalyzer(context)
|
||
analyzer.recordCurrentUsage()
|
||
|
||
val dailyGrowth = analyzer.getDailyGrowth()
|
||
val daysUntilFull = analyzer.estimateDaysUntilFull()
|
||
|
||
println("Daily Growth: ${StorageInfo(context).formatBytes(dailyGrowth)}")
|
||
if (daysUntilFull < 365) {
|
||
println("Storage will be full in approximately $daysUntilFull days")
|
||
}
|
||
```
|
||
|
||
### 10. 比较不同类别的存储占用
|
||
|
||
```kotlin
|
||
fun compareStorageCategories(context: Context) {
|
||
val storageInfo = StorageInfo(context)
|
||
val breakdown = storageInfo.getInternalStorageBreakdown()
|
||
|
||
data class CategoryInfo(val name: String, val size: Long)
|
||
|
||
val categories = listOf(
|
||
CategoryInfo("System", breakdown.systemSize),
|
||
CategoryInfo("Apps & Data", breakdown.appsAndDataSize),
|
||
CategoryInfo("Cache", breakdown.cacheSize),
|
||
CategoryInfo("Other", breakdown.otherSize)
|
||
)
|
||
|
||
// 按大小排序
|
||
val sorted = categories.sortedByDescending { it.size }
|
||
|
||
println("=== Storage Usage by Category ===")
|
||
sorted.forEachIndexed { index, category ->
|
||
val percentage = (category.size.toDouble() / breakdown.totalSpace * 100)
|
||
val bar = "█".repeat((percentage / 2).toInt().coerceIn(0, 50))
|
||
|
||
println(
|
||
"${index + 1}. ${category.name.padEnd(15)} " +
|
||
"${storageInfo.formatBytes(category.size).padStart(10)} " +
|
||
"(${String.format("%5.1f%%", percentage)}) $bar"
|
||
)
|
||
}
|
||
|
||
// 找出占用最大的类别
|
||
val largest = sorted.first()
|
||
println("\nLargest category: ${largest.name} (${storageInfo.formatBytes(largest.size)})")
|
||
}
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
=== Storage Usage by Category ===
|
||
1. Other 57.5 GB ( 44.9%) ██████████████████████
|
||
2. Apps & Data 18.5 GB ( 14.5%) ███████
|
||
3. System 8.2 GB ( 6.4%) ███
|
||
4. Cache 1.2 GB ( 0.9%)
|
||
|
||
Largest category: Other (57.5 GB)
|
||
```
|
||
|
||
## 技术细节
|
||
|
||
### 计算方法
|
||
|
||
1. **Apps & Data 大小**:
|
||
- 扫描 `/data/data` (应用数据)
|
||
- 扫描 `/data/app` (已安装应用)
|
||
- 递归计算目录大小
|
||
|
||
2. **System 大小**:
|
||
- 使用 `StatFs` 读取 `/system` 分区大小
|
||
- 包括系统应用和核心文件
|
||
|
||
3. **Cache 大小**:
|
||
- 扫描 `/data/cache` (系统缓存)
|
||
- 包括应用缓存目录
|
||
|
||
4. **Free 大小**:
|
||
- 使用 `StatFs.availableBlocksLong` 获取可用块
|
||
- 乘以块大小得到字节数
|
||
|
||
### 存储分类
|
||
|
||
- **System**: 操作系统和系统应用
|
||
- **Apps & Data**: 用户安装的应用和数据
|
||
- **Cache**: 临时文件和缓存
|
||
- **Other**: 媒体文件、下载等其他内容
|
||
|
||
## 注意事项
|
||
|
||
1. **权限**:
|
||
- 基本存储信息无需特殊权限
|
||
- 某些目录可能因权限限制无法访问
|
||
|
||
2. **性能**:
|
||
- 计算目录大小是耗时操作
|
||
- 建议在后台线程执行
|
||
- 考虑缓存结果
|
||
|
||
3. **精确度**:
|
||
- 由于权限限制,某些大小可能不完全精确
|
||
- 系统文件和隐藏文件可能未计入
|
||
|
||
4. **存储单位**:
|
||
- 1 KB = 1024 bytes
|
||
- 1 MB = 1024 KB
|
||
- 1 GB = 1024 MB
|
||
|
||
5. **兼容性**:
|
||
- 支持 Android 5.0 (API 21) 及以上
|
||
- 某些特性需要更高 API 级别
|
||
|
||
## 性能优化建议
|
||
|
||
### 异步加载
|
||
|
||
```kotlin
|
||
// 在协程中加载
|
||
lifecycleScope.launch(Dispatchers.IO) {
|
||
val storageInfo = StorageInfo(context)
|
||
val breakdown = storageInfo.getInternalStorageBreakdown()
|
||
|
||
withContext(Dispatchers.Main) {
|
||
// 更新 UI
|
||
updateStorageUI(breakdown)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 缓存结果
|
||
|
||
```kotlin
|
||
class CachedStorageInfo(context: Context) {
|
||
private val storageInfo = StorageInfo(context)
|
||
private var cachedBreakdown: StorageBreakdown? = null
|
||
private var lastUpdateTime: Long = 0
|
||
|
||
fun getBreakdown(forceRefresh: Boolean = false): StorageBreakdown {
|
||
val now = System.currentTimeMillis()
|
||
val cacheExpired = now - lastUpdateTime > 5 * 60 * 1000 // 5 分钟
|
||
|
||
if (cachedBreakdown == null || cacheExpired || forceRefresh) {
|
||
cachedBreakdown = storageInfo.getInternalStorageBreakdown()
|
||
lastUpdateTime = now
|
||
}
|
||
|
||
return cachedBreakdown!!
|
||
}
|
||
}
|
||
```
|
||
|
||
## 常见应用场景
|
||
|
||
1. **存储管理应用**: 显示详细的存储使用情况
|
||
2. **清理工具**: 识别可清理的缓存和临时文件
|
||
3. **应用市场**: 检查是否有足够空间安装应用
|
||
4. **备份工具**: 评估备份所需空间
|
||
5. **文件管理器**: 提供存储概览
|
||
6. **设置应用**: 显示系统存储信息
|
||
7. **性能监控**: 跟踪存储趋势
|
||
8. **用户提醒**: 低存储空间警告
|