自拍摄像头在Flutter的相机插件中崩溃

huangapple go评论79阅读模式
英文:

Selfie camera crash in camera plugin in Flutter

问题

以下是翻译好的内容:

当我尝试从 camera 插件打开前置摄像头时,我的项目应用在 Pixel 3XL 上崩溃,但在后置摄像头上运行正常。

插件版本:camera: ^0.5.8+1

我的摄像头类。

class CameraState extends State<Camera> with WidgetsBindingObserver {
  // ...(代码部分被省略)

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          left: 0, top: 0, right: 0, bottom: 0,
          child: _cameraPreviewWidget(),
        ),
        Scaffold(
          body: new Container(
            // ...(代码部分被省略)
          ),
        )
      ],
    );
  }
}

Flutter Doctor 输出:

Doctor 摘要(要查看所有详细信息,请运行 flutter doctor -v):
[✓] Flutter(通道:稳定,v1.17.1,在 Mac OS X 10.15.1 19B88 上,区域设置为 en-GB)

[✓] 用于 Android 设备的 Android 工具链(Android SDK 版本 29.0.2)
[✓] 用于 iOS 和 macOS 的 Xcode(Xcode 11.2.1)
[✓] Android Studio(版本 4.0)
[✓] VS Code(版本 1.48.0)
[✓] 已连接的设备(1 个可用)

• 未发现问题!

崩溃日志:

08-31 10:24:07.816 E/AndroidRuntime(23702): FATAL EXCEPTION: main
08-31 10:24:07.816 E/AndroidRuntime(23702): Process: com.craypay.app, PID: 23702
08-31 10:24:07.816 E/AndroidRuntime(23702): java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Surface android.media.ImageReader.getSurface()' on a null object reference
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at f.b.c.b.g.d(Unknown Source:5)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at f.b.c.b.g$b.onOpened(Unknown Source:7)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:143)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Handler.handleCallback(Handler.java:873)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Handler.dispatchMessage(Handler.java:99)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Looper.loop(Looper.java:193)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.app.ActivityThread.main(ActivityThread.java:6680)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at java.lang.reflect.Method.invoke(Native Method)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

此外,我已尝试了此线程中的几乎所有解决方案,但没有成功。

英文:

Whenever i try to open front camera from camera plugin in my project app crashes on Pixel 3XL, however app works fine on back camera.

plugin version : camera: ^0.5.8+1

My camera class.

class CameraState extends State&lt;Camera&gt; with WidgetsBindingObserver {
  CameraController controller;
  List&lt;CameraDescription&gt; cameras;

  @override initState() {
    super.initState();
    getCameras();
  }

  void getCameras() async {
    cameras = await availableCameras();
    cameras.forEach((camera) {
      if (camera.lensDirection == CameraLensDirection.front) {
        onNewCameraSelected(camera);
      }
    });
  }

  /// Returns a suitable camera icon for [direction].
  IconData getCameraLensIcon(CameraLensDirection direction) {
    switch (direction) {
      case CameraLensDirection.back:
        return Icons.camera_rear;
      case CameraLensDirection.front:
        return Icons.camera_front;
      case CameraLensDirection.external:
        return Icons.camera;
    }
    throw ArgumentError(&#39;Unknown lens direction&#39;);
  }

  /// Display the preview from the camera (or a message if the preview is not available).
  Widget _cameraPreviewWidget() {
    if (controller == null || !controller.value.isInitialized) {
      return new Center(
        child: new Text(
          allTranslations.text(&#39;camera_no&#39;),
          style: TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.w600,
              fontFamily: fontMontserrat,
              fontStyle: FontStyle.normal,
              fontSize: 24.0),
        ),
      );
    } else {
      final size = MediaQuery.of(context).size;
      final deviceRatio = size.width / size.height;
      return Transform.scale(
        scale: controller.value.aspectRatio / deviceRatio,
        child: Center(
          child: AspectRatio(
            aspectRatio: controller.value.aspectRatio,
            child: CameraPreview(controller),
          ),
        ),
      );
    }
  }

  String timestamp() =&gt; DateTime.now().millisecondsSinceEpoch.toString();

  void onNewCameraSelected(CameraDescription cameraDescription) async {
    if (controller != null) {
      await controller.dispose();
    }
    controller = CameraController(cameraDescription, ResolutionPreset.medium, enableAudio: false);

    controller.addListener(() {
      if (mounted) setState(() {});
    });

    try {
      ///
      /// APP CRASHES HERE.
      /// 
      await controller.initialize();
    } on CameraException catch (e) {
        print(e);
    }

    if (mounted) {
      setState(() {});
    }
  }

  void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (filePath != null) {
       // Navigate to other screen.
      }
    });
  }

  Future&lt;String&gt; takePicture() async {
    if (!controller.value.isInitialized) {
      return null;
    }
    final Directory extDir = await getApplicationDocumentsDirectory();
    final String dirPath = &#39;${extDir.path}/Pictures/flutter_test&#39;;
    await Directory(dirPath).create(recursive: true);
    final String filePath = &#39;$dirPath/${timestamp()}.jpg&#39;;

    if (controller.value.isTakingPicture) {
      // A capture is already pending, do nothing.
      return null;
    }

    try {
      await controller.takePicture(filePath);
    } on CameraException catch (e) {
      return null;
    }
    return filePath;
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: &lt;Widget&gt;[
        Positioned(
          left: 0, top: 0, right: 0, bottom: 0,
          child: _cameraPreviewWidget(),
        ),
        Scaffold(
          body: new Container(
            color: Colors.transparent,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: &lt;Widget&gt;[
                new Text(allTranslations.text(&#39;licensescan_back&#39;),
                    textAlign: TextAlign.center,
                    style: const TextStyle(
                        color:  Colors.white,
                        fontWeight: FontWeight.w400,
                        fontFamily: fontSourceSansPro,
                        fontStyle:  FontStyle.normal,
                        fontSize: 18.0
                    )
                ),
                Container(height: 10),
                Padding(
                  padding: new EdgeInsets.only(left: 40, right: 40),
                  child: new Text(allTranslations.text(&#39;licensescan_positionback&#39;),
                      textAlign: TextAlign.center,
                      style: const TextStyle(
                          color:  Colors.white,
                          fontWeight: FontWeight.w400,
                          fontFamily: fontSourceSansPro,
                          fontStyle:  FontStyle.normal,
                          fontSize: 13.0
                      )
                  ),
                ),
                Expanded(child: new Container()),
                new FlatButton(
                    onPressed: onTakePictureButtonPressed,
                    child: new Container(
                      width: 54, height: 54,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(27),
                          border: Border.all(
                              color: Colors.white
                          ),
                          color: Colors.transparent
                      ),
                      child: Center(
                        child: new Container(
                          width: 45, height: 45,
                          decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(22.5),
                              color: Colors.white
                          ),
                        ),
                      ),
                    )
                ),
                new Container(height: 58)
              ],
            ),
          ),
        )
      ],
    );
  }
}

Flutter doctor output

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.1, on Mac OS X 10.15.1 19B88, locale en-GB)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.48.0)
[✓] Connected device (1 available)

• No issues found!

Crash logs

08-31 10:24:07.816 E/AndroidRuntime(23702): FATAL EXCEPTION: main
08-31 10:24:07.816 E/AndroidRuntime(23702): Process: com.craypay.app, PID: 23702
08-31 10:24:07.816 E/AndroidRuntime(23702): java.lang.NullPointerException: Attempt to invoke virtual method &#39;android.view.Surface android.media.ImageReader.getSurface()&#39; on a null object reference
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at f.b.c.b.g.d(Unknown Source:5)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at f.b.c.b.g$b.onOpened(Unknown Source:7)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:143)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Handler.handleCallback(Handler.java:873)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Handler.dispatchMessage(Handler.java:99)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.os.Looper.loop(Looper.java:193)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at android.app.ActivityThread.main(ActivityThread.java:6680)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at java.lang.reflect.Method.invoke(Native Method)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
08-31 10:24:07.816 E/AndroidRuntime(23702): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Also tried almost all solutions on this thread but no luck.

答案1

得分: 1

我在使用相机的 takePicture 函数时遇到了崩溃。

> "java.lang.NullPointerException: 尝试调用虚拟方法 'int
> io.flutter.embedding.engine.systemchannels.PlatformChannel$DeviceOrientation.ordinal()',
> 但空对象引用 E/AndroidRuntime(18591): at
> io.flutter.plugins.camera.DeviceOrientationManager.getMediaOrientation(DeviceOrientationManager.java:58)"

对我来说,将以下内容添加后问题得到了解决:

在 initialize() 之后添加 await controller.lockCaptureOrientation()。你可以尝试这样做,也许对你有帮助。

try {
    ///
    /// APP 在这里崩溃。
    /// 
    await controller.initialize();
    await controller.lockCaptureOrientation();
}
英文:

I had crash with camera takepicture function.

> "java.lang.NullPointerException: Attempt to invoke virtual method 'int
> io.flutter.embedding.engine.systemchannels.PlatformChannel$DeviceOrientation.ordinal()'
> on a null object reference E/AndroidRuntime(18591): at
> io.flutter.plugins.camera.DeviceOrientationManager.getMediaOrientation(DeviceOrientationManager.java:58)"

For me helped adding
await controller.lockCaptureOrientation() after initialize().
Try this, maybe it will help you

   try {
          ///
          /// APP CRASHES HERE.
          /// 
          await controller.initialize();
          await controller.lockCaptureOrientation();

        }

huangapple
  • 本文由 发表于 2020年8月31日 20:09:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63670546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定