如何获取设备总存储与可用存储信息?disk_space包数值不准确求助
解决disk_space包存储数值不准确问题:获取设备存储信息的可靠实现
disk_space包(v0.2.1)的数值不准确,通常是因为它未处理平台差异、权限限制或系统预留空间的计算逻辑问题。以下是基于path_provider和原生API的替代方案,能更精准获取总存储空间、可用空间及已用空间:
方案一:Flutter跨平台基础实现(沙盒/外部存储)
依赖path_provider访问对应平台的存储目录,结合dart:io的FileSystemStat获取准确的存储数据。
步骤1:添加依赖
在pubspec.yaml中添加:
dependencies: path_provider: ^2.0.15 permission_handler: ^10.2.0 # 用于Android权限请求
步骤2:实现存储信息获取方法
import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; Future<Map<String, int>> getStorageDetails() async { // Android需先请求存储权限 if (Platform.isAndroid) { final status = await Permission.storage.request(); if (!status.isGranted) { return {'total': 0, 'available': 0, 'used': 0}; } } Directory? targetDir; try { if (Platform.isAndroid) { // 访问Android外部存储根目录(对应手机内置存储) targetDir = Directory('/storage/emulated/0'); } else if (Platform.isIOS) { // iOS仅能访问应用沙盒目录,若需全局存储见方案二 targetDir = await getApplicationDocumentsDirectory(); } if (targetDir != null && await targetDir.exists()) { final stat = await targetDir.stat(); final usedSpace = stat.totalSpace - stat.availableSpace; return { 'total': stat.totalSpace, // 总存储空间(字节) 'available': stat.availableSpace, // 应用可使用的可用空间(字节) 'used': usedSpace // 已用空间(字节) }; } } catch (e) { print('获取存储信息失败: $e'); } return {'total': 0, 'available': 0, 'used': 0}; }
权限配置(Android)
在android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 若需访问公共媒体文件,添加对应媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
方案二:iOS全局存储信息获取(原生Channel)
iOS应用默认只能访问沙盒,若需获取整个设备的存储数据,需通过MethodChannel调用原生代码:
Flutter端Channel代码
import 'dart:async'; import 'dart:io'; import 'package:flutter/services.dart'; static const MethodChannel _storageChannel = MethodChannel('com.example/storage_info'); Future<Map<String, int>> getIOSGlobalStorage() async { try { final total = await _storageChannel.invokeMethod<int>('getTotalStorage') ?? 0; final available = await _storageChannel.invokeMethod<int>('getAvailableStorage') ?? 0; return { 'total': total, 'available': available, 'used': total - available }; } on PlatformException catch (e) { print('原生调用失败: ${e.message}'); return {'total': 0, 'available': 0, 'used': 0}; } }
iOS原生代码(Swift)
在Runner/ViewController.swift中添加:
import UIKit import Flutter class StorageInfoHandler: NSObject, FlutterPlugin { static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "com.example/storage_info", binaryMessenger: registrar.messenger()) let instance = StorageInfoHandler() registrar.addMethodCallDelegate(instance, channel: channel) } func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "getTotalStorage": result(getTotalDeviceStorage()) case "getAvailableStorage": result(getAvailableDeviceStorage()) default: result(FlutterMethodNotImplemented) } } private func getTotalDeviceStorage() -> Int64 { let url = URL(fileURLWithPath: NSHomeDirectory()) do { let attrs = try url.resourceValues(forKeys: [.volumeTotalCapacityKey]) return attrs.volumeTotalCapacity ?? 0 } catch { return 0 } } private func getAvailableDeviceStorage() -> Int64 { let url = URL(fileURLWithPath: NSHomeDirectory()) do { let attrs = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]) return attrs.volumeAvailableCapacityForImportantUsage ?? 0 } catch { return 0 } } }
然后在Runner/AppDelegate.swift中注册Channel:
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { StorageInfoHandler.register(with: self.registrar(forPlugin: "StorageInfoHandler")) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }
为什么disk_space包不准确?
- 未区分系统预留空间和应用实际可用空间:部分系统级存储(如系统分区、缓存)不会开放给应用,但disk_space可能直接返回磁盘总容量,导致可用空间计算偏差。
- 平台挂载点处理错误:Android的外部存储路径可能因设备而异,旧版包未适配不同厂商的存储路径。
- 权限适配不足:未处理Android 13+的媒体权限变更,导致无法正确读取存储数据。
内容的提问来源于stack exchange,提问作者Noob Developer
相关产品推荐
相关产品推荐

