Flutter: 使用Dart检查设备可用存储空间

huangapple go评论67阅读模式
英文:

Flutter: Check Device Available Storage using Dart

问题

如何检查设备存储是否足够,是否可以在Flutter中实现而无需本地操作?我想知道设备是否有足够的存储空间来下载图片。如何实现这一点?

英文:

How to check device storage is it possible to do it in Flutter without doing natively? I want to know if the device has enough storage to download images. How to achieve this?

答案1

得分: 15

有一个名为disk_space的包,允许您获取您要查找的确切信息。您可以像这样使用它:

import 'package:disk_space/disk_space.dart';

void getDiskSpaceInfo() async{
  print(await DiskSpace.getFreeDiskSpace);
  print(await DiskSpace.getTotalDiskSpace);
}

编辑:此包已于2021年3月9日升级到Dart 2.12的版本0.1.0+2。但仍然没有GitHub链接。

英文:

There is a package called disk_space that allows you to get exactly the information you are looking for. You can use it like this:

import 'package:disk_space/disk_space.dart';

void getDiskSpaceInfo() async{
  print(await DiskSpace.getFreeDiskSpace);
  print(await DiskSpace.getTotalDiskSpace);
}

EDIT: This package has been updated to version 0.1.0+2 for Dart 2.12 on Mar 9, 2021. But still has no link to GitHub.

答案2

得分: 4

我已经为您翻译了您提供的代码部分,如下所示:

一个可能性是使用已经提到的 `DiskSpace` 并稍作更改。

该库包含两个文件:
-------------------------------

`disk_space.dart`:
```dart
import 'dart:async';

import 'package:flutter/services.dart';

class DiskSpace {
  static const MethodChannel _channel =
      const MethodChannel('disk_space');

  static Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static Future<double?> get getFreeDiskSpace async {
    final double? freeDiskSpace = await _channel.invokeMethod('getFreeDiskSpace');
    return freeDiskSpace;
  }

  static Future<double?> get getTotalDiskSpace async {
    final double? totalDiskSpace = await _channel.invokeMethod('getTotalDiskSpace');
    return totalDiskSpace;
  }
}

DiskSpacePlugin.kt:

package de.appgewaltig.disk_space

import android.os.Environment
import android.os.StatFs
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar

class DiskSpacePlugin: MethodCallHandler {
  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "disk_space")
      channel.setMethodCallHandler(DiskSpacePlugin())
    }
  }

  private fun getFreeDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.availableBlocks.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

  private fun getTotalDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.blockCountLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.blockCount.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }


  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method) {
      "getFreeDiskSpace" -> result.success(getFreeDiskSpace())
      "getTotalDiskSpace" -> result.success(getTotalDiskSpace())
      else -> result.notImplemented()
    }
  }
}

我的更改:

我已经添加了另一个通道方法(并在KT文件中添加了一个用于获取内部存储的方法):

class DiskSpacePlugin: MethodCallHandler {
  ...

  private fun getFreeDiskSpace(path: String): Double {
    val stat = StatFs(path) // 动态路径来自Flutter

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.availableBlocks.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

  private fun getFreeInternalDiskSpace(): Double {
    val stat = StatFs(Environment.getDataDirectory().path) // 更改为获取内部目录
    ...
  }

  private fun getFreeExternalDiskSpace(): Double {...} // 更改名称以反映外部目录

  private fun getTotalDiskSpace(): Double {...}


  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method) {
      "getFreeDiskSpace" -> {
        var path = call.argument("path") as String
        result.success(getFreeDiskSpace(path)) // 添加了这个
      }
      "getFreeInternalDiskSpace" -> result.success(getFreeInternalDiskSpace())
      "getFreeExternalDiskSpace" -> result.success(getFreeExternalDiskSpace())
      "getTotalDiskSpace" -> result.success(getTotalDiskSpace())
      else -> result.notImplemented()
    }
  }
}

FlutterActivity 中注册了插件:

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);

    DiskSpacePlugin.registerWith(registrarFor("<your_package>.DiskSpacePlugin"));
  }
}

添加了一个 Storage 辅助类:

import 'dart:io';

import 'package:path_provider/path_provider.dart';

class Storage {
  static Future<Directory> internal() async {
    return getApplicationDocumentsDirectory();
  }
  
  static Future<Directory> external() async {
    return getExternalStorageDirectory();
  }

  static Future<Directory> sdCard() async {
    return (await getExternalStorageDirectories()).firstWhere(
      (directory) => !directory.path.contains("emulated"),
      orElse: () => null,
    );
  }
}

现在您可以从Dart代码中调用这些方法:

static const MethodChannel _channel = const MethodChannel('disk_space');

void getFreeMemory() async {
  final String internal = (await Storage.internal()).path;
  final String external = (await Storage.external()).path;
  final String sdCard = (await Storage.sdCard()).path;

  final double freeDiskSpace = await _channel.invokeMethod('getFreeDiskSpace', {"path": internal});
  final double freeExternalDiskSpace = await _channel.invokeMethod('getFreeDiskSpace', {"path": external});
  if (sdCard != null) {
    final double freeSdCardSpace = await _channel.invokeMethod('getFreeDiskSpace', {"path": sdCard});
  }
}

PS:如果有人与DiskSpace库的开发者有联系,您可以询问他是否愿意将所提到的内容添加到库中。谢谢!

英文:

One of the possibilities is to use already mentioned DiskSpace with a bit of a change.

The library contains two files:

disk_space.dart:

import &#39;dart:async&#39;;

import &#39;package:flutter/services.dart&#39;;

class DiskSpace {
  static const MethodChannel _channel =
      const MethodChannel(&#39;disk_space&#39;);

  static Future&lt;String?&gt; get platformVersion async {
    final String? version = await _channel.invokeMethod(&#39;getPlatformVersion&#39;);
    return version;
  }

  static Future&lt;double?&gt; get getFreeDiskSpace async {
    final double? freeDiskSpace = await _channel.invokeMethod(&#39;getFreeDiskSpace&#39;);
    return freeDiskSpace;
  }

  static Future&lt;double?&gt; get getTotalDiskSpace async {
    final double? totalDiskSpace = await _channel.invokeMethod(&#39;getTotalDiskSpace&#39;);
    return totalDiskSpace;
  }
}

and

DiskSpacePlugin.kt:

package de.appgewaltig.disk_space

import android.os.Environment
import android.os.StatFs
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar

class DiskSpacePlugin: MethodCallHandler {
  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), &quot;disk_space&quot;)
      channel.setMethodCallHandler(DiskSpacePlugin())
    }
  }

  private fun getFreeDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.availableBlocks.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

  private fun getTotalDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.blockCountLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.blockCount.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }


  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method) {
      &quot;getFreeDiskSpace&quot; -&gt; result.success(getFreeDiskSpace())
      &quot;getTotalDiskSpace&quot; -&gt; result.success(getTotalDiskSpace())
      else -&gt; result.notImplemented()
    }
  }
}

My changes:

I've added another channel method (and a method to the KT file to get internal storage):

class DiskSpacePlugin: MethodCallHandler {
  ...

  private fun getFreeDiskSpace(String path): Double {
    val stat = StatFs(path) // dynamic path from the Flutter

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.availableBlocks.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

  private fun getFreeInternalDiskSpace(): Double {
    val stat = StatFs(Environment.getDataDirectory().path) // changed to get internal directory
    ...
  }

  private fun getFreeExternalDiskSpace(): Double {...} // Changed name to reflect external directory

  private fun getTotalDiskSpace(): Double {...}


  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method) {
      &quot;getFreeDiskSpace&quot; -&gt; {
        var path = call.argument(&quot;path&quot;) as String
        result.success(getFreeDiskSpace(path)) // added this
      }
      &quot;getFreeInternalDiskSpace&quot; -&gt; result.success(getFreeInternalDiskSpace())
      &quot;getFreeExternalDiskSpace&quot; -&gt; result.success(getFreeExternalDiskSpace())
      &quot;getTotalDiskSpace&quot; -&gt; result.success(getTotalDiskSpace())
      else -&gt; result.notImplemented()
    }
  }
}

Registered the Plugin in the FlutterActivity:

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);

    DiskSpacePlugin.registerWith(registrarFor(&quot;&lt;your_package&gt;.DiskSpacePlugin&quot;));
  }
}

Added a Storage helper:

import &#39;dart:io&#39;;

import &#39;package:path_provider/path_provider.dart&#39;;

class Storage {
  static Future&lt;Directory&gt; internal() async {
    return getApplicationDocumentsDirectory();
  }
  
  static Future&lt;Directory&gt; external() async {
    return getExternalStorageDirectory();
  }

  static Future&lt;Directory&gt; sdCard() async {
    return (await getExternalStorageDirectories()).firstWhere(
      (directory) =&gt; !directory.path.contains(&quot;emulated&quot;),
      orElse: () =&gt; null,
    );
  }
}

And now you can call these from the dart code:

static const MethodChannel _channel = const MethodChannel(&#39;disk_space&#39;);

void getFreeMemory() async {
  final String internal = (await Storage.internal()).path;
  final String external = (await Storage.external()).path;
  final String sdCard = (await Storage.sdCard()).path;

  final double freeDiskSpace = await _channel.invokeMethod(&#39;getFreeDiskSpace&#39;, {&quot;path&quot;: internal});
  final double freeExternalDiskSpace = await _channel.invokeMethod(&#39;getFreeDiskSpace&#39;, {&quot;path&quot;: external});
  if (sdCard != null) {
    final double freeSdCardSpace = await _channel.invokeMethod(&#39;getFreeDiskSpace&#39;, {&quot;path&quot;: sdCard});
  }
}

PS: If someone has a contact to the DiskSpace lib developer - what if ask him to add something mentioned to the library? thx

答案3

得分: 0

以下是翻译好的部分:

"扩展存储空间的测试是"

"private fun getFreeDiskSpace(): Double {"
"private fun getTotalDiskSpace(): Double {"

英文:

The test is to expand the storage space

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

  private fun getFreeDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.availableBlocksLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.availableBlocks.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

  private fun getTotalDiskSpace(): Double {
    val stat = StatFs(Environment.getExternalStorageDirectory().path)

    var bytesAvailable: Long

    if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
      bytesAvailable = stat.blockSizeLong * stat.blockCountLong
    else
      bytesAvailable = stat.blockSize.toLong() * stat.blockCount.toLong()
    return (bytesAvailable / (1024f * 1024f)).toDouble()
  }

<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月6日 21:50:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定