我正在使用 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
如果有人有工作代码,请指导问题所在或分享您的实现。
也许有点晚了,但这是我对 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();
}
}
}