Flutter中如何获取设备完整总存储容量?
解决Flutter获取设备总存储(含系统预留)的方案
storage_space库返回的是用户可支配的总空间(排除系统预留/已占用部分),如果需要获取包含系统占用的系统识别总存储容量(更接近设备标称值),可以通过MethodChannel调用原生API实现,以下是具体步骤:
一、Flutter端代码实现
创建工具类通过MethodChannel与原生通信:
import 'package:flutter/services.dart'; class StorageUtils { static const _channel = MethodChannel('storage_capacity'); /// 获取总存储和可用存储(单位:GB) static Future<Map<String, double>> getStorageCapacity() async { final Map<String, dynamic> data = await _channel.invokeMethod('getStorage'); return { 'total': data['total'] as double, 'available': data['available'] as double, }; } }
二、Android端原生实现(Kotlin)
在MainActivity.kt中添加MethodChannel处理逻辑:
import android.os.Build import android.os.Environment import android.os.StatFs import android.os.storage.StorageManager import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "storage_capacity" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "getStorage") { result.success(getStorageData()) } else { result.notImplemented() } } } private fun getStorageData(): Map<String, Double> { val storageManager = getSystemService(STORAGE_SERVICE) as StorageManager val primaryVolume = storageManager.storageVolumes.firstOrNull { it.isPrimary } ?: return emptyMap() return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val stats = runCatching { storageManager.queryStatsForVolume(primaryVolume.uuid) }.getOrNull() ?: return emptyMap() mapOf( "total" to stats.totalBytes / (1024.0 * 1024.0 * 1024.0), "available" to stats.availableBytes / (1024.0 * 1024.0 * 1024.0) ) } else { // 兼容Android 7及以下版本 val path = primaryVolume.directory?.path ?: Environment.getExternalStorageDirectory().path val statFs = StatFs(path) val blockSize = statFs.blockSizeLong mapOf( "total" to (statFs.blockCountLong * blockSize) / (1024.0 * 1024.0 * 1024.0), "available" to (statFs.availableBlocksLong * blockSize) / (1024.0 * 1024.0 * 1024.0) ) } } }
三、iOS端原生实现(Swift)
在AppDelegate.swift中添加MethodChannel处理逻辑:
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let CHANNEL = "storage_capacity" override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler { [weak self] call, result in guard call.method == "getStorage" else { result(FlutterMethodNotImplemented) return } self?.fetchStorageInfo(result: result) } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func fetchStorageInfo(result: FlutterResult) { let fileManager = FileManager.default guard let docDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { result(FlutterError(code: "DIR_ERROR", message: "无法获取存储目录", details: nil)) return } do { let attributes = try fileManager.attributesOfFileSystem(forPath: docDir.path) let totalBytes = attributes[.systemSize] as? Int64 ?? 0 let availableBytes = attributes[.systemFreeSize] as? Int64 ?? 0 let totalGB = Double(totalBytes) / (1024 * 1024 * 1024) let availableGB = Double(availableBytes) / (1024 * 1024 * 1024) result(["total": totalGB, "available": availableGB]) } catch { result(FlutterError(code: "ATTR_ERROR", message: error.localizedDescription, details: nil)) } } }
四、使用示例
import 'package:flutter/material.dart'; import 'storage_utils.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text("存储容量测试")), body: Center( child: FutureBuilder<Map<String, double>>( future: StorageUtils.getStorageCapacity(), builder: (context, snapshot) { if (snapshot.hasData) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("总存储: ${snapshot.data!['total']?.toStringAsFixed(1)} GB"), const SizedBox(height: 16), Text("可用存储: ${snapshot.data!['available']?.toStringAsFixed(1)} GB"), ], ); } else if (snapshot.hasError) { return Text("获取失败: ${snapshot.error}"); } return const CircularProgressIndicator(); }, ), ), ), ); } }
说明
- 该方案获取的总存储是系统识别的总容量(包含系统占用空间),比如标称128GB的设备,系统识别的总容量约为119GB(厂商按1GB=1000MB计算,系统按1GB=1024MB计算),比
storage_space返回的数值更接近设备标称值。 - 若需精确获取厂商标称容量(如128GB),需读取设备硬件信息或维护设备型号-容量映射表,实现复杂度较高,一般不推荐。
- Android 10+及iOS无需额外权限即可获取存储容量。
内容的提问来源于stack exchange,提问作者Chinmay Nanaware
相关产品推荐
相关产品推荐

