24
#100DaysOfCodeChallenge - Crop Management Information System - Day 9
On Day 8 we solved the PlatformException (PlatformException(no_available_camera, No cameras available for taking pictures., null, null))
In this post we will discuss how to access the device camera and save photo in cloud storage.
We will use the device camera to take a photo, next, we will save the photo to cloud storage and finally we will save the url reference of the cloud storage photo to the farmer document on cloud firestore.
class _AddFarmerScreenController extends State<AddFarmerScreen> {
Widget build(BuildContext context) => _AddFarmerScreenView(this);
FarmerServiceModel farmer = FarmerServiceModel.form();
final _picker = ImagePicker();
PickedFile? _pickedFile;
late File? _farmerProfilePicture;
}
To recap, the class _AddFarmerScreenController()
is responsible for the all the logic associated with the class _AddFarmerScreenView()
. The latter class is responsible for the layout of the AddFarmerScreen
.
The ImagePicker()
is from the flutter image_picker package. This class gives us access to the methods we'll need to use the device camera.
PickedFile
is returned from the method call that takes a photo from the device camera.
File
is the photo that will be stored in cloud storage.
void _handleTakePhoto() async {
_pickedFile = await _picker.getImage(source: ImageSource.camera);
_farmerProfilePicture = File(_pickedFile!.path);
setState(() {});
}
_handleTakePhoto()
will be called when the user press the take farmer picture button. _picker.getImage(source: ImageSource.camera)
is the method that gives us access to the device camera. The returned photo is a PickedFile
. The _pickedFile
is converted to a File
by File(_pickedFile!.path)
and stored in the _farmerProfilePicture
variable.
ImageProvider<Object>? _imagePreview() {
if (_pickedFile != null) {
if (kIsWeb) {
return NetworkImage(_pickedFile!.path);
} else {
return FileImage(File(_pickedFile!.path));
}
} else {
return null;
}
}
_imagePreview()
method is assigned to:
CircleAvatar(
backgroundImage: state._imagePreview(),
minRadius: 200.0,
),
void _handleRegisterFarmer() async {
if (_formkey.currentState!.validate()) {
_formkey.currentState!.save();
farmer.saveRegistrationNumber('');
AddFarmerCommand(context).run(
farmerServiceModel: farmer,
context: context,
farmerProfilePicture: _farmerProfilePicture);
}
}
When the form data is saved, the farmer's profile picture is passed to the AddFarmerCommand().run()
method along with the other farmer data and the build context.
/// This class is responsible for farmer registration.
class AddFarmerCommand extends BaseCommand {
AddFarmerCommand(BuildContext c) : super(c);
/// Calls FarmerService.addFarmer method
///
/// Receives farmer data and buildcontext from widget and pass it to the farmerService.addFarmer and fileService.uploadFarmerProfilePicture method.
Future<bool> run({
required FarmerServiceModel farmerServiceModel,
required File? farmerProfilePicture,
required BuildContext context,
}) async {
bool farmerAddedSuccess = false;
if (farmerProfilePicture != null) {
final farmerProfilePictureUrl =
await fileservice.uploadFarmerProfilePicture(farmerProfilePicture);
farmerServiceModel.saveProfilePicture(farmerProfilePictureUrl);
}
await farmerService
.addFarmer(farmerServiceModel: farmerServiceModel)
.then((value) => farmerAddedSuccess = true);
return farmerAddedSuccess;
}
}
This method is comprised of two main parts. await fileservice.uploadFarmerProfilePicture()
and await farmerService.addFarmer()
Only if the farmer's profile picture is not null, the fileService.uploadFarmerProfilePicture()
method will be called.
class FileStorageService {
final storage = firebase_storage.FirebaseStorage.instance;
Future<String?> uploadFarmerProfilePicture(
File farmerProfilePicture,
) async {
String? farmerProfilePictureUrl;
try {
await storage
.ref()
.child('farmer_profile_picture')
.child(basename(farmerProfilePicture.path))
.putFile(farmerProfilePicture)
.then((value) async {
farmerProfilePictureUrl = await value.ref.getDownloadURL();
});
} on firebase_storage.FirebaseException catch (e) {
// e.g, e.code == 'canceled'
print(e);
}
return farmerProfilePictureUrl;
}
}
The farmerProfilePicture
is saved in cloud storage using await storage.ref().child().child.putFile().then()
method. It saves the farmerProfilePicture
in a farmer_profile_picture
folder. It then returns a url reference to the file in the then()
method. This reference is stored in cloud firestore along with the remainder of the farmer data when the await farmerService.addFarmer()
method is called.
In this post, we discussed how to save a photo from the device camera in cloud storage and store a url cloud reference of the photo from cloud storage with the remainder of the farmer data in cloud firestore.
Below are screenshots of the process.
Thank you for reading my post. Feel free to subscribe below to join me on the #100DaysOfCodeChallenge or connect with me on LinkedIn and Twitter. You can also buy me a book to show your support.
24