Repository: flutter
Issue: [camera_windows] Camera with given device id already exists. Existing camera must be disposed before creating it again
Labels: platform-windows,p: camera,package,a: desktop,has reproducible steps,P3,team-windows,triaged-windows,found in release: 3.24,found in release: 3.27

### Steps to reproduce

camera_error: Camera with given device id already exists. Existing camera must be disposed before creating it again

### Expected results

camera should work

### Actual results

camera_error: Camera with given device id already exists. Existing camera must be disposed before creating it again

### Code sample

```
import 'dart:async';

import 'dart:developer';

import 'dart:io';

import 'package:camera_platform_interface/camera_platform_interface.dart';

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

import 'package:flutter/services.dart';

import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:responsive_sizer/responsive_sizer.dart';

import '../InspectionPhotos/Bloc/InspectionPhotosBloc.dart';

import '../InspectionPhotos/Bloc/InspectionPhotosEvent.dart';

class CameraCapture extends StatefulWidget {
  final inspectionId, inspectionData;

  const CameraCapture(
      {super.key, required this.inspectionData, required this.inspectionId});

  @override
  State<CameraCapture> createState() => _MyAppState();
}

class _MyAppState extends State<CameraCapture> {
  List<CameraDescription> _cameras = <CameraDescription>[];

  int _cameraIndex = 0;

  int _cameraId = -1;

  bool _initialized = false;

  Size? _previewSize;

  String? _capturedImagePath;

  final MediaSettings _mediaSettings = const MediaSettings(
    resolutionPreset: ResolutionPreset.medium,
    fps: 15,
    videoBitrate: 200000,
    audioBitrate: 32000,
    enableAudio: true,
  );

  StreamSubscription<CameraErrorEvent>? _errorStreamSubscription;

  StreamSubscription<CameraClosingEvent>? _cameraClosingStreamSubscription;

  @override
  void initState() {
    super.initState();

    WidgetsFlutterBinding.ensureInitialized();

    fetch();
  }

  fetch() async {
    await _fetchCameras();

    await _initializeCamera();
  }

  @override
  void dispose() {
    _disposeCurrentCamera();

    _errorStreamSubscription?.cancel();

    _cameraClosingStreamSubscription?.cancel();

    super.dispose();
  }

  Future<void> _fetchCameras() async {
    try {
      List<CameraDescription> cameras =
          await CameraPlatform.instance.availableCameras();

      if (cameras.isNotEmpty) {
        setState(() {
          _cameras = cameras;

          _cameraIndex %= cameras.length;
        });
      }
    } on PlatformException catch (e) {
      log(e.toString());
    }
  }

  Future<void> _initializeCamera() async {
    if (_initialized) return;

    if (_cameras.isEmpty) return;

    try {
      final CameraDescription camera = _cameras[_cameraIndex];

      if (_cameraId >= 0) {
        await _disposeCurrentCamera();
      }

      _cameraId = await CameraPlatform.instance.createCameraWithSettings(
        camera,
        _mediaSettings,
      );

      _errorStreamSubscription?.cancel();

      _errorStreamSubscription = CameraPlatform.instance
          .onCameraError(_cameraId)
          .listen(_onCameraError);

      _cameraClosingStreamSubscription?.cancel();

      _cameraClosingStreamSubscription = CameraPlatform.instance
          .onCameraClosing(_cameraId)
          .listen(_onCameraClosing);

      await CameraPlatform.instance.initializeCamera(_cameraId);

      final event =
          await CameraPlatform.instance.onCameraInitialized(_cameraId).first;

      _previewSize = Size(event.previewWidth, event.previewHeight);

      setState(() {
        _initialized = true;
      });
    } on CameraException catch (e) {
      debugPrint('Failed to initialize camera: ${e.code}: ${e.description}');

      await _disposeCurrentCamera();
    }
  }

  Future<void> _takePicture() async {
    try {
      final XFile file = await CameraPlatform.instance.takePicture(_cameraId);

      setState(() {
        _capturedImagePath = file.path;
      });
    } catch (e) {
      debugPrint('Error capturing image: $e');
    }
  }

  void _onCancelPreview() {
    setState(() {
      _capturedImagePath = null;
    });
  }

  void _onSaveImage() {
    if (_capturedImagePath != null) {
     

      _onCancelPreview();
    }
  }

  void _onCameraClosing(CameraClosingEvent event) {
    if (mounted) {
      _disposeCurrentCamera();
    }
  }

  Future<void> _disposeCurrentCamera() async {
    if (_cameraId >= 0 && _initialized) {
      try {
        await CameraPlatform.instance.dispose(_cameraId);

        setState(() {
          _initialized = false;

          _cameraId = -1;

          _previewSize = null;
        });
      } on CameraException catch (e) {
        log(e.toString());
      }
    }
  }

  Future<void> _switchCamera() async {
    if (_cameras.isNotEmpty) {
      _cameraIndex = (_cameraIndex + 1) % _cameras.length;

      await _disposeCurrentCamera(); // Ensure current camera is fully disposed

      await _initializeCamera(); // Reinitialize with new camera index
    }
  }

  void _onCameraError(CameraErrorEvent event) {
    if (mounted) {
      _disposeCurrentCamera();

      _fetchCameras();
    }
  }

  Widget _buildPreview() {
    return CameraPlatform.instance.buildPreview(_cameraId);
  }

  Widget _buildCapturedImagePreview() {
    return Stack(
      children: [
        Positioned.fill(
          child: Image.file(
            File(_capturedImagePath!),
            fit: BoxFit.cover,
          ),
        ),
        Positioned(
          bottom: 20,
          left: 20,
          right: 20,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              ElevatedButton(
                onPressed: _onCancelPreview,
                child: const Text("Cancel"),
              ),
              ElevatedButton(
                onPressed: _onSaveImage,
                child: const Text("Save"),
              ),
            ],
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).primaryColorDark,
      appBar: AppBar(
        title: Text(
          "Inspection Photos",
          style: Theme.of(context).appBarTheme.titleTextStyle,
        ),
        centerTitle: true,
        iconTheme: Theme.of(context).appBarTheme.iconTheme,
        automaticallyImplyLeading: true,
      ),
      body: Stack(
        children: <Widget>[
          if (_initialized &&
              _cameraId > 0 &&
              _previewSize != null &&
              _capturedImagePath == null)
            SizedBox(
              height: 100.h,
              width: 100.w,
              child: _buildPreview(),
            ),
          if (_capturedImagePath != null) _buildCapturedImagePreview(),
          if (_cameras.isNotEmpty && _capturedImagePath == null)
            Align(
              alignment: Alignment.centerRight,
              child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 20.sp),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    if (_cameras.length > 1)
                      IconButton(
                        onPressed: _switchCamera,
                        icon: const Icon(
                          CupertinoIcons.switch_camera_solid,
                          color: Colors.white,
                        ),
                      ),
                    Padding(
                      padding: EdgeInsets.only(
                          bottom: 20.sp, top: 10.sp, right: 15.sp),
                      child: IconButton(
                        onPressed: _initialized ? _takePicture : null,
                        icon: const Icon(
                          CupertinoIcons.camera_circle,
                          size: 60,
                          color: Colors.white,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
        ],
      ),
    );
  }
}

```
### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

[Upload media here]

</details>


### Logs

<details open><summary>Logs</summary>

```console
[Paste your logs here]
```

</details>


### Flutter Doctor output

[√] Flutter (Channel stable, 3.24.0, on Microsoft Windows [Version 10.0.22631.4317], locale en-IN)
    • Flutter version 3.24.0 on channel stable at D:\Mobile Devlopment\flutter_windows_3.13.2-stable\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 80c2e84975 (3 months ago), 2024-07-30 23:06:49 +0700
    • Engine revision b8800d88be
    • Dart version 3.5.0
    • DevTools version 2.37.2
 
[√] Windows Version (Installed version of Windows is version 10 or higher)
 
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at C:\Users\devus\AppData\Local\Android\sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)
    ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
 
[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe
 
[√] Visual Studio - develop Windows apps (Visual Studio Enterprise 2022 17.9.5)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Enterprise
    • Visual Studio Enterprise 2022 version 17.9.34723.18
    • Windows 10 SDK version 10.0.22621.0
 
[√] Android Studio (version 2022.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)
 
[√] VS Code (version 1.94.2)
    • VS Code at C:\Users\devus\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.98.0
 
[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.22631.4317]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 127.0.6533.120
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 130.0.2849.68
 
[√] Network resources
    • All expected network resources are available.
 
! Doctor found issues in 1 category.