Home > Back-end >  Flutter `Screenshot` package: Why isn't the `captureAndSave()` method saving an image to my (An
Flutter `Screenshot` package: Why isn't the `captureAndSave()` method saving an image to my (An

Time:07-05

Preface:

I'm using the enter image description here

Full Traceback:


======== Exception caught by image resource service ================================================
The following assertion was thrown resolving an image codec:
Unable to load asset: /data/user/0/com.example.qr/app_flutter/qr.png

When the exception was thrown, this was the stack: 
#0      PlatformAssetBundle.load (package:flutter/src/services/asset_bundle.dart:237:7)
<asynchronous suspension>
#1      AssetBundleImageProvider._loadAsync (package:flutter/src/painting/image_provider.dart:675:14)
<asynchronous suspension>
Image provider: AssetImage(bundle: null, name: "/data/user/0/com.example.qr/app_flutter/qr.png")
Image key: AssetBundleImageKey(bundle: PlatformAssetBundle#5986d(), name: "/data/user/0/com.example.qr/app_flutter/qr.png", scale: 1.0)
====================================================================================================
  • Why isn't my image being saved to the device when calling _captureAndSaveQRCode()?

Side note:

I recently posted an answer (currently in Bounty) with (almost) the same code as in this question which does work correctly, so, what's the difference?

CodePudding user response:

load image with Image.file(File(imagePath))
Image.Asset is for loading images defined in pubspec.yaml

Edit:
the path in captureAndSave is directory path. it takes another optional argument fileName.

// previous code

// i create new getter for directory
Future<String> get dirPath async {
    final directory = (await getApplicationDocumentsDirectory()).path;
    return directory;
  }

  Future<String> get imagePath async {
    final directory = await dirPath;
    return '$directory/qr.png';
  }

  Future<Image> _loadImage() async {
    return imagePath.then((imagePath) => Image.file(File(imagePath)));
  }

  Future<void> _captureAndSaveQRCode() async {
    final path = await dirPath;
    await _screenshotController.captureAndSave(path, fileName: "qr.png");
    // It always returns false, although I'm saving the file using `captureAndSave` .
    doesTheImageExist = File(path).existsSync();
  }

// the rest of the code

CodePudding user response:

The problem was that I had an empty setState:

onPressed: () async {
                await _captureAndSaveQRCode();
                image = await _loadImage();
                setState(() {});
              },
            )

So to solve the problem, I removed the setState and also got rid of the _loadImage() function. And then change the image variable within the TextButton():

  TextButton(
              child: Text("Save QR Code"),
              onPressed: () async {
                await _captureAndSaveQRCode();

                setState(() {
                  doesTheImageExist = true;
                  image = image;
                });
              },
            )

Complete working example:

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:screenshot/screenshot.dart';

class QrCodeScreen extends StatefulWidget {
  const QrCodeScreen({Key? key}) : super(key: key);

  @override
  State<QrCodeScreen> createState() => _QrCodeScreenState();
}

class _QrCodeScreenState extends State<QrCodeScreen> {
  final _screenshotController = ScreenshotController();
  Image? image;
  var doesTheImageExist = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          if (image == null)
            TextButton(
              child: Text("Save QR Code"),
              onPressed: () async {
                await _captureAndSaveQRCode();

                setState(() {
                  doesTheImageExist = true;
                  image = image;
                });
              },
            )
          else
            image!,
          Row(children: [
            Text('hi'),
            Text("Is the QR Code saved to your device? ${doesTheImageExist}")
          ]),
          if (image == null)
            Screenshot(
                controller: _screenshotController,
                child: _buildQRImage('_authProvider.user!.uid')),
        ],
      ),
    );
  }

  Widget _buildQRImage(String data) {
    return QrImage(
      data: data,
      size: 250.0,
      gapless: false,
      foregroundColor: Colors.black,
      backgroundColor: Colors.white,
    );
  }

  Future<String> get imagePath async {
    final directory = (await getApplicationDocumentsDirectory()).path;
    return '$directory/qr.png';
  }

  // Future<Image> _loadImage() async {
  //   return imagePath.then((imagePath) => Image.asset(imagePath));
  // }

  Future<void> _captureAndSaveQRCode() async {
    final path = await imagePath;
    await _screenshotController.captureAndSave(path);
    // It always returns false, although I'm saving the file using `captureAndSave` .
    doesTheImageExist = File(path).existsSync();
  }
}
  • Related