无法使用ImagePicker打开Windows相机

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

我正在使用 image_picker: ^1.0.4 包从相机和图库中选取图像。它在 Android 和 ios 上运行良好,但在 Windows 中相机无法打开。文档建议使用自定义相机委托。我尝试将所有东西组合在一起,但没有任何效果。

final pickedFile = await ImagePicker().getImage(
      source: ImageSource.camera,
    );

我尝试了以下代码

import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
// ···
class MyCameraDelegate extends ImagePickerCameraDelegate {
  @override
  Future<XFile?> takePhoto(
      {ImagePickerCameraDelegateOptions options =
          const ImagePickerCameraDelegateOptions()}) async {
    return _takeAPhoto(options.preferredCameraDevice);
  }

  @override
  Future<XFile?> takeVideo(
      {ImagePickerCameraDelegateOptions options =
          const ImagePickerCameraDelegateOptions()}) async {
    return _takeAVideo(options.preferredCameraDevice);
  }
}

// ···
void setUpCameraDelegate() {
  final ImagePickerPlatform instance = ImagePickerPlatform.instance;
  if (instance is CameraDelegatingImagePickerPlatform) {
    instance.cameraDelegate = MyCameraDelegate();
  }
}

但仍然遇到以下问题

除非设置了cameraDelegate,否则不支持ImageSource.camera

如果有人有工作代码,请指导问题所在或分享您的实现。

flutter camera flutter-windows flutter-image-picker
1个回答
0
投票

也许有点晚了,但这是我对 Windows 的自定义委托的实现。

在使用图像选择器之前,必须调用 WindowsCameraDelegate.register 方法。


void main(List<String> args) async {
  // Ensure WidgetsFlutterBinding is initialized before any async code.
  WidgetsFlutterBinding.ensureInitialized();

  initCamera();

  ...
}


void initCamera() {
  if (Platform.isWindows) {
    /// Add camera support to Image Picker on Windows.
    WindowsCameraDelegate.register();
  }
}

And the custom delegate method
```dart
import 'dart:async';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';

import '../hmb_toast.dart';

class WindowsCameraDelegate extends ImagePickerCameraDelegate {
  List<CameraDescription> _cameras = [];
  int _cameraId = -1;
  bool _initialized = false;
  bool _isTakingPhoto = false;
  StreamSubscription<CameraErrorEvent>? _errorStreamSubscription;

  @override
  Future<XFile?> takePhoto(
      {ImagePickerCameraDelegateOptions options =
          const ImagePickerCameraDelegateOptions()}) async {
    if (_isTakingPhoto) {
      HMBToast.error('Camera is currently busy.');
      return null;
    }
    _isTakingPhoto = true;

    if (!_initialized) {
      await _initializeCamera();
    }

    try {
      // Capture the image
      final file = await CameraPlatform.instance.takePicture(_cameraId);
      return file;
    } catch (e) {
      HMBToast.error('Error capturing image: $e');
      return null;
    } finally {
      await _disposeCamera();
      _isTakingPhoto = false;
    }
  }

  Future<void> _fetchCameras() async {
    try {
      _cameras = await CameraPlatform.instance.availableCameras();
    } catch (e) {
      HMBToast.error('Error fetching cameras: $e');
    }
  }

  Future<void> _initializeCamera() async {
    print('initializeCamera');
    if (_cameras.isEmpty) {
      await _fetchCameras();
    }

    try {
      final camera = _cameras.first;
      _cameraId = await CameraPlatform.instance.createCameraWithSettings(
        camera,
        const MediaSettings(resolutionPreset: ResolutionPreset.high, fps: 30),
      );

      // Listen for camera initialization
      await CameraPlatform.instance.initializeCamera(_cameraId);
      _initialized = true;

      // Start monitoring the camera error stream
      _monitorCameraErrors();
    } catch (e) {
      HMBToast.error('Error initializing camera: $e');
      _initialized = false;
    }
  }

  void _monitorCameraErrors() {
    // Cancel any previous subscription to avoid duplicate listeners
    unawaited(_errorStreamSubscription?.cancel());

    _errorStreamSubscription =
        CameraPlatform.instance.onCameraError(_cameraId).listen((errorEvent) {
      HMBToast.error('Camera error detected: ${errorEvent.description}');
      unawaited(_resetCamera());
    });
  }

  Future<void> _resetCamera() async {
    await _disposeCamera();
    await _initializeCamera();
  }

  Future<void> _disposeCamera() async {
    // Dispose of error stream
    await _errorStreamSubscription?.cancel();
    _errorStreamSubscription = null;

    if (_initialized) {
      await CameraPlatform.instance.dispose(_cameraId);
      _initialized = false;
    }
  }

  @override
  Future<XFile?> takeVideo(
      {ImagePickerCameraDelegateOptions options =
          const ImagePickerCameraDelegateOptions()}) {
    throw UnimplementedError('Video capture is not yet supported on Windows.');
  }

  /// Initialize this CameraDelegate
  /// This method should be called before the ImagePicker is used
  /// on Windows.
  static void register() {
    final instance = ImagePickerPlatform.instance;
    if (instance is CameraDelegatingImagePickerPlatform) {
      instance.cameraDelegate = WindowsCameraDelegate();
    }
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.