Search code examples
androidflutterfiledartio

'No such file or directory' error when writing file in Flutter


I'm trying to write image bytes to a local file but I'm getting the error:

Directory: '/data/user/0/ca.footeware.flutter.xkcdrandomizer/app_flutter'/flutter.png: open failed: ENOENT (No such file or directory)

My relevant code:

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xkcd_randomizer">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<application
    android:label="xkcd_randomizer"
    android:icon="@mipmap/ic_launcher"
    android:requestLegacyExternalStorage="true">

[snip]

main.dart:

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:http/io_client.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:photo_view/photo_view.dart';
import 'package:share/share.dart';

[snip]

Future<PermissionStatus> get permission async {
    return await Permission.storage.request();
}

[snip]

  Future<void> share() async {
    if (await permission.isGranted) {
      final RenderBox box = context.findRenderObject() as RenderBox;
      var response = await get(Uri.parse(_url));
      var directory = await getApplicationDocumentsDirectory();
      print('dir=$directory');
      File imgFile = File('/data/user/0/ca.footeware.flutter.xkcdrandomizer/app_flutter/flutter.png');
      print('imgFile=$imgFile');
      var bodyBytes = response.bodyBytes;
      print(bodyBytes);
      imgFile.writeAsBytes(bodyBytes);
      File file = File('$directory/flutter.png');
      Share.shareFiles([file.path],
          subject: 'XKCD comic',
          text: 'test',
          sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
    }
  }

The debug output from the print statements:

I/flutter ( 9509): dir=Directory: '/data/user/0/ca.footeware.flutter.xkcdrandomizer/app_flutter'
I/flutter ( 9509): imgFile=File: '/data/user/0/ca.footeware.flutter.xkcdrandomizer/app_flutter/flutter.png'
I/flutter ( 9509): [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 2, 1, 1, 144, 1, 144, 0, 0, 255, 225, 1, 26, 69, 120, 105, 102, 0, 0, 77, 77, 0, 42, 0, 0, 0, 8, 0, 9, 1, 15, 0, 2, 0, 0, 0, 6, 0, 0, 0, 122, 1, 16, 0, 2, 0, 0, 0, 15, 0, 0, 0, 128, 1, 18, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0, 1, 26, 0, 5, 0, 0, 0, 1, 0, 0, 0, 143, 1, 27, 0, 5, 0, 0, 0, 1, 0, 0, 0, 151, 1, 40, 0, 3, 0, 0, 0, 1, 0, 2, 0, 0, 1, 49, 0, 2, 0, 0, 0, 21, 0, 0, 0, 159, 1, 50, 0, 2, 0, 0, 0, 20, 0, 0, 0, 180, 135, 105, 0, 4, 0, 0, 0, 1, 0, 0, 0, 200, 0, 0, 0, 0, 67, 97, 110, 111, 110, 0, 67, 97, 110, 111, 83, 99, 97, 110, 32, 57, 57, 53, 48, 70, 0, 0, 0, 1, 144, 0, 0, 0, 1, 0, 0, 1, 144, 0, 0, 0, 1, 67, 97, 110, 111, 83, 99, 97, 110, 32, 84, 111, 111, 108, 98, 111, 120, 32, 52, 46, 57, 0, 50, 48, 48, 53, 58, 49, 49, 58, 48, 51, 58, 50, 48, 58, 51, 51, 58, 50, 57, 0, 0, 4, 144, 0, 0, 7, 0, 0, 0, 4, 48, 50, 50, 49, 144, 4, 0, 2, 0, 0, 0, 20, 0, 0, 0, 254, 160, 0, 0, 7, 0, 0, 0, 4, 48, 49, 48, 48, 160, 1, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 50, 48, 48, 53

...then the line:

imgFile.writeAsBytes(bodyBytes);

...causes the error. I tried writeAsBytesSync but got the same result. I hardcoded the file path as a debug step but you can see it's the same as the document directory.


Solution

  • Pay close attention to the printed output. When you do print('dir=$directory'), you get:

    dir=Directory: '/path/to/directory'
    

    and not:

    dir=/path/to/directory
    

    In other words, Directory.toString() does not return the path but instead returns a string:

    Directory: '/path/to/directory'
    

    The same thing applies to File.toString(). You instead should use the .path property:

    File file = File('${directory.path}/flutter.png');