You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:34:56