Nib*_*ain 9 video camera android dart flutter
如何正确初始化和处理相机控制器。我在用 camera: ^0.9.4+5
与许多人一起
\n\n\n\n
我在单击切换相机按钮时收到此错误:
\n======== Exception caught by widgets library =======================================================\nThe following CameraException was thrown building ValueListenableBuilder<CameraValue>(dirty, state: _ValueListenableBuilderState<CameraValue>#47f17):\nCameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.)\nRun Code Online (Sandbox Code Playgroud)\n这是完整的代码:
\nclass VideoRecorderScreen extends StatefulWidget {\n @override\n _VideoRecorderScreenState createState() {\n return _VideoRecorderScreenState();\n }\n\n //final ApplicantData applicantData;\n final String videorec;\n \n\n VideoRecorderScreen(this.applicationId, this.name, this.description,\n this.descriptionHindi, this.videorec,\n {this.isOpenSubsDashboard = false});\n}\n\nclass _VideoRecorderScreenState extends State<VideoRecorderScreen> {\n CameraController controller;\n XFile videoPath;\n List<CameraDescription> cameras;\n int selectedCameraIdx = 1;\n int videoElapseTime = 25;\n int videoMinElapseTime = 20;\n \n bool visibilityStop = false;\n bool visibilityButtons = false;\n String timer = "00:00";\n CountdownTimer cd;\n bool startRecording = false;\n\nvoid _reset() {\n videoPath = null;\n _changed(false);\n _changedTimer("00:00");\n _changedButtonVisibility(false);\n }\n\n void _changed(bool visibility) {\n if (mounted) setState(() {\n visibilityStop = visibility;\n });\n }\n\n void _changedTimer(String time) {\n if (mounted) setState(() {\n timer = time;\n });\n }\n\n void _changedButtonVisibility(bool visibility) {\n if (mounted) setState(() {\n visibilityButtons = visibility;\n });\n }\n\n void _navigateAndDisplaySelection(BuildContext context) async {\n final result = await Navigator.push(\n context,\n MaterialPageRoute(\n builder: (context) => VideoPlayerScreen(\n videoPath: videoPath.path,\n applicationId: widget.applicationId,\n name: widget.name,\n dateTime: selectedDate,\n isOpenSubsDashboard: widget.isOpenSubsDashboard)),\n );\n\n if (result) {\n _reset();\n }\n }\n\n\n @override\n void initState() {\n super.initState();\n \n\n WidgetsBinding.instance.addPostFrameCallback((_) =>\n showSnackBar(\'User Validated Successfully! Welcome \' + widget.name));\n\n \n availableCameras().then((availableCameras) {\n cameras = availableCameras;\n\n if (cameras.length > 0) {\n \n for (int i = 0; i < cameras.length; i++) {\n if (cameras[i].lensDirection == CameraLensDirection.front) {\n if (mounted) setState(() {\n selectedCameraIdx = i;\n });\n }\n }\n\n _onCameraSwitched(cameras[selectedCameraIdx]).then((void v) {});\n }\n }).catchError((err) {\n print(\'Error: $err.code\\nError Message: $err.message\');\n });\n }\n\n\n @override\n Widget build(BuildContext context) {\n var size = MediaQuery.of(context).size.width * (2 / 3);\n return WillPopScope(\n onWillPop: _onBackPressed,\n child: Scaffold(\n key: _scaffoldKey,\n appBar: AppBarWidget(\n title: \'Record Your Video\',\n actions: [\n IconButton(\n icon: Icon(\n Icons.call,\n \n ),\n onPressed: () {\n ConstantMethods.callToSupport();\n }),\n AppBarLogo(),\n ],\n ),\n body: Builder(builder: (BuildContext buildContext) {\n scaffold = Scaffold.of(buildContext);\n return Container(\n child: ListView(\n \n children: <Widget>[\n \n Center(\n child: Container(\n width: size / 1.5,\n height: size / 1.5,\n \n Container(\n padding: EdgeInsets.all(5.0),\n color: Colors.grey[850],\n child: Text(\n selectedDate != null ? selectedDate : "",\n textAlign: TextAlign.start,\n \n ),\n ],\n ),\n ))\n : Column(\n mainAxisAlignment: MainAxisAlignment.center,\n crossAxisAlignment: CrossAxisAlignment.center,\n children: <Widget>[\n VerticalSpacing(20.0),\n Padding(\n padding:\n const EdgeInsets.only(left: 8.0, right: 8.0),\n child: Text(\n \'Click on video icon to start the recording\',\n textAlign: TextAlign.justify,\n \n FlatButton(\n child: Text(\' Proceed for Recording \'),\n onPressed: () {\n if (mounted) setState(() {\n startRecording = true;\n });\n },\n ),\n VerticalSpacing(10.0),\n FlatButton(\n\n textColor: ThemeColors.colorPrimary,\n VerticalSpacing(20.0),\n ],\n ),\n startRecording\n ? Padding(\n padding: const EdgeInsets.all(5.0),\n child: Row(\n mainAxisAlignment: MainAxisAlignment.spaceBetween,\n children: <Widget>[\n _cameraTogglesRowWidget(),\n \n _captureControlRowWidget(),\n Expanded(\n child: Text("$timer",\n textAlign: TextAlign.end,\n style: TextStyle(\n fontSize: Consts.fontSizeMedium)),\n ),\n ],\n ),\n )\n : new Container(),\n \n !visibilityButtons\n ? Column(\n \n children: [\n Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,\n //alignment: Alignment.bottomRight,\n children: [\n IconButton(\n icon: const Icon(Icons.info_outline,\n size: 25.0),\n color: ThemeColors.colorPrimary,\n onPressed: () {\n showDialog(\n context: context,\n builder: (BuildContext context) =>\n MessageDialog(\n title: "ImportantTips",\n message: Languages.of(context)\n .videoPreInstruction,\n ),\n );\n \n },\n ),\n ToggleButtons(\n borderColor: ThemeColors.colorAccent,\n fillColor: Colors.lightBlue[100],\n borderWidth: 1,\n selectedBorderColor: ThemeColors.colorAccent,\n selectedColor: Colors.blue[900],\n color: ThemeColors.colorPrimary,\n borderRadius: BorderRadius.circular(10),\n children: <Widget>[\n Padding(\n padding: const EdgeInsets.only(\n left: 12.0, right: 8.0),\n child: Text(\n \'In English\',\n textAlign: TextAlign.center,\n style: TextStyle(\n fontSize: Consts.fontSizeSmall),\n ),\n ),\n Padding(\n padding: const EdgeInsets.only(\n left: 8.0, right: 8.0),\n child: Text(\n \'\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 \xe0\xa4\xae\xe0\xa5\x87\xe0\xa4\x82 \',\n textAlign: TextAlign.center,\n style: TextStyle(\n fontSize: Consts.fontSizeSmall),\n ),\n ),\n ],\n onPressed: (int index) {\n if(this.mounted) setState(() {\n for (int i = 0;\n i < isSelectedLanguage.length;\n i++) {\n if (i == index) {\n isSelectedLanguage[i] = true;\n } else {\n isSelectedLanguage[i] = false;\n }\n }\n if (isSelectedLanguage[0]) {\n changeLanguage(context, \'en\');\n } else if (isSelectedLanguage[1]) {\n changeLanguage(context, \'hi\');\n }\n });\n },\n isSelected: isSelectedLanguage,\n )\n ]),\n VerticalSpacing(10.0),\n \n Padding(\n padding:\n const EdgeInsets.only(left: 8.0, right: 8.0),\n child\n : Row(\n mainAxisAlignment: MainAxisAlignment.center,\n children: <Widget>[\n OutlineButton(\n padding: EdgeInsets.all(5.0),\n splashColor: Colors.blue[300],\n borderSide:\n BorderSide(color: ThemeColors.colorPrimary),\n child: Text(\' Retake Video \',\n style: TextStyle(\n color: Colors.blue,\n fontSize: Consts.fontSizeMedium)),\n onPressed: () {\n _reset();\n },\n ),\n HorizontalSpacing(10.0),\n FlatButton(\n padding: EdgeInsets.all(5.0),\n color: ThemeColors.colorPrimary,\n// splashColor: Colors.greenAccent,\n textColor: ThemeColors.white,\n\n child: Text(\' Play Recording \',\n style:\n TextStyle(fontSize: Consts.fontSizeMedium)),\n onPressed: () {\n if(videoPath!=null) {\n _navigateAndDisplaySelection(context);\n } else{\n //ConstantMethods.showToast("Technical exception with camera.");\n ConstantMethods.showToast("There is some issue in recording video right now, please try again later.");\n _onBackPressed();\n }\n },\n ),\n ],\n ),\n VerticalSpacing(10.0),\n ],\n ));\n })),\n );\n }\n\n IconData _getCameraLensIcon(CameraLensDirection direction) {\n switch (direction) {\n case CameraLensDirection.back:\n return Icons.camera_rear;\n case CameraLensDirection.front:\n return Icons.camera_front;\n case CameraLensDirection.external:\n return Icons.camera;\n default:\n return Icons.device_unknown;\n }\n }\n\n // Display \'Loading\' text when the camera is still loading.\n Widget _cameraPreviewWidget(var size) {\n if (controller == null || !controller.value.isInitialized) {\n return const Text(\n \'Loading\',\n style: TextStyle(\n color: ThemeColors.white,\n fontSize: 20.0,\n fontWeight: FontWeight.w900,\n ),\n );\n }\n\n return Container(\n width: size,\n height: size,\n child: ClipRect(\n child: OverflowBox(\n alignment: Alignment.center,\n child: FittedBox(\n fit: BoxFit.fitWidth,\n child: Container(\n width: size,\n height: size / controller.value.aspectRatio,\n// height: size / controller.value.aspectRatio,\n child: CameraPreview(controller),\n\n // this is my CameraPreview\n ),\n ),\n ),\n ),\n );\n\n \n }\n\n /// Display a row of toggle to select the camera (or a message if no camera is available).\n Widget _cameraTogglesRowWidget() {\n if (cameras == null) {\n return Row();\n }\n\n CameraDescription selectedCamera =\n cameras[selectedCameraIdx]; \n CameraLensDirection lensDirection =\n selectedCamera.lensDirection; \n //CameraLensDirection lensDirection = CameraLensDirection.front;\n\n return Expanded(\n child: Align(\n alignment: Alignment.centerLeft,\n child: FlatButton.icon(\n onPressed: controller != null && controller.value.isRecordingVideo\n ? null\n : _onSwitchCamera,\n icon: Icon(_getCameraLensIcon(lensDirection)),\n label: Text(\n "${lensDirection.toString().substring(lensDirection.toString().indexOf(\'.\') + 1)}")),\n ),\n );\n }\n\n /// Display the control bar with buttons to record videos.\n Widget _captureControlRowWidget() {\n return Expanded(\n child: Align(\n alignment: Alignment.center,\n child: Row(\n mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n mainAxisSize: MainAxisSize.max,\n children: <Widget>[\n IconButton(\n icon: const Icon(Icons.videocam, size: 40.0),\n color: ThemeColors.colorPrimary,\n onPressed: controller != null &&\n controller.value.isInitialized &&\n !controller.value.isRecordingVideo &&\n videoPath == null\n ? _onRecordButtonPressed\n : null,\n ),\n IconButton(\n icon: const Icon(Icons.stop, size: 40.0),\n color: ThemeColors.red,\n onPressed: controller != null &&\n controller.value.isInitialized &&\n controller.value.isRecordingVideo &&\n visibilityStop\n ? _onStopButtonPressed\n : null,\n ),\n// : new Container(),\n ],\n ),\n ),\n );\n }\n\n String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();\n\n Future<void> _onCameraSwitched(CameraDescription description) async {\n\n if (description == null) {\n return;\n }\n if(!(controller != null && controller.value.isRecordingVideo)){\n onNewCameraSelected(description);\n }\n\n \n }\n\n void onNewCameraSelected(CameraDescription cameraDescription) async {\n if (controller != null) {\n await controller.dispose();\n }\n\n controller = CameraController(\n cameraDescription, ResolutionPreset.low\n );\n\n //controller = cameraController;\n\n // If the controller is updated then update the UI.\n controller.addListener(() {\n if (mounted) setState(() {});\n if (controller.value.hasError) {\n Fluttertoast.showToast(\n msg: \'Camera error ${controller.value.errorDescription}\',\n toastLength: Toast.LENGTH_SHORT,\n gravity: ToastGravity.CENTER,\n timeInSecForIosWeb: 1,\n backgroundColor: ThemeColors.red,\n textColor: ThemeColors.white);\n }\n });\n\n try {\n await controller.initialize();\n } on CameraException catch (e) {\n _showCameraException(e);\n }\n\n if (mounted) {\n setState(() {});\n }\n }\n\n void _onSwitchCamera() {\n selectedCameraIdx =\n selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0;\n CameraDescription selectedCamera = cameras[selectedCameraIdx];\n\n _onCameraSwitched(selectedCamera);\n\n if (mounted) setState(() {\n selectedCameraIdx = selectedCameraIdx;\n });\n }\n\n void _onRecordButtonPressed() {\n _startVideoRecording().then((_) {\n /*if (mounted) setState(() {});*/\n //if (filePath != null) {\n final df = new DateFormat(\'dd-MM-yyyy hh:mm a\');\n String date = df.format(new DateTime.now());\n\n if (mounted) setState(() {\n// selectedDate = date1.replaceAll("/", "-");\n selectedDate = date;\n });\n\n Fluttertoast.showToast(\n msg: \'Recording video started\',\n toastLength: Toast.LENGTH_SHORT,\n gravity: ToastGravity.CENTER,\n timeInSecForIosWeb: 1,\n backgroundColor: ThemeColors.grey,\n textColor: ThemeColors.white);\n // }\n });\n }\n\n void _onStopButtonPressed() {\n if (cd.isRunning) {\n cd.cancel();\n }\n\n _stopVideoRecording().then((file) {\n if (mounted) setState(() {});\n if (file != null) {\n showInSnackBar(\'Video recorded to ${file.path}\');\n videoPath = file;\n }\n\n });\n }\n\n Future<void> _star
解决此问题的一种方法是使用 WidgetsBindingObserver - 这有助于管理应用程序的生命周期。继承类中的 WidgetsBidingObserver_VideoRecorderScreenState以正确处理相机。此GitHub 问题线程演示了类似的方法。
| 归档时间: |
|
| 查看次数: |
4792 次 |
| 最近记录: |