I refactored taking a photo code of AVLE.
Taking a photo was working well in desktop but it was not in mobile devices.
I've struggled all day to find out the cause and finally resolved the issue.
What I did was to change camera package from image_picker_web
to image_picker_for_web
.
Previously I used this
https://pub.dev/packages/image_picker_web
( I thought this is by Flutter.dev team)Now I use this by Flutter.dev team
https://pub.dev/packages/image_picker_for_web
And I noticed that taking a photo function is different on different browsers. For example, Safari and Samsung browsers show the camera option when choosing 'Gallery' but Chrome and Brave do not.
I confirmed that taking a photo on mobile devices is working great!
Here is the code for Flutter to capture an image from a camera
camera control class
class CameraControl {
late List<CameraDescription> cameras;
CameraController? controller;
int cameraIndex = 0;
CameraControl() {
// initialize();
}
Future<void> initialize() async {
cameras = await availableCameras();
print('CameraControl. initialize. cameras: $cameras');
print('CameraControl. initialize. camera count: ${cameras.length}');
if (cameras.length > 0) {
await onNewCameraSelected(cameras[0]);
print('CameraControl. onNewCameraSelected');
}
}
Future<void> onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
print('onNewCameraSelected. dispose controller first');
await controller!.dispose();
}
final CameraController cameraController = CameraController(
cameraDescription,
ResolutionPreset.max,
enableAudio: false,
imageFormatGroup: ImageFormatGroup.jpeg,
);
controller = cameraController;
try {
await cameraController.initialize();
print('onNewCameraSelected. camera is initialized');
} on CameraException catch (e) {
print('camera execption: $e');
}
}
Future<void> switchCamera() async {
// if (cameraIndex == 0 && cameras.length > 0) {
// cameraIndex = 1;
// }
// if (cameraIndex > 0) {
// cameraIndex = 0;
// }
print('switch camera. before. cameraIndex: $cameraIndex');
cameraIndex++;
if (cameraIndex >= cameras.length) {
cameraIndex = 0;
}
print('switch camera. after cameraIndex: $cameraIndex');
print('camera description: ${cameras[cameraIndex]}');
await onNewCameraSelected(cameras[cameraIndex]);
}
Future<XFile?> takeSceenshot() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isInitialized) {
print('Camera is empty');
return null;
}
try {
XFile file = await cameraController.takePicture();
return file;
} on CameraException catch (e) {
print('failed to take sceenshot. $e');
// TODO: show snackbar
// dispose controller
controller!.dispose();
return null;
}
}
Future<void> disposeController() async {
if (controller != null) {
await controller!.dispose();
}
}
}
capture main
_capturePhoto({required BuildContext context}) async {
printWarning('capture video');
// close the bottom sheet
Get.back();
CameraControl cameraController = CameraControl();
await cameraController.initialize();
showCameraDialog(
cameraController: cameraController,
onTakeStarted: () {
if (onImageSelected != null) {
onImageSelected!();
}
},
onPhotoTaken: (frame) {
// dispose the camera
cameraController.disposeController();
_uploadCameraImage(frame: frame);
},
);
}
Capture stream dialog
showCameraDialog({
required CameraControl cameraController,
required VoidCallback onTakeStarted,
required Function onPhotoTaken,
}) {
Get.defaultDialog(
title: 'CameraDialog_title'.tr,
content: _buildBody(
cameraController: cameraController,
onTakeStarted: onTakeStarted,
onPhotoTaken: onPhotoTaken,
),
);
}
Widget _buildBody({
required CameraControl cameraController,
required VoidCallback onTakeStarted,
required Function onPhotoTaken,
}) {
if (cameraController.controller == null || cameraController.cameras.isEmpty) {
print('camera dialog. No camera found');
return const CircularProgressIndicator();
}
print('camera dialog build body');
return StatefulBuilder(
builder: (context, setState) {
print(
'camera dialog builder. camera controller: ${cameraController.controller}');
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 1.5,
child: Column(
children: [
Expanded(
child: Card(
child: CameraPreview(
cameraController.controller!,
child: LayoutBuilder(builder:
(BuildContext context, BoxConstraints constraints) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
);
}),
),
),
),
const Divider(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TextButton(
onPressed: () async {
print('CameraDialgo_take');
onTakeStarted();
final file = await cameraController.takeSceenshot();
if (file != null) {
// get bytes
final bytes = await file.readAsBytes();
onPhotoTaken(bytes);
Get.back();
}
},
child: Text('CameraDialog_take'.tr),
),
TextButton(
onPressed: () async {
print('switch');
await cameraController.switchCamera();
setState(() {});
},
child: Text('CameraDialog_switch'.tr),
),
TextButton(
onPressed: () {
print('cancel');
cameraController.disposeController();
Get.back();
},
child: Text('CameraDialog_cancel'.tr),
),
],
),
),
],
),
);
},
);
}
Nice, i Now know flutter is not difficult just some simple language with a style 😆
Nice going
Congratulations, your post has been curated by @dsc-r2cornell. Also, find us on Discord
Felicitaciones, su publication ha sido votado por @dsc-r2cornell. También, encuéntranos en Discord