|
- import 'dart:io';
-
- import 'package:camera/camera.dart';
- import 'package:farm_tpf/main.dart';
- import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
- import 'package:file_picker/file_picker.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:path_provider/path_provider.dart';
-
- class CameraHelper extends StatefulWidget {
- @override
- _CameraHelperState createState() => _CameraHelperState();
- }
-
- /// 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('Unknown lens direction');
- }
-
- void logError(String code, String message) => print('Error: $code\nError Message: $message');
-
- class _CameraHelperState extends State<CameraHelper> with WidgetsBindingObserver {
- CameraController? controller;
- String? imagePath;
- String? videoPath;
- VoidCallback? videoPlayerListener;
- bool enableAudio = true;
- int indexCamera = 0;
-
- @override
- void initState() {
- super.initState();
- controller = CameraController(cameras[indexCamera], ResolutionPreset.medium);
- controller?.initialize().then((_) {
- if (!mounted) {
- return;
- }
- setState(() {});
- });
- WidgetsBinding.instance.addObserver(this);
- }
-
- @override
- void dispose() {
- WidgetsBinding.instance.removeObserver(this);
- super.dispose();
- }
-
- @override
- void didChangeAppLifecycleState(AppLifecycleState state) {
- // App state changed before we got the chance to initialize.
- if (controller == null || !controller!.value.isInitialized) {
- return;
- }
- if (state == AppLifecycleState.inactive) {
- controller?.dispose();
- } else if (state == AppLifecycleState.resumed) {
- if (controller != null) {
- onNewCameraSelected(controller!.description);
- }
- }
- }
-
- final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- key: _scaffoldKey,
- body: SafeArea(
- top: false,
- bottom: false,
- child: Column(
- children: <Widget>[
- Expanded(
- child: Container(
- child: Padding(
- padding: const EdgeInsets.all(1.0),
- child: Center(
- child: _cameraPreviewWidget(),
- ),
- ),
- decoration: BoxDecoration(
- color: Colors.black,
- border: Border.all(
- color: controller != null && controller!.value.isRecordingVideo ? Colors.redAccent : Colors.grey,
- width: controller != null && controller!.value.isRecordingVideo ? 1.0 : 0.0,
- ),
- ),
- ),
- ),
- _captureControlRowWidget(),
- ],
- ),
- ),
- );
- }
-
- /// Display the preview from the camera (or a message if the preview is not available).
- Widget _cameraPreviewWidget() {
- if (controller == null || !controller!.value.isInitialized) {
- return const Text(
- 'Đang mở camera ....',
- style: TextStyle(
- color: Colors.white,
- fontSize: 18.0,
- fontWeight: FontWeight.w900,
- ),
- );
- } else {
- return AspectRatio(
- aspectRatio: controller!.value.aspectRatio,
- child: CameraPreview(controller!),
- );
- }
- }
-
- /// Display the control bar with buttons to take pictures and record videos.
- Widget _captureControlRowWidget() {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- mainAxisSize: MainAxisSize.max,
- children: <Widget>[
- IconButton(
- icon: Icon(Icons.arrow_back),
- onPressed: () {
- Get.back();
- }),
- _cameraTogglesRowWidget(),
- IconButton(
- icon: const Icon(
- Icons.camera_alt,
- size: 30,
- ),
- color: Colors.blue,
- onPressed: controller != null && controller!.value.isInitialized && !controller!.value.isRecordingVideo ? onTakePictureButtonPressed : null,
- ),
- // IconButton(
- // icon: const Icon(Icons.videocam, size: 35),
- // color: Colors.blue,
- // onPressed: controller != null && controller.value.isInitialized && !controller.value.isRecordingVideo ? onVideoRecordButtonPressed : null,
- // ),
- // IconButton(
- // icon: controller != null && controller.value.isRecordingPaused ? Icon(Icons.play_arrow) : Icon(Icons.pause),
- // color: Colors.blue,
- // onPressed: controller != null && controller.value.isInitialized && controller.value.isRecordingVideo
- // ? (controller != null && controller.value.isRecordingPaused ? onResumeButtonPressed : onPauseButtonPressed)
- // : null,
- // ),
- // IconButton(
- // icon: const Icon(Icons.stop),
- // color: Colors.red,
- // onPressed: controller != null && controller.value.isInitialized && controller.value.isRecordingVideo ? onStopButtonPressed : null,
- // )
- ],
- );
- }
-
- /// Display a row of toggle to select the camera (or a message if no camera is available).
- Widget _cameraTogglesRowWidget() {
- if (cameras.isEmpty) {
- return const Text('Không có camera');
- } else {
- bool disableSwitch = controller != null && controller!.value.isRecordingVideo;
- if (indexCamera == cameras.length - 1) {
- indexCamera = 0;
- } else {
- indexCamera++;
- }
- return IconButton(
- icon: Icon(
- Icons.switch_camera,
- color: Colors.green,
- ),
- onPressed: disableSwitch == true
- ? null
- : () {
- onNewCameraSelected(cameras[indexCamera]);
- });
- }
- }
-
- String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
-
- void showInSnackBar(String message) {
- Utils.showSnackBarError(message: message);
- }
-
- void onNewCameraSelected(CameraDescription cameraDescription) async {
- if (controller != null) {
- await controller?.dispose();
- }
- controller = CameraController(
- cameraDescription,
- ResolutionPreset.medium,
- enableAudio: enableAudio,
- );
-
- // If the controller is updated then update the UI.
- controller?.addListener(() {
- if (mounted) setState(() {});
- if (controller!.value.hasError) {
- showInSnackBar('Lỗi camera: ${controller?.value.errorDescription}');
- }
- });
-
- try {
- await controller?.initialize();
- } on CameraException catch (e) {
- _showCameraException(e);
- }
-
- if (mounted) {
- setState(() {});
- }
- }
-
- void onTakePictureButtonPressed() {
- takePicture().then((String filePath) {
- if (mounted) {
- setState(() {
- imagePath = filePath;
- // videoController?.dispose();
- // videoController = null;
- });
- if (filePath != null) {
- print('Picture saved to $filePath');
- Get.back(result: [filePath, false]);
- }
- }
- });
- }
-
- void onVideoRecordButtonPressed() {
- startVideoRecording().then((String filePath) {
- if (mounted) setState(() {});
- if (filePath != null) {
- print('Saving video to $filePath');
- }
- });
- }
-
- void onStopButtonPressed() {
- stopVideoRecording().then((_) {
- if (mounted) setState(() {});
- {
- print('Video recorded to: $videoPath');
- Get.back(result: [videoPath, true]);
- }
- });
- }
-
- void onPauseButtonPressed() {
- pauseVideoRecording().then((_) {
- if (mounted) setState(() {});
- print('Video recording paused');
- });
- }
-
- void onResumeButtonPressed() {
- resumeVideoRecording().then((_) {
- if (mounted) setState(() {});
- print('Video recording resumed');
- });
- }
-
- Future<String> startVideoRecording() async {
- if (!controller!.value.isInitialized) {
- showInSnackBar('Vui lòng chọn camera');
- return '';
- }
-
- final Directory extDir = await getApplicationDocumentsDirectory();
- final String dirPath = '${extDir.path}/Movies/tpf';
- await Directory(dirPath).create(recursive: true);
- final String filePath = '$dirPath/${timestamp()}.mp4';
-
- if (controller!.value.isRecordingVideo) {
- // A recording is already started, do nothing.
- return '';
- }
-
- try {
- videoPath = filePath;
- // await controller?.startVideoRecording(filePath ?? '');
- } on CameraException catch (e) {
- _showCameraException(e);
- return '';
- }
- return filePath;
- }
-
- Future<void> stopVideoRecording() async {
- if (!controller!.value.isRecordingVideo) {
- return null;
- }
-
- try {
- await controller?.stopVideoRecording();
- } on CameraException catch (e) {
- _showCameraException(e);
- return null;
- }
- }
-
- Future<void> pauseVideoRecording() async {
- if (!controller!.value.isRecordingVideo) {
- return null;
- }
-
- try {
- await controller?.pauseVideoRecording();
- } on CameraException catch (e) {
- _showCameraException(e);
- rethrow;
- }
- }
-
- Future<void> resumeVideoRecording() async {
- if (!controller!.value.isRecordingVideo) {
- return null;
- }
-
- try {
- await controller?.resumeVideoRecording();
- } on CameraException catch (e) {
- _showCameraException(e);
- rethrow;
- }
- }
-
- Future<String> takePicture() async {
- if (!controller!.value.isInitialized) {
- showInSnackBar('Vui lòng chọn camera');
- return '';
- }
- final Directory extDir = await getApplicationDocumentsDirectory();
- final String dirPath = '${extDir.path}/Pictures/tpf';
- await Directory(dirPath).create(recursive: true);
- String filePath = '$dirPath/${timestamp()}.jpg';
-
- if (controller!.value.isTakingPicture) {
- // A capture is already pending, do nothing.
- return '';
- }
-
- try {
- var xFile = await controller?.takePicture(); //.takePicture(filePath);
- filePath = xFile?.path ?? '';
- } on CameraException catch (e) {
- _showCameraException(e);
- return '';
- }
- return filePath;
- }
-
- void _showCameraException(CameraException e) {
- logError(e.code, e.description ?? '');
- showInSnackBar('Lỗi: ${e.code}\n${e.description}');
- }
- }
|