Flutter“屏幕快照软件包:为什么是captureandsave()`方法将图像保存到我的(Android)设备?

发布于 2025-02-13 10:07:26 字数 4272 浏览 0 评论 0原文

序言:

我正在使用 ScreenShot package。在此软件包中,有一个方法 cartureandsave()代码>将小部件作为图像保存到特定位置,但是,当我调用此功能时,我的图像没有被保存。为什么?

完整的代码示例:

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();
                image = await _loadImage();
                setState(() {});
              },
            )
          else
            image!,
          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();
  }
}

问题:

在上面的代码中,当我单击textButton()时,它说“保存qr code” ,然后调用_CAPTUREANDSAVEQRCRCRCODE()_loadimage()。因此,我的图像应该成功地保存到我的(Android)手机中。但是,我遇到了一个错误:

Unable to load asset: /data/user/0/com.example.qr/app_flutter/qr.png

”在此处输入图像描述”

全追溯:


======== 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)
====================================================================================================
  • 为什么我的图像在调用时不会保存到设备_CAPTUREANDSAVEQRCODE()

旁注:

i 最近发布了一个答案(当前在赏金中)(几乎)与此问题相同的代码(几乎)正常工作,那么有什么区别?

Preface:

I'm using the Screenshot package. In this package, there is a method captureAndSave() which saves a widget as an image to a specific location, however, when I call this function, my image is not being saved. Why?

Complete Code 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();
                image = await _loadImage();
                setState(() {});
              },
            )
          else
            image!,
          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();
  }
}

The Question:

In the code above, when I click on the TextButton() that says "Save QR Code" it then calls _captureAndSaveQRCode() and _loadImage(). Hence my image should successfully be saved to my (Android) phone. However, I get an error:

Unable to load asset: /data/user/0/com.example.qr/app_flutter/qr.png

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧故 2025-02-20 10:07:26

问题是我有一个空的setState

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

为了解决问题,我删除了setState,也摆脱了_loadimage()>功能。
然后更新imagetextButton()中更新了变量:

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

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

完成工作示例:

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

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 updated 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();
  }
}
嘿咻 2025-02-20 10:07:26

加载图像带有image.file(file(imagepath))
image.asset用于加载pubspec.yaml

编辑中定义的图像:
Caureandsave的路径是目录路径。它需要另一个可选的参数文件名。

// 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文