How to enable camera access for Android and IOS in Flutter?
This is a Flutter code that implements a camera module. The code creates a StatefulWidget named CameraModule, which contains a single state class _CameraModuleState.
Before we step into the coding we need to get camera access from the respective devices:
For Android:
you need to modify the app's AndroidManifest.xml file. Here's an example of how to add camera permission:
<manifest ...>
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
For IOS:
Request camera access in your AppDelegate.m file by adding the following to your Info.plist file:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
The _CameraModuleState class has several instance variables:
- _controller is an instance of the CameraController class, which is used to control the camera.
- _cameras is a list of CameraDescription objects, which describe the available cameras on the device.
- _images is a list of strings, which store the paths to the images taken by the camera.
late CameraController _controller;
late List<CameraDescription> _cameras;
List<String> _images = [];
The initState method calls the _initializeCamera method, which initializes the camera. It calls the availableCameras function to get a list of available cameras and sets the _cameras variable. Then, it creates an instance of the CameraController class, using the first camera in the list and a ResolutionPreset.medium resolution. Finally, it initializes the camera controller by calling its initialize method.
Future<void> _initializeCamera() async {
_cameras = await availableCameras();
_controller = CameraController(_cameras[0], ResolutionPreset.medium);
try {
await _controller.initialize();
} catch (e) {
print(e);
}
}
The dispose method is called when the widget is removed from the tree. It disposes of the camera controller by calling its dispose method.
@override
void dispose() {
_controller.dispose();
super.dispose();
}
The _takePicture method takes a picture with the camera. It calls the takePicture method on the camera controller and then copies the image to a specified path. Finally, it adds the path to the _images list and calls setState to notify the framework that the state has changed and the widget tree needs to be rebuilt.
Future<void> _takePicture() async {
final path = 'path/to/image.jpg';
await _controller.takePicture().then((File image) {
image.copy(path);
} as FutureOr Function(XFile value));
setState(() {
_images.add(path);
});
}
The build method returns a Scaffold widget that contains a camera preview and a list of taken images. The camera preview is displayed using the CameraPreview widget, which takes the camera controller as an argument. The list of images is displayed using a ListView.builder widget.
Column(
children: [
Expanded(
child: FutureBuilder<void>(
future: _initializeCamera(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return CameraPreview(_controller);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
Container(
height: 200,
child: ListView.builder(
itemBuilder: (context, index) {
return Image.file(_images[index] as File);
},
itemCount: _images.length,
),
),
],
),
Finally, the floatingActionButton contains a FloatingActionButton that takes a picture when pressed.
floatingActionButton: FloatingActionButton(
onPressed: _takePicture,
child: Icon(Icons.camera_alt),
),
Please find the full code below:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
class CameraModule extends StatefulWidget {
@override
_CameraModuleState createState() => _CameraModuleState();
}
class _CameraModuleState extends State<CameraModule> {
late CameraController _controller;
late List<CameraDescription> _cameras;
List<String> _images = [];
Future<void> _initializeCamera() async {
_cameras = await availableCameras();
_controller = CameraController(_cameras[0], ResolutionPreset.medium);
try {
await _controller.initialize();
} catch (e) {
print(e);
}
}
@override
void initState() {
super.initState();
_initializeCamera();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _takePicture() async {
final path = 'path/to/image.jpg';
await _controller.takePicture().then((File image) {
image.copy(path);
} as FutureOr Function(XFile value));
setState(() {
_images.add(path);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Camera'),
),
body: Column(
children: [
Expanded(
child: FutureBuilder<void>(
future: _initializeCamera(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return CameraPreview(_controller);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
Container(
height: 200,
child: ListView.builder(
itemBuilder: (context, index) {
return Image.file(_images[index] as File);
},
itemCount: _images.length,
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _takePicture,
child: Icon(Icons.camera_alt),
),
);
}
}
Comments
Post a Comment