fluttercandies / flutter_wechat_camera_picker

A camera picker (take photos and videos) for Flutter projects based on WeChat's UI. It's a standalone module of wechat_assets_picker yet it can be run separately.
https://pub.dev/packages/wechat_camera_picker
Apache License 2.0
366 stars 145 forks source link

[BUG] iOS camera preview crashes when switching app #155

Closed lcuis closed 1 year ago

lcuis commented 1 year ago

Hello! Thanks a lot for this great plugin!

Describe the bug Whole app crashes on iOS when in preview and switching back to the app from another one. Not reproduced on Android.

How to reproduce Plugin example app gives an exception in the same situation. However, it does not really crash the example app as it does on my production app.

Steps to reproduce the behavior:

  1. Open plugin example app on iOS with logs visible.
  2. Open first line (take a photo).
  3. While on the preview screen, switch to another app.
  4. Switch back to example app.

Expected behavior No Exception raised.

Effective behavior Exception raised.

Screenshots (If contains) :

======== Exception caught by widgets library =======================================================
The following CameraException was thrown building ValueListenableBuilder<CameraValue>(dirty, state: _ValueListenableBuilderState<CameraValue>#c046c):
CameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.)

The relevant error-causing widget was: 
  CameraPreview CameraPreview:file:///Users/hindl/StudioProjects/flutter_wechat_camera_picker/lib/src/states/camera_picker_state.dart:1230:15
When the exception was thrown, this was the stack: 
#0      CameraController._throwIfNotInitialized (package:camera/src/camera_controller.dart:814:7)
#1      CameraController.buildPreview (package:camera/src/camera_controller.dart:569:5)
#2      CameraPreview.build.<anonymous closure> (package:camera/src/camera_preview.dart:36:57)
#3      _ValueListenableBuilderState.build (package:flutter/src/widgets/value_listenable_builder.dart:186:26)
#4      StatefulElement.build (package:flutter/src/widgets/framework.dart:4992:27)
#5      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4878:15)
#6      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#7      Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#8      StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#9      Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#11     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#12     StatelessElement.update (package:flutter/src/widgets/framework.dart:4956:5)
#13     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#14     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#15     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#16     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#17     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#19     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#20     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#21     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#22     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#23     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#24     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#25     StatelessElement.update (package:flutter/src/widgets/framework.dart:4956:5)
#26     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#27     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#28     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#29     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#30     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#31     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#32     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#33     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#34     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#35     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#36     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#37     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#38     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#39     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#40     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#41     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#42     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5904:32)
#43     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6460:17)
#44     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#45     _LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:135:18)
#46     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2605:19)
#47     _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:153:12)
#48     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2246:59)
#49     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1035:15)
#50     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2246:14)
#51     RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:228:7)
#52     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:316:5)
#53     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1973:7)
#54     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:999:18)
#55     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:513:19)
#56     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884:13)
#57     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#58     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#59     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#60     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#61     _invoke (dart:ui/hooks.dart:148:13)
#62     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#63     _drawFrame (dart:ui/hooks.dart:115:31)
====================================================================================================

Version information

Additional context .

lcuis commented 1 year ago

I don't have the error anymore on flutter run with the following version of didChangeAppLifecycleState in camera_picker_state.dart:

@override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    final CameraController? c = innerController;
    if (c == null && state == AppLifecycleState.resumed) {
      initCameras(currentCamera);
    }
    // App state changed before we got the chance to initialize.
    if (c == null || !c.value.isInitialized) {
      return;
    }
    if (state == AppLifecycleState.inactive) {
      c.dispose();
      innerController = null;
    } else if (state == AppLifecycleState.resumed) {
      initCameras(currentCamera);
    }
  }

I am not proposing a PR for this yet because I need to make sure this solves the issue as well when running from test flight in a near production situation.

lcuis commented 1 year ago

Works fine on test-flight => proposed PR #157

lcuis commented 1 year ago

Thanks for the merge @AlexV525 !