7

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?

3 Answers 3

21

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.

Sign up to request clarification or add additional context in comments.

7 Comments

I've tested it on iOS and Android and it works in both. If an answer solves your issue, please mark it as correct
@RodrigoHenriques The documentation doesn't state, but I believe it is bytes, yes.
@JoãoSoares after double checking the source code I saw that the value is in megabytes. If you look at the plugin native code you can see for yourself.
@JoãoSoares I would like to ask, did you know that DiskSpace.getTotalDiskSpace was accessing internal storage only or with sd card storage?... I try to implement it to my project, but I get different result when comparing with space in my phone
@uyhaW Sorry, I am not aware of the actual implementation. I haven't been able to find the GitHub page of that package, and it also hasn't been updated since November 2019.
|
4

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 '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;
  }
}

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(), "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()
    }
  }
}

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 >= 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) {
      "getFreeDiskSpace" -> {
        var path = call.argument("path") as String
        result.success(getFreeDiskSpace(path)) // added this
      }
      "getFreeInternalDiskSpace" -> result.success(getFreeInternalDiskSpace())
      "getFreeExternalDiskSpace" -> result.success(getFreeExternalDiskSpace())
      "getTotalDiskSpace" -> result.success(getTotalDiskSpace())
      else -> 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("<your_package>.DiskSpacePlugin"));
  }
}

Added a Storage helper:

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,
    );
  }
}

And now you can call these from the dart code:

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: If someone has a contact to the DiskSpace lib developer - what if ask him to add something mentioned to the library? thx

3 Comments

This looks awesome @NonGrate! Does this code work to get the disk space for MacOS, Windows and Linux too please?
I haven't tested that. If someone can - I would be grateful.
Hi @0xba1, you need to add that .kt file to the android directory (as if you would add the file to the android project - android/app/src/main/java/.../...)
0

The test is to expand the storage space

  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()
  }

1 Comment

The original post is for Flutter and not Android.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.