Repository: flutter
Issue: [camera] Unable to keep torch on while taking a photo on a Samsung Device
Labels: e: device-specific,platform-android,p: camera,package,P2,team-android,triaged-android

<!-- Thank you for using Flutter!

     If you are looking for support, please check out our documentation
     or consider asking a question on Stack Overflow:
      * https://flutter.dev/
      * https://api.flutter.dev/
      * https://stackoverflow.com/questions/tagged/flutter?sort=frequent

     If you have found a bug or if our documentation doesn't have an answer
     to what you're looking for, then fill out the template below. Please read
     our guide to filing a bug first: https://flutter.dev/docs/resources/bug-reports
-->

## Steps to Reproduce

<!-- Please include full steps to reproduce so that we can reproduce the problem. -->

1. Set flash mode to torch using `_controller.setFlashMode(FlashMode.torch)`
2. Try to take a picture using `image = await _controller.takePicture()`

(Tested on a Samsung A51)

**Expected results:** <!-- what did you want to see? -->

The torch stays on while the photo is taken, only turning off after the photo is captured resulting in a well lit image.

**Actual results:** <!-- what did you see? -->

The torch turns down just as the camera captures the photo, then it flashes briefly as if using `FlashMode.always` but ultimately results in a dark photo.

https://user-images.githubusercontent.com/14153390/147861849-eedbf3ed-5a77-4a52-8c18-dcbc62558537.mp4

Switching to `FlashMode.always` just before taking the picture also results in a dark image. However, the following code produces a well timed flash and a well lit photo, even if the desired behaviour is to keep the torch on at all times while the picture is taken:

```dart
_controller.setFlashMode(FlashMode.off);
_controller.setFlashMode(FlashMode.always);
final image = await _controller.takePicture();
```

<details>
<summary>Code sample</summary>

<!--
      Please create a minimal reproducible sample that shows the problem
      and attach it below between the lines with the backticks.

      To create it you can use `flutter create bug` command and update the `main.dart` file.

      Alternatively, you can use https://dartpad.dev/
      which is capable of creating and running small Flutter apps.

      Without this we will unlikely be able to progress on the issue, and because of that
      we regretfully will have to close it.
-->
Full code in https://github.com/dogudo/tfg/tree/main/lib
```dart
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';

import 'display_picture.dart';

List<CameraDescription> cameras = [];

// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
  TakePictureScreen({
    Key? key,
  }) : super(key: key);

  final CameraDescription camera = cameras.first;

  @override
  TakePictureScreenState createState() => TakePictureScreenState();
}

class TakePictureScreenState extends State<TakePictureScreen>
    with WidgetsBindingObserver {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;
  bool flash = false;

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _initializeControllerFuture = _controller.initialize();
    }
  }

  @override
  void initState() {
    super.initState();
    // To display the current output from the Camera,
    // create a CameraController.
    _controller = CameraController(
      // Get a specific camera from the list of available cameras.
      widget.camera,
      // Define the resolution to use.
      ResolutionPreset.high, // CHECK RESOLUTION
    );

    // Next, initialize the controller. This returns a Future.
    _initializeControllerFuture = _controller.initialize().whenComplete(
        () => _controller.setFlashMode(FlashMode.off)); // START WITH FLASH OFF

    WidgetsBinding.instance!.addObserver(this); // ADD OBSERVER
  }

  @override
  void dispose() {
    // Dispose of the controller when the widget is disposed.
    _controller.dispose();
    super.dispose();

    WidgetsBinding.instance!.removeObserver(this); // REMOVE OBSERVER
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(
      const SystemUiOverlayStyle(
        systemNavigationBarColor: Colors.black,
        systemNavigationBarIconBrightness: Brightness.light,
      ),
    );
    return AnnotatedRegion(
      child: Scaffold(
        backgroundColor: Colors.black,
        extendBodyBehindAppBar: true,
        appBar: AppBar(
          title: const Text('Take a picture'),
          systemOverlayStyle: const SystemUiOverlayStyle(
            statusBarColor: Colors.transparent,
          ),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.collections_outlined),
              tooltip: 'Show Snackbar',
              onPressed: () async {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('This is a snackbar')),
                );
                final ImagePicker _picker = ImagePicker();
                final XFile? image =
                    await _picker.pickImage(source: ImageSource.gallery);
                if (image != null) {
                  await Navigator.of(context).push(
                    MaterialPageRoute(
                      builder: (context) => DisplayPictureScreen(
                        // Pass the automatically generated path to
                        // the DisplayPictureScreen widget.
                        imagePath: image.path,
                      ),
                    ),
                  );
                }
              },
            ),
            IconButton(
              icon: Icon(
                flash ? Icons.flash_on : Icons.flash_off,
                color: Colors.white,
                size: 28,
              ),
              tooltip: 'Go to the next page',
              onPressed: () {
                setState(() {
                  flash = !flash;
                });
                flash
                    ? _controller.setFlashMode(FlashMode.torch)
                    : _controller.setFlashMode(FlashMode.off);
              },
            ),
            IconButton(
              icon: const Icon(Icons.help_outline_rounded),
              tooltip: 'Go to the next page',
              onPressed: () {
                Navigator.push(context, MaterialPageRoute<void>(
                  builder: (BuildContext context) {
                    return Scaffold(
                      appBar: AppBar(
                        title: const Text('Next page'),
                      ),
                      body: const Center(
                        child: Text(
                          'This is the next page',
                          style: TextStyle(fontSize: 24),
                        ),
                      ),
                    );
                  },
                ));
              },
            ),
          ],
          backgroundColor: Colors.transparent,
          elevation: 0,
          flexibleSpace: Container(
            decoration: const BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.black, Colors.transparent],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
              ),
            ),
          ),
          leading: const CloseButton(),
        ),
        // You must wait until the controller is initialized before displaying the
        // camera preview. Use a FutureBuilder to display a loading spinner until the
        // controller has finished initializing.
        body: FutureBuilder<void>(
          future: _initializeControllerFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              // If the Future is complete, display the preview.
              final scale = 1 /
                  (_controller.value.aspectRatio *
                      MediaQuery.of(context).size.aspectRatio);
              return Transform.scale(
                scale: scale,
                alignment: Alignment.topCenter,
                child: CameraPreview(_controller),
              );
              // return CameraPreview(_controller);
            } else {
              // Otherwise, display a loading indicator.
              return const Center(child: CircularProgressIndicator());
            }
          },
        ),
        //floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
        floatingActionButton: FloatingActionButton(
          // Provide an onPressed callback.
          onPressed: () async {
            // Take the Picture in a try / catch block. If anything goes wrong,
            // catch the error.
            try {
              // Ensure that the camera is initialized.
              await _initializeControllerFuture;

              // Attempt to take a picture and get the file `image`
              // where it was saved.
              // _controller.setFlashMode(FlashMode.off);
              // _controller.setFlashMode(FlashMode.always);
                final image = await _controller.takePicture();

              // If the picture was taken, display it on a new screen.
              await Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (context) => DisplayPictureScreen(
                    // Pass the automatically generated path to
                    // the DisplayPictureScreen widget.
                    imagePath: image.path,
                  ),
                ),
              );
            } catch (e) {
              // If an error occurs, log the error to the console.
              print(e);
            }
          },
          child: const Icon(Icons.camera_alt),
        ),
      ),
      value: const SystemUiOverlayStyle(
        systemNavigationBarColor: Colors.transparent,
        systemNavigationBarIconBrightness: Brightness.light,
      ),
    );
  }
}
```

</details>

<details>
  <summary>Logs</summary>

<!--
      Run your application with `flutter run --verbose` and attach all the
      log output below between the lines with the backticks. If there is an
      exception, please see if the error message includes enough information
      to explain how to solve the issue.
-->



<!--
     Run `flutter analyze` and attach any output of that command below.
     If there are any analysis errors, try resolving them before filing this issue.
-->

```
Analyzing mugunghwa...                                                  

   info - Avoid `print` calls in production code - lib\camera.dart:212:15 - avoid_print
   info - Avoid `print` calls in production code - lib\display_picture.dart:70:5 - avoid_print
   info - Avoid `print` calls in production code - lib\display_picture.dart:72:5 - avoid_print
   info - Avoid `print` calls in production code - lib\display_picture.dart:73:5 - avoid_print
   info - Avoid `print` calls in production code - lib\display_picture.dart:75:5 - avoid_print

5 issues found. (ran in 7.2s)
```

<!-- Finally, paste the output of running `flutter doctor -v` here. -->

```
[√] Flutter (Channel stable, 2.8.1, on Microsoft Windows [VersiÃ³n 10.0.22000.376], locale es-ES)
    • Flutter version 2.8.1 at C:\Users\alobr\Documents\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 77d935af4d (2 weeks ago), 2021-12-16 08:37:33 -0800
    • Engine revision 890a5fca2e
    • Dart version 2.15.1

[√] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at C:\Users\alobr\AppData\Local\Android\sdk
    • Platform android-31, build-tools 31.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 2020.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 11.0.10+0-b96-7249189)

[√] VS Code (version 1.63.2)
    • VS Code at C:\Users\alobr\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.29.0

[√] Connected device (3 available)
    • SM A516B (mobile) • R5CNC03Q1PV • android-arm64  • Android 11 (API 30)
    • Chrome (web)      • chrome      • web-javascript • Google Chrome 96.0.4664.110
    • Edge (web)        • edge        • web-javascript • Microsoft Edge 96.0.1054.62

• No issues found!
```





</details>


<!--
      Consider also attaching screenshots and/or videos to better
      illustrate the issue.

      You can upload them directly on GitHub.
      Beware that video file size is limited to 10MB.
-->