Skip to content

CameraPreview not working correctly on Android devices with natural landscape orientation #149177

Closed
flutter/packages
#7044

Description

@organic-nailer

What package does this bug report belong to?

camera

What target platforms are you seeing this bug on?

Android

Have you already upgraded your packages?

Yes

Dependency versions

pubspec.lock
[Paste file content here]

Steps to reproduce

  1. On Android devices with a natural landscape orientation, such as Docomo arrows Tab F-02K, run the following sample code

Expected results

CameraPreview shows the image naturally (the ground of the image faces downwards) regardless of the device orientation

Actual results

CameraPreview shows the image with incorrect orientation in all device orientations

Code sample

Code sample
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;
  @override
  void initState() {
    super.initState();
    _initializeControllerFuture = Future(() async {
      final cameras = await availableCameras();
      _controller = CameraController(cameras[0], ResolutionPreset.max);
      await _controller.initialize();
      setState(() {});
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Center(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      SizedBox(
                        width: 300,
                        height: 300,
                        child: _controller.buildPreview(),
                      ),
                      const Text("buildPreview()"),
                    ],
                  ),
                  Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      SizedBox(
                        width: 300,
                        height: 300,
                        child: CameraPreview(
                          _controller,
                        ),
                      ),
                      const Text("CameraPreview"),
                    ],
                  ),
                ],
              ),
            );
          } else {
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

Screenshots or Videos

Screenshots / Video demonstration
Screen_recording_20240528_223632.mp4

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.16.9, on macOS 14.4.1 23E224 darwin-arm64, locale ja-JP)
    • Flutter version 3.16.9 on channel stable at /Users/hykwy/development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 41456452f2 (4 months ago), 2024-01-25 10:06:23 -0800
    • Engine revision f40e976bed
    • Dart version 3.2.6
    • DevTools version 2.28.5

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/hykwy/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15E204a
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • 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.10+0-17.0.10b1087.21-11572160)

[✓] VS Code (version 1.88.1)
    • VS Code at /Users/hykwy/Downloads/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (3 available)
    • F 02K (mobile)  • cc12da58 • android-arm64  • Android 9 (API 28)
    • macOS (desktop) • macos    • darwin-arm64   • macOS 14.4.1 23E224 darwin-arm64
    • Chrome (web)    • chrome   • web-javascript • Google Chrome 125.0.6422.77
    ! Error: Browsing on the local area network for 高級なルーズリーフ. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Activity

  1. darshankawar commented on May 29, 2024

    @darshankawar
    Member

    Thanks for the report. I think this seems to be specific to the device you mentioned or with devices that have natural orientation landscape, because I tried the same on S10 device which gave me correct CameraPreview as below:

    Screenshot 2024-05-29 at 12 50 36 PM

    I'll keep the issue open and label for tracking as device specific.

  2. added
    platform-androidAndroid applications specifically
    packageflutter/packages repository. See also p: labels.
    team-androidOwned by Android platform team
    fyi-ecosystemFor the attention of Ecosystem team
    and removed
    in triagePresently being triaged by the triage team
    on May 29, 2024
  3. camsim99 commented on May 29, 2024

    @camsim99
    Contributor

    @organic-nailer Can you confirm the version of the camera plugin that you're using?

    Either way, I assume this issue comes from CameraX (assuming version >=0.11.0 is used) not behaving in the way that the plugin expects when the device has a natural landscape orientation.

  4. organic-nailer commented on May 30, 2024

    @organic-nailer
    Author

    I tried the camera plugin version 0.10.6 and 0.11.0, and have confirmed that this issue occurs with both. I don't think this issue is specific to the new CameraX plugin.

  5. organic-nailer commented on May 30, 2024

    @organic-nailer
    Author

    Based on my research, my hypothesis is as follows:

    1. Flutter renders camera images using CameraController.buildPreview(). This is achieved by placing a Texture using the textureId found in the provided CameraDescription.

    https://github.com/flutter/packages/blob/910fabb4886b975f13e0f98f60714c95b81465ed/packages/camera/camera_android/lib/src/android_camera.dart#L537-L540

    1. The TextureView of the Camera2 API outputs an image after correcting for sensor orientation. This orientation is correct when the device is in its natural position (typically with the camera at the top). Screen rotation is not considered.

    https://developer.android.com/media/camera/camera2/camera-preview#textureview

    1. The CameraPreview widget wraps the Texture in a RotatedBox to support screen rotation. The rotation amount is calculated from CameraController.value.deviceOrientation. This is where the problem lies. deviceOrientation only provides information on whether the screen is portrait, landscape, or inverted. It assumes, implicitly, that portrait with the top side up is the natural orientation, giving it a rotation of 0 degrees.

    https://github.com/flutter/packages/blob/910fabb4886b975f13e0f98f60714c95b81465ed/packages/camera/camera/lib/src/camera_preview.dart#L64-L72

    1. Ideally, the rotation amount should be determined by the tilt from the device's natural orientation. Android provides this through Display.getRotation(), but Flutter currently disregards this and does not offer a way to access it from Dart.

    https://github.com/flutter/packages/blob/910fabb4886b975f13e0f98f60714c95b81465ed/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/sensororientation/DeviceOrientationManager.java#L316-L327

    To resolve this issue, I believe we need to pass the value obtained from Display.getRotation() to Dart and use it to determine the rotation amount.

  6. added
    P1High-priority issues at the top of the work list
    on May 30, 2024
  7. self-assigned this
    on May 30, 2024
  8. reidbaker commented on May 30, 2024

    @reidbaker
    Contributor

    @organic-nailer Thank you for such a well researched comment and explaining where we made our mistake!

  9. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jul 8, 2024
  10. github-actions commented on Jul 22, 2024

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  11. locked as resolved and limited conversation to collaborators on Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work liste: device-specificOnly manifests on certain devicesp: cameraThe camera pluginpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions