Work with the camera in Flutter
The ability to use the camera exists in many applications, and we all regularly use it. In Flutter, we can implement the work with the camera using two official plugins:
There is a noticeable difference between them, and it is worth using them according to the situation:
camera
Allows you to interact with the cameras available to the device from your application and display the image in the widget. It is well suited for tasks when you need to "customize" the operation of the camera for the application.image-picker
launches the camera application and returns an object of the typeFile
(image or video file selected by the user) to your application. It alsoimage-picker
makes it possible to select a file from those available on the device, while, as in the case of the camera, a separate application is launched, after which the selected object is returned to your application.
Here you can see the source .
camera
1. Add the plugin to our project according to the instructions
Additional settings for
iOS OS
Add the following lines to ios/Runner/Info.plist
:
NSCameraUsageDescription Access to Camera NSMicrophoneUsageDescription Access to Microphone
Android
Ensure that the minimum version of Android sdk in the file is android/app/build.gradle
21 .
minSdkVersion 21
All necessary permissions will be requested when the application starts.
Work on emulators
In the case of iOS, we can not check the camera on the emulator, we need a "live" device.
Android generates a mock (see image below), which replaces what the camera lens sees.
In the emulator settings, select Advanced Settings and set it for the rear camera VirtualScene
.
We restart the emulator. Now the camera "shows" the virtual room, which can be moved with the mouse and wasd.
Thanks to Tonn_Tamerlan for the tip.
2. We pass to the code. First, we get all the available cameras using the function availableCameras
.
final cameras = await availableCameras();
This function will return an array of descriptions ( ) of available cameras, where each element will contain the name of the camera (it can just be an index), type (back, front, external) and the angle by which the photo should be rotated so that it displays in its orientation.List
To control the camera, we need an object-controller of the type CameraController
, to determine which we must specify one of the received camera descriptions and resolution (low, medium, high).
void _setCameraController(CameraDescription cameraDescription) async {
_controller = CameraController(cameraDescription, ResolutionPreset.medium);
...
await _controller.initialize();
...
if (mounted) {
setState(() {});
}
}
Next, we initialize the controller and after making sure that the widget is "alive", we update the state of this widget. ( function text )
We pass the initialized controller to the widget CameraPreview
AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: CameraPreview(_controller))
It is based CameraPreview
on a widget Texture
responsible for displaying pictures from the camera. Its dimensions are determined by the parent, so a widget approach AspectRatio
that determines the size of the child in a certain aspect ratio is a good approach . We get the ratio from the controller _controller.value.aspectRatio
. As a result, in the interface we get a picture in the interface
3. Now we can take a photo or shoot a video.
a. We take a photo ( function text ) using the method takePicture(String path)
. It takes a picture and saves along the specified path.
Future _takePhoto(BuildContext context) async {
...
await _controller.takePicture(filePath);
...
}
To get the path, we need the official path_provider plugin and its method getApplicationDocumentsDirectory
, which will return a private directory. Next, we determine the name of the directory to taste, if necessary, create it, and select the file name:
final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/Pictures/flutter_camera';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${_getTimestamp()}.jpg';
Before taking a picture, it is advisable to verify that the controller is initialized and the picture is no longer taken.
if (!_controller.value.isInitialized) {
return null;
}
...
if (_controller.value.isTakingPicture) {
return null;
}
The picture was taken, we have a way to it, it would be nice to see. Using a standard widget Image
, object File
and file path, we display the image on the screen.
Image.file(File(filePath))
b. When recording video ( function text ), we need two functions: startVideoRecording(String filePath)
and stopVideoRecording()
.
Future _startVideoRecording() async {
...
await _controller.startVideoRecording(filePath);
...
}
Future _stopVideoRecording(BuildContext context) async {
...
await _controller.stopVideoRecording();
...
}
startVideoRecording
writes a video and saves according to the specified path (obtained by the same principle as with a photograph), stopVideoRecording
but simply ends the recording process. Before you start recording, make sure that shooting is no longer in progress.
if (_controller.value.isRecordingVideo) {
return null;
}
As a result, we have a saved video and a path to it. To play it, you will need the video_player plugin . All the code associated with playing the video, taken out in a separate file .
image-picker
1. Add the plugin to our project according to the instructions
Additional settings for
iOS OS
Add the following lines to ios/Runner/Info.plist
:
NSCameraUsageDescription Access to Camera NSMicrophoneUsageDescription Access to Microphone NSPhotoLibraryUsageDescription Access to PhotoLibrary
Work on emulators
In iOS, we can not check the camera on the emulator, we need a "live" device.
2.image-picker
использует стандартное приложение для создания фото/видео или просмотра файлов. Для запуска нужного приложения необходимо воспользоваться функцией pickImage
для фото или pickVideo
и указать параметр source (источник).
...
final File video = await ImagePicker.pickVideo(source: ImageSource.camera);
final File photo = await ImagePicker.pickImage(source: ImageSource.gallery);
// для pickImage можно еще указать максимальные показатели ширины и высоты, иначе изображение вернется в оригинальном размере
...
Выбранный файл получает наше приложение, но если ничего не было выбрано, то вернется null
. Для показа картинки и видео используем те же подходы, что и в случае плагина camera
. Для изображений виджет Image
— в этот раз не надо оборачивать в File
, так как мы изначально получили объект этого типа.
Image.file(photo)
Для видео плагин video_player. Весь код, связанный с проигрыванием видео, вынесен в отдельный файл.
Заключение
As you can see, it’s image-picker
noticeably easier to use and is great in cases where you just need to transfer the image or video to the application. camera
it also provides us with all the necessary features for customizing the user’s work with the camera in your application.
Thanks for reading!