Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: Check Device Available Storage using Dart

Tags:

flutter

dart

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

like image 660
Jagath Ratchagan Avatar asked Nov 30 '22 13:11

Jagath Ratchagan


2 Answers

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.

like image 181
João Soares Avatar answered Dec 03 '22 04:12

João Soares


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

like image 21
NonGrate Avatar answered Dec 03 '22 04:12

NonGrate