Flutter files creation Error: (OS Error: Operation not permitted, errno = 1)

Viewed 9329

I'm trying to save an excel file to the local storage but I'm getting this error while creating the file. I'm debugging using a physical device. It only works when the device has an external SD card and is configured as internal storage. But when I run the app on a different device (physical device) with an SD card (configured as portable storage) it doesn't work and I get the error below.

Error

[ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: FileSystemException: Creation failed, path = '/storage/emulated/0/Traders' (OS Error: Operation not permitted, errno = 1)
E/flutter (15532): #0      _Directory.create.<anonymous closure> (dart:io/directory_impl.dart:117:11)
E/flutter (15532): #1      _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (15532): #2      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (15532): #3      _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter (15532): #4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter (15532): #5      Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter (15532): #6      Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter (15532): #7      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:577:7)
E/flutter (15532): #8      _rootRun (dart:async/zone.dart:1354:13)
E/flutter (15532): #9      _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter (15532): #10     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
E/flutter (15532): #11     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
E/flutter (15532): #12     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (15532): #13     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (15532): 

My Code

import 'dart:io' as IO;

IO.Directory dir = await getExternalStorageDirectory();
    String outputFile = "report"+DateFormat('dd-MM-yyyy hh:mm:ss').format(DateTime.now())+".xls";
    if (await Permission.storage.request().isGranted) {

      if (!IO.Directory('${dir.parent.parent.parent.parent.parent.path}/Traders/Reports').existsSync())
        await IO.Directory('${dir.parent.parent.parent.parent.path}/Traders/Reports').create(recursive: true);
      final file = IO.File(join('${dir.parent.parent.parent.parent.path}/Traders/Reports',outputFile));
      await file.writeAsBytes(excel.encode()).then((value) {
        if(IO.Platform.isAndroid||IO.Platform.isIOS)
          OpenFile.open('${dir.parent.parent.parent.parent.path}/Traders/Reports/$outputFile');
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("File Saved !")));
      }).catchError((e){
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Error Saving File !")));
      });
    }else{
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Error:Permission denied.Grant storage permission to save file."),action: SnackBarAction(label: 'Grant',onPressed: ()async{
        await Permission.storage.request();
      },),));
    }

AndroidMalifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
1 Answers

Abovecode is messy. You can use this packages to directly get the Home path. (/storage/emulated/0)

Then you can simple do this

var path = await ExtStorage.getExternalStorageDirectory();
final file = await File(path+'/Traders/Report').create(recursive: true);
file.writeAsStringSync("Hello I'm writting a stackoverflow answer into you");

OR

Ik that this packages is not null safe. So I'm providing native code in that case.

Some dart file, where you need the path

exportPath = await channel.invokeMethod('getExternalStorageDirectory'); // Call native code like this in your dart file

and then implement this

Go to 'android->app->src->main->kotlin->....your app name->MainActivity.kt'.

Add this


class MainActivity : FlutterFragmentActivity() {
    private val channel = "externalStorage";

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler { call, result ->
            when (call.method) {
                "getExternalStorageDirectory" ->
                    result.success(Environment.getExternalStorageDirectory().toString())
                "getExternalStoragePublicDirectory" -> {
                    val type = call.argument<String>("type")
                    result.success(Environment.getExternalStoragePublicDirectory(type).toString())
                }
                else -> result.notImplemented()
            }
        }

    }

}
Related