在Flutter中,如何将相机图像保存到DCIM之类的文件夹中?

问题描述 投票:0回答:1

超出了我的能力范围,但我已经将相机应用程序的骨架放在一起(实际上 MS Copilot 做到了)。

编辑:应用程序运行的屏幕截图:

最后一个问题是将照片保存在我想要的地方,例如“内部共享存储/DCIM/AppTestPhotos”。

直接相关的代码:

 floatingActionButton: FloatingActionButton(
    child: const Icon(Icons.camera),
    onPressed: () async {
      final XFile photo = await controller.takePicture();
      String filePath = photo.path;
      print('File path from photo.path: $filePath');

      await Gal.putImage(filePath);
      print('Image saved at: $filePath');
    },
  ),

使用 XFile 中的默认路径,文件路径指示为:

  /data/user/0/com.example.cam_test_2_one_screen/cache/CAP555419134659270816.jpg
...它显示在手机上的“内部共享存储/图片”文件夹中。我尝试修改路径以使其显示在“内部共享存储/DCIM/AppTestPhotos”中,但没有成功。

对于如何让它发挥作用有什么想法吗?看起来很接近。

由于它不太长,所以这是完整的 main.dart 文件:

import 'dart:math';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
import 'package:gal/gal.dart';
import 'package:path/path.dart' as p;

List<CameraDescription> cameras = [];

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  runApp(const CameraApp());
}

class CameraApp extends StatelessWidget {
  const CameraApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: CameraScreen(),
    );
  }
}

class CameraScreen extends StatefulWidget {
  const CameraScreen({super.key});

  @override
  // ignore: library_private_types_in_public_api
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  late CameraController controller;
  bool showFocusCircle = false;
  double x = 0;
  double y = 0;

  @override
  void initState() {
    super.initState();
    controller = CameraController(cameras[0], ResolutionPreset.medium);
    controller.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    if (!controller.value.isInitialized) {
      return Container();
    }
    return Scaffold(
      appBar: AppBar(title: const Text('Take a picture')),
      body: GestureDetector(
        onTapUp: (details) {
          _onTap(details);
        },
        child: Stack(
          children: [
            Center(child: CameraPreview(controller)),
            if (showFocusCircle)
              Positioned(
                top: y - 20,
                left: x - 20,
                child: Container(
                  height: 40,
                  width: 40,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    border: Border.all(color: Colors.white, width: 1.5),
                  ),
                ),
              ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.camera),
        onPressed: () async {
          final XFile photo = await controller.takePicture();
          String filePath = photo.path;
          print('File path from photo.path: $filePath');

          await Gal.putImage(filePath);
          print('Image saved at: $filePath');
        },
      ),
      // floatingActionButton: FloatingActionButton(
      //   child: const Icon(Icons.camera),
      //   onPressed: () async {
      //     final XFile photo = await controller.takePicture();
      //     final Directory? extDir = await getExternalStorageDirectory();
      //     if (extDir != null) {
      //       final String dirPath = '${extDir.path}/DCIM/AppTestPhotos';
      //       await Directory(dirPath).create(recursive: true);
      //       final String filePath = '$dirPath/${DateTime.now()}.jpg';
      //       await photo.saveTo(filePath);
      //       print('Picture saved at: $filePath');
      //     }
      //   },
      // ),

      // floatingActionButton: FloatingActionButton(
      //   child: const Icon(Icons.camera),
      //   onPressed: () async {
      //     final XFile photo = await controller.takePicture();
      //     final Directory? extDir = await getExternalStorageDirectory();
      //     if (extDir != null) {
      //       final String dirPath = '${extDir.path}/AppTestPhotos';
      //       await Directory(dirPath).create(recursive: true);
      //       final String filePath = '$dirPath/${DateTime.now()}.jpg';
      //       await photo.saveTo(filePath);
      //       print('Picture saved at: $filePath');
      //     }
      //   },
      // ),

      // floatingActionButton: FloatingActionButton(
      //   child: Icon(Icons.camera),
      //   onPressed: () async {
      //     final XFile photo = await controller.takePicture();
      //     print('Picture saved at: ${photo.path}');
      //   },
      // ),
    );
  }

  Future<void> _onTap(TapUpDetails details) async {
    if (controller.value.isInitialized) {
      showFocusCircle = true;
      x = details.localPosition.dx;
      y = details.localPosition.dy;
      double fullWidth = MediaQuery.of(context).size.width;
      double cameraHeight = fullWidth * controller.value.aspectRatio;
      double xp = x / fullWidth;
      double yp = y / cameraHeight;
      Offset point = Offset(xp, yp);
      await controller.setFocusPoint(point);
      setState(() {
        Future.delayed(const Duration(seconds: 2)).whenComplete(() {
          setState(() {
            showFocusCircle = false;
          });
        });
      });
    }
  }
}

Future<void> _requestStoragePermission() async {
  final status = await Permission.storage.request();
  print('Permission status: $status');
}
android flutter android-camera
1个回答
0
投票

这是我将照片保存到 Android 上的 DCIM 文件夹的方法

  • 它可能不适用于最新的 Android 版本
  • 检查权限 WRITE_EXTERNAL_STORAGE

这是结果

代码片段

        FloatingActionButton(
          child: const Icon(Icons.camera),
          onPressed: () async {
            final XFile photo = await controller.takePicture();
            Uint8List captureImage = File(photo.path).readAsBytesSync();

            String _directory = '';
            if (Platform.isIOS) {
              _directory = (await getApplicationSupportDirectory()).path;
            } else {
              /// It might not work with latest Android version
              /// Check Permission WRITE_EXTERNAL_STORAGE
              _directory = '/storage/emulated/0/DCIM';
            }
            final path = '$_directory/captured${const Uuid().v1()}.png';
            final imagePath = await File(path).create();
            await imagePath.writeAsBytes(captureImage);

            await Gal.putImage(path);
            print('Image saved at: $path');
  
          },
        ),
© www.soinside.com 2019 - 2024. All rights reserved.