DevCheck-lib/StorageInfo使用示例.md
2025-12-29 11:39:18 +08:00

672 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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. **用户提醒**: 低存储空间警告