diff --git a/android/app/build.gradle b/android/app/build.gradle
index c722841e51aa1f2271d161773cbaf991b5a80222..c6b5d48e2e161a833f97e478f8cef140438e1aa1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -44,7 +44,7 @@ android {
 
     defaultConfig {
         applicationId "org.benoitharrault.random"
-        minSdkVersion 19
+        minSdkVersion 21
         targetSdkVersion 30
         versionCode appVersionCode.toInteger()
         versionName appVersionName
diff --git a/android/gradle.properties b/android/gradle.properties
index cfe1f46b5f8d528a00df0b970d82b0a0f7297079..e7bbd478806d6d3d5c8d27157b30df069180a8b6 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=1.0.43
-app.versionCode=44
+app.versionName=1.0.44
+app.versionCode=45
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 6b6d02750729a4be993e296a06bcc5e0f63d4fe2..7280a8a3e1e7d0316800f5a1005c0893419ca4cd 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -2,6 +2,7 @@
   "app_name": "Sandbox App",
 
   "bottom_nav_sample": "Sample",
+  "bottom_nav_camera": "Camera",
   "bottom_nav_api": "API",
   "bottom_nav_chart": "Graph",
   "bottom_nav_game": "Game",
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 72682066e0c519f9bdd04d866ef5fa0644db798f..5ef35e50be00a17d1c45e5deca1517d327ef6341 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -2,6 +2,7 @@
   "app_name": "App de test",
 
   "bottom_nav_sample": "Démo",
+  "bottom_nav_camera": "Caméra",
   "bottom_nav_api": "API",
   "bottom_nav_chart": "Graph",
   "bottom_nav_game": "Jeu",
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
index 98ff898e6e0e4bc0e5f7784b40462ccb1cf1e8d3..a02cc94d81d823edb09522d02406763341dc12f2 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -3,7 +3,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 class BottomNavCubit extends HydratedCubit<int> {
   BottomNavCubit() : super(0);
 
-  int pagesCount = 5;
+  int pagesCount = 6;
 
   void updateIndex(int index) {
     if (isIndexAllowed(index)) {
diff --git a/lib/ui/screens/camera_page.dart b/lib/ui/screens/camera_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..98c22824edbc072dd7bc89334b91fcfdaa8eb683
--- /dev/null
+++ b/lib/ui/screens/camera_page.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:random/ui/widgets/take_picture_widget.dart';
+
+class CameraPage extends StatelessWidget {
+  const CameraPage({super.key});
+
+  static Icon navBarIcon = const Icon(UniconsLine.camera);
+  static String navBarText = 'bottom_nav_camera';
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: <Widget>[
+          const SizedBox(height: 8),
+          const TakePictureWidget(),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 275a44618b4c0780dd33157aa5d81f492c09219e..044b573f6823cfb4bb0f8adb1edc342349a4c134 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -5,6 +5,7 @@ import 'package:flutter_swipe/flutter_swipe.dart';
 import 'package:random/cubit/bottom_nav_cubit.dart';
 import 'package:random/ui/screens/about_page.dart';
 import 'package:random/ui/screens/api_page.dart';
+import 'package:random/ui/screens/camera_page.dart';
 import 'package:random/ui/screens/demo_page.dart';
 import 'package:random/ui/screens/game_page.dart';
 import 'package:random/ui/screens/graph_page.dart';
@@ -25,6 +26,7 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
     const List<Widget> pageNavigation = <Widget>[
       DemoPage(),
       ApiPage(),
+      CameraPage(),
       GraphPage(),
       GamePage(),
       SettingsPage(),
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
index 6d6f83d1e47a4c73acaca1aca929a59224dc43ec..2013e651e39935e8c9b6c3197eb18773d1d3d6f1 100644
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -50,6 +50,10 @@ class BottomNavBar extends StatelessWidget {
                 icon: const Icon(UniconsLine.globe),
                 label: tr('bottom_nav_api'),
               ),
+              BottomNavigationBarItem(
+                icon: const Icon(UniconsLine.camera),
+                label: tr('bottom_nav_camera'),
+              ),
               BottomNavigationBarItem(
                 icon: const Icon(UniconsLine.pen),
                 label: tr('bottom_nav_chart'),
diff --git a/lib/ui/widgets/take_picture_widget.dart b/lib/ui/widgets/take_picture_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7a73090629bb996bdb2af68bd4ba45c97b35a3b4
--- /dev/null
+++ b/lib/ui/widgets/take_picture_widget.dart
@@ -0,0 +1,121 @@
+import 'dart:io';
+
+import 'package:camera/camera.dart';
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:random/utils/picture_storage.dart';
+
+class TakePictureWidget extends StatefulWidget {
+  const TakePictureWidget({super.key});
+
+  @override
+  TakePictureWidgetState createState() => TakePictureWidgetState();
+}
+
+class TakePictureWidgetState extends State<TakePictureWidget> {
+  CameraController? controller;
+  PictureStorage? storage;
+
+  List<String> previousImages = [];
+  List<String> debug = [];
+
+  @override
+  void initState() {
+    loadCamera();
+    storage = PictureStorage();
+    super.initState();
+  }
+
+  loadCamera() async {
+    final List<CameraDescription>? cameras = await availableCameras();
+    if (cameras != null) {
+      controller = CameraController(
+        cameras.first,
+        ResolutionPreset.max,
+        enableAudio: false,
+      );
+
+      controller!.initialize().then((_) {
+        if (!mounted) {
+          return;
+        }
+        setState(() {});
+      });
+    } else {
+      print("No camera found.");
+    }
+  }
+
+  @override
+  void dispose() {
+    controller!.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: [
+          Container(
+            height: 400,
+            child: controller == null
+                ? Center(child: Text("Loading camera..."))
+                : !controller!.value.isInitialized
+                    ? Center(child: CircularProgressIndicator())
+                    : CameraPreview(controller!),
+          ),
+          ElevatedButton.icon(
+            label: Text("Take picture"),
+            icon: Icon(UniconsLine.camera),
+            onPressed: () async {
+              try {
+                if ((controller != null) && (controller!.value.isInitialized)) {
+                  final XFile image = await controller!.takePicture();
+                  print('image.path: ' + image.path);
+                  debug.add('image.path: ' + image.path);
+
+                  File savedFile = await storage!.writeCounter(File(image.path));
+                  debug.add('image.path: ' + image.path);
+
+                  String imagePath = savedFile.path;
+                  print('imagePath: ' + imagePath);
+                  debug.add('imagePath: ' + imagePath);
+
+                  previousImages.add(imagePath);
+                  setState(() {});
+                }
+              } catch (e) {
+                debug.add('error: ' + e.toString());
+                setState(() {});
+
+                print(e);
+              }
+            },
+          ),
+          Text('debug: '),
+          Column(
+            children: debug.map((String line) {
+              return Text(line);
+            }).toList(),
+          ),
+          previousImages.length == 0
+              ? Text('no previous images')
+              : Column(
+                  children: previousImages.map((String imagePath) {
+                    return Row(
+                      children: [
+                        // Image.file(File(imagePath)),
+                        Text(imagePath),
+                      ],
+                    );
+                  }).toList(),
+                ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/utils/picture_storage.dart b/lib/utils/picture_storage.dart
new file mode 100644
index 0000000000000000000000000000000000000000..72e2278f677d39ef318ab24a57dd4a7e8b9ae950
--- /dev/null
+++ b/lib/utils/picture_storage.dart
@@ -0,0 +1,35 @@
+import 'dart:io';
+
+import 'package:path/path.dart';
+import 'package:path_provider/path_provider.dart';
+
+class PictureStorage {
+  Future<String> get _localPath async {
+    final directory = await getApplicationDocumentsDirectory();
+
+    return directory.path;
+  }
+
+  Future<String> _localFilePath(String name) async {
+    final path = await _localPath;
+
+    return path + '/' + name;
+  }
+
+  Future<File> moveFile(File sourceFile, String newPath) async {
+    try {
+      return await sourceFile.rename(newPath);
+    } on FileSystemException catch (e) {
+      print('Found exception while moving file: ' + e.toString());
+      final newFile = await sourceFile.copy(newPath);
+      await sourceFile.delete();
+      return newFile;
+    }
+  }
+
+  Future<File> writeCounter(File sourceFile) async {
+    final targetFile = await _localFilePath(basename(sourceFile.path));
+
+    return moveFile(sourceFile, targetFile);
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 1505f2f3bab4e02e4b77d1b5d90e487a9eb593e5..b3dd33c8a58e6b44e1eff2ec494b36c08e757a6d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -25,6 +25,46 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "8.1.2"
+  camera:
+    dependency: "direct main"
+    description:
+      name: camera
+      sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.10.5+9"
+  camera_android:
+    dependency: transitive
+    description:
+      name: camera_android
+      sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.10.8+16"
+  camera_avfoundation:
+    dependency: transitive
+    description:
+      name: camera_avfoundation
+      sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.9.14"
+  camera_platform_interface:
+    dependency: transitive
+    description:
+      name: camera_platform_interface
+      sha256: e971ebca970f7cfee396f76ef02070b5e441b4aa04942da9c108d725f57bbd32
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.7.2"
+  camera_web:
+    dependency: transitive
+    description:
+      name: camera_web
+      sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.3.2+4"
   characters:
     dependency: transitive
     description:
@@ -49,6 +89,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.18.0"
+  cross_file:
+    dependency: transitive
+    description:
+      name: cross_file
+      sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.3.3+8"
   crypto:
     dependency: transitive
     description:
@@ -123,6 +171,14 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_plugin_android_lifecycle:
+    dependency: transitive
+    description:
+      name: flutter_plugin_android_lifecycle
+      sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.17"
   flutter_swipe:
     dependency: "direct main"
     description:
@@ -365,6 +421,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.10.0"
+  stream_transform:
+    dependency: transitive
+    description:
+      name: stream_transform
+      sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.0"
   string_scanner:
     dependency: transitive
     description:
@@ -438,5 +502,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.2.0 <4.0.0"
-  flutter: ">=3.16.0"
+  dart: ">=3.2.3 <4.0.0"
+  flutter: ">=3.16.6"
diff --git a/pubspec.yaml b/pubspec.yaml
index 499f579c251cc60572d357eda98f5d4fdccd65e3..2e0ad1ddb9fb0b379c371fd73328014ec8aad36b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
 
 publish_to: 'none'
 
-version: 1.0.43+44
+version: 1.0.44+45
 
 environment:
   sdk: '^3.0.0'
@@ -12,6 +12,7 @@ dependencies:
   flutter:
     sdk: flutter
 
+  camera: ^0.10.5+8
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1