flutter_media_picker_pro 1.0.4 copy "flutter_media_picker_pro: ^1.0.4" to clipboard
flutter_media_picker_pro: ^1.0.4 copied to clipboard

A versatile Flutter package for picking and handling images, videos, and audio, with compression, timestamps, and recording features.

example/lib/main.dart

import 'dart:io';
import 'package:audioplayers/audioplayers.dart';
import 'package:example/custom_recording_button.dart';
import 'package:example/custom_recording_wave_widget.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_media_picker_pro/flutter_media_picker_pro.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:image/image.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image/image.dart' as img;
import 'package:permission_handler/permission_handler.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: PictureScreen(),
    );
  }
}

class PictureScreen extends ConsumerStatefulWidget {
  const PictureScreen({super.key});

  @override
  _PictureScreenState createState() => _PictureScreenState();
}

class _PictureScreenState extends ConsumerState<PictureScreen> {
  final FlutterMediaPickerPro mediaPicker = FlutterMediaPickerPro();
  XFile? _mediaFile;
  bool _isProcessing = false;
  bool _isStartRecording = false;
  final AudioPlayer _audioPlayer = AudioPlayer();
  bool _isPlaying = false;
  bool isPlayAudio = true;
  String? audioPath;
  XFile? randomFile;

  @override
  void initState() {
    _audioPlayer.onPlayerComplete.listen((_) {
      setState(() {
        isPlayAudio = true;
        _isPlaying = false;
      });
    });
    super.initState();
  }

  @override
  void dispose() {
    _audioPlayer.dispose();
    super.dispose();
  }

  Future<void> _pickMedia({
    CompressionLevel? compressionLevel,
    required bool isNeedTimeStamp,
    required bool isVideo,
    required bool isAudio,
    required bool isRecording,
    required bool isStartRecording,
    required bool isSourceCamera,
    required bool isCompressionRequired,
  }) async {
    final XFile? pickedFile = await FlutterMediaPickerPro.getMedia(
      compressionLevel: compressionLevel ?? CompressionLevel.high,
      isStartRecording: isStartRecording,
      isRecording: isRecording,
      isAudio: isAudio,
      isSourceCamera: isSourceCamera,
      context: context,
      isVideo: isVideo,
      ref: ref,
      isCompressionRequired: isCompressionRequired,
      isNeedTimeStamp: isNeedTimeStamp,
      onProcessing: (bool isProcessing) {
        setState(() {
          _isProcessing = isProcessing;
        });
      },
    );

    if (pickedFile != null) {
      setState(() {
        _mediaFile = pickedFile;
      });
    }

    if (isAudio) {
      if (!isRecording) {
        await _audioPlayer
            .play(DeviceFileSource((pickedFile?.path).toString()));
        setState(() {
          _isPlaying = true;
        });
      }
    }
  }

  final PageController _pageController = PageController();
  int _activePage = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Row(
            children: [
              Icon(Icons.perm_media, color: Colors.white), // General media icon
              SizedBox(width: 12), // Spacing between icon and title
              Text(
                'Flutter Media Picker Pro',
                style: TextStyle(color: Colors.white, fontSize: 18),
              ),
            ],
          ),
          backgroundColor: Colors.deepPurpleAccent,
          actions: [
            IconButton(
              icon: const Icon(
                Icons.info_outline,
                color: Colors.white,
              ),
              onPressed: () {
                // Handle info action (e.g., show package information)
                showDialog(
                  context: context,
                  builder: (context) => AlertDialog(
                    title: const Text(
                      'About Media Picker Pro',
                      style:
                          TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                    ),
                    content: const Text(
                      'The Flutter Media Picker Pro package is a versatile solution for Flutter developers, enabling users to pick images, videos, and audio files from their device gallery or camera. It includes features like media compression, adding timestamps to videos, and audio recording and playback. The package is designed to simplify media handling in Flutter apps, providing a smooth and efficient user experience.',
                      style: TextStyle(fontSize: 14),
                    ),
                    actions: [
                      TextButton(
                        onPressed: () => Navigator.of(context).pop(),
                        child: const Text('Close'),
                      ),
                    ],
                  ),
                );
              },
            ),
          ],
        ),
        body: PageView.builder(
          physics: const NeverScrollableScrollPhysics(),
          controller: _pageController,
          itemCount: 4,
          onPageChanged: (int page) {
            setState(() {
              _activePage = page;
              _mediaFile = null;
              if (kDebugMode) {
                print(_activePage);
              }
            });
          },
          itemBuilder: (BuildContext context, int index) {
            if (kDebugMode) {
              print('index : $index');
            }
            if (_activePage == 0) {
              return SingleChildScrollView(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    children: [
                      _isProcessing
                          ? const Center(child: CircularProgressIndicator())
                          : _mediaFile == null
                              ? Container(
                                  height: 200,
                                  width: double.infinity,
                                  decoration: BoxDecoration(
                                    border: Border.all(color: Colors.grey),
                                    borderRadius: BorderRadius.circular(8),
                                  ),
                                  child: const Center(
                                    child: Text(
                                      'No media selected!',
                                      style: TextStyle(
                                        fontSize: 18,
                                      ),
                                    ),
                                  ))
                              : mediaPicker
                                  .displayImage(File(_mediaFile!.path)),
                      const SizedBox(height: 20),
                      Wrap(
                        crossAxisAlignment: WrapCrossAlignment.start,
                        spacing: 10,
                        runSpacing: 10,
                        children: [
                          _buildMediaButton(
                            icon: Icons.camera_alt,
                            label: 'Capture Image',
                            onPressed: () {
                              _pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: false,
                                  isSourceCamera: true,
                                  isCompressionRequired: false);
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.image,
                            label: 'Pick Image',
                            onPressed: () {
                              _pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: false,
                                  isSourceCamera: false,
                                  isCompressionRequired: false);
                            },
                          ),
                          _buildMediaButton(
                            showSecondIcon: true,
                            secondIcon: Icons.compress,
                            icon: Icons.image,
                            label: 'Pick & Compress Image',
                            onPressed: () {
                              showCompressionDialog(
                                  isSourceCamera: false,
                                  isTimeStampNeeded: false);
                              /*_pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: false,
                                  isSourceCamera: false,
                                  isCompressionRequired: true);*/
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.camera_alt,
                            showSecondIcon: true,
                            secondIcon: Icons.compress,
                            label: 'Pick & Compress Image',
                            onPressed: () {
                              showCompressionDialog(
                                  isSourceCamera: true,
                                  isTimeStampNeeded: false);
                              /*_pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: false,
                                  isSourceCamera: true,
                                  isCompressionRequired: true);*/
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.access_time,
                            label: 'Add Timestamp on Gallery Image',
                            onPressed: () {
                              _pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: true,
                                  isSourceCamera: false,
                                  isCompressionRequired: false);
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.access_time,
                            label: 'Add Timestamp on Camera Image',
                            //color: Colors.white,
                            onPressed: () {
                              _pickMedia(
                                  isVideo: false,
                                  isAudio: false,
                                  isRecording: false,
                                  isStartRecording: false,
                                  isNeedTimeStamp: true,
                                  isSourceCamera: true,
                                  isCompressionRequired: false);
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.access_time,
                            showSecondIcon: true,
                            secondIcon: Icons.compress,
                            label: 'Add Timestamp & Compress Camera Image',
                            //color: Colors.white,
                            onPressed: () {
                              showCompressionDialog(
                                  isSourceCamera: true,
                                  isTimeStampNeeded: true);
                            },
                          ),
                          _buildMediaButton(
                            icon: Icons.access_time,
                            showSecondIcon: true,
                            secondIcon: Icons.compress,
                            label: 'Add Timestamp & Compress Gallery Image',
                            //color: Colors.white,
                            onPressed: () {
                              showCompressionDialog(
                                  isSourceCamera: false,
                                  isTimeStampNeeded: true);
                            },
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              );
            } else if (_activePage == 1) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Container(
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          border: Border.all(color: Colors.blue)),
                      width: double.infinity,
                      child: Column(
                        children: [
                          if (_isStartRecording)
                            const CustomRecordingWaveWidget(),
                          const SizedBox(height: 16),
                          Center(
                            child: CustomRecordingButton(
                              isRecording: _isStartRecording,
                              onPressed: () async {
                                _mediaFile = null;
                                audioPath = null;
                                if (_isStartRecording == false) {
                                  _isStartRecording = true;
                                  _pickMedia(
                                      isVideo: false,
                                      isAudio: true,
                                      isRecording: true,
                                      isStartRecording: true,
                                      isNeedTimeStamp: false,
                                      isSourceCamera: false,
                                      isCompressionRequired: false);
                                } else {
                                  _isStartRecording = false;
                                  audioPath =
                                      await FlutterMediaPickerPro.getMedia(
                                    isStartRecording: false,
                                    isRecording: true,
                                    isAudio: true,
                                    isSourceCamera: true,
                                    context: context,
                                    isVideo: false,
                                    ref: ref,
                                    isCompressionRequired: false,
                                    isNeedTimeStamp: true,
                                    onProcessing: (bool isProcessing) {
                                      setState(() {
                                        _isProcessing = isProcessing;
                                      });
                                    },
                                  );
                                  if (kDebugMode) {
                                    print(
                                        'Checking audio path at stop recording::${audioPath.toString()}');
                                  }
                                  setState(() {});
                                }
                              },
                            ),
                          ),
                          audioPath != null
                              ? Text(
                                  '$audioPath',
                                  textAlign: TextAlign.center,
                                )
                              : const SizedBox(),
                          audioPath != null
                              ? IconButton(
                                  icon: Icon(!isPlayAudio
                                      ? Icons.pause
                                      : Icons.play_arrow),
                                  onPressed: () async {
                                    if (kDebugMode) {
                                      print(
                                          'Checking audio path::${audioPath.toString()}');
                                    }
                                    if (isPlayAudio) {
                                      isPlayAudio = false;
                                      await _audioPlayer.play(DeviceFileSource(
                                          audioPath.toString()));
                                      setState(() {});
                                    } else {
                                      isPlayAudio = true;
                                      _audioPlayer.pause();
                                    }
                                    setState(() {});
                                  },
                                )
                              : const SizedBox(),
                          const SizedBox(height: 16),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(width: 10),
                  if (_isProcessing)
                    const CircularProgressIndicator()
                  else if (_mediaFile == null)
                    const SizedBox()
                  else
                    Text(_mediaFile!.name),
                  _mediaFile != null
                      ? IconButton(
                          icon:
                              Icon(_isPlaying ? Icons.pause : Icons.play_arrow),
                          onPressed: () async {
                            if (_isPlaying) {
                              await _audioPlayer.pause();
                            } else {
                              await _audioPlayer.resume();
                            }
                            setState(() {
                              _isPlaying = !_isPlaying;
                            });
                          },
                        )
                      : const SizedBox(),
                  _buildMediaButton(
                    icon: Icons.audiotrack,
                    label: 'Pick Audio',
                    onPressed: () {
                      _mediaFile = null;
                      audioPath = null;
                      _pickMedia(
                          isVideo: false,
                          isAudio: true,
                          isRecording: false,
                          isStartRecording: false,
                          isNeedTimeStamp: false,
                          isSourceCamera: false,
                          isCompressionRequired: false);
                    },
                  ),
                ],
              );
            } else if (_activePage == 2) {
              return SingleChildScrollView(
                child: Column(
                  children: [
                    _isProcessing
                        ? const Center(child: CircularProgressIndicator())
                        : _mediaFile == null
                            ? Padding(
                                padding: const EdgeInsets.all(12.0),
                                child: Container(
                                    height: 200,
                                    width: double.infinity,
                                    decoration: BoxDecoration(
                                      border: Border.all(color: Colors.grey),
                                      borderRadius: BorderRadius.circular(8),
                                    ),
                                    child: const Center(
                                      child: Text(
                                        'No media selected!',
                                        style: TextStyle(
                                          fontSize: 18,
                                        ),
                                      ),
                                    )),
                              )
                            : mediaPicker.displayVideo(File(_mediaFile!.path)),
                    Wrap(
                      crossAxisAlignment: WrapCrossAlignment.start,
                      spacing: 10,
                      runSpacing: 10,
                      children: [
                        _buildMediaButton(
                          icon: Icons.video_call,
                          label: 'Take Video',
                          //color: Colors.white,
                          onPressed: () {
                            _pickMedia(
                                isVideo: true,
                                isAudio: false,
                                isRecording: false,
                                isStartRecording: false,
                                isNeedTimeStamp: false,
                                isSourceCamera: true,
                                isCompressionRequired: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.video_call,
                          label: 'Pick Video',
                          //color: Colors.white,
                          onPressed: () {
                            _pickMedia(
                                isVideo: true,
                                isAudio: false,
                                isRecording: false,
                                isStartRecording: false,
                                isNeedTimeStamp: false,
                                isSourceCamera: false,
                                isCompressionRequired: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.image,
                          label: 'Compress Camera Video',
                          //color: Colors.white,
                          onPressed: () {
                            showCompressionDialog(
                                isVideo: true,
                                isTimeStampNeeded: false,
                                isSourceCamera: true);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.image,
                          label: 'Compress Gallery Video',
                          //color: Colors.white,
                          onPressed: () {
                            showCompressionDialog(
                                isVideo: true,
                                isTimeStampNeeded: false,
                                isSourceCamera: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.access_time,
                          label: 'Add Timestamp on Camera Video',
                          //color: Colors.white,
                          onPressed: () {
                            _pickMedia(
                                isVideo: true,
                                isAudio: false,
                                isRecording: false,
                                isStartRecording: false,
                                isNeedTimeStamp: true,
                                isSourceCamera: true,
                                isCompressionRequired: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.access_time,
                          label: 'Add Timestamp on Gallery Video',
                          //color: Colors.white,
                          onPressed: () {
                            _pickMedia(
                                isVideo: true,
                                isAudio: false,
                                isRecording: false,
                                isStartRecording: false,
                                isNeedTimeStamp: true,
                                isSourceCamera: false,
                                isCompressionRequired: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.access_time,
                          secondIcon: Icons.compress,
                          showSecondIcon: true,
                          label: 'Add Timestamp & Compress Gallery Video',
                          //color: Colors.white,
                          onPressed: () {
                            showCompressionDialog(
                                isVideo: true,
                                isTimeStampNeeded: true,
                                isSourceCamera: false);
                          },
                        ),
                        _buildMediaButton(
                          icon: Icons.access_time,
                          secondIcon: Icons.compress,
                          showSecondIcon: true,
                          label: 'Add Timestamp & Compress Camera Video',
                          //color: Colors.white,
                          onPressed: () {
                            showCompressionDialog(
                                isVideo: true,
                                isTimeStampNeeded: true,
                                isSourceCamera: true);
                          },
                        ),
                      ],
                    ),
                  ],
                ),
              );
            } else {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  if (_isProcessing)
                    const CircularProgressIndicator()
                  else if (randomFile == null)
                    const SizedBox()
                  else
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(
                        'Picked File Path: ${(randomFile?.path).toString()}',
                        textAlign: TextAlign.center,
                      ),
                    ),
                  _buildMediaButton(
                    icon: Icons.file_present_outlined,
                    label: 'Pick File',
                    onPressed: () async {
                      randomFile = await FlutterMediaPickerPro.getMedia(
                        isFile: true,
                        isStartRecording: false,
                        isRecording: false,
                        isAudio: false,
                        isSourceCamera: true,
                        context: context,
                        isVideo: false,
                        ref: ref,
                        isCompressionRequired: false,
                        isNeedTimeStamp: false,
                        onProcessing: (bool isProcessing) {
                          setState(() {
                            _isProcessing = isProcessing;
                          });
                        },
                      );
                    },
                  ),
                ],
              );
            }
          },
        ),
        floatingActionButton: SpeedDial(
          spacing: 8,
          spaceBetweenChildren: 5,
          animatedIcon: AnimatedIcons.menu_arrow,
          children: [
            SpeedDialChild(
                child: const Icon(Icons.image_outlined),
                label: 'Image',
                onTap: () {
                  _pageController.animateToPage(
                    0,
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.easeInOut,
                  );
                }),
            SpeedDialChild(
                child: const Icon(Icons.video_call),
                label: 'Video',
                onTap: () {
                  _pageController.animateToPage(
                    2,
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.easeInOut,
                  );
                }),
            SpeedDialChild(
                child: const Icon(Icons.audiotrack),
                label: 'Audio',
                onTap: () {
                  _pageController.animateToPage(
                    1,
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.easeInOut,
                  );
                }),
            SpeedDialChild(
                child: const Icon(Icons.file_present),
                label: 'File',
                onTap: () {
                  _pageController.animateToPage(
                    4,
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.easeInOut,
                  );
                })
          ],
        ));
  }

  Widget _buildMediaButton({
    required IconData icon,
    IconData? secondIcon,
    bool showSecondIcon = false,
    required String label,
    Color? color,
    required VoidCallback onPressed,
  }) {
    return ElevatedButton.icon(
      onPressed: onPressed,
      icon: Row(
        children: [
          Icon(
            icon,
            color: Colors.white,
            size: 14,
          ),
          showSecondIcon
              ? Row(
                  children: [
                    const Padding(
                      padding: EdgeInsets.symmetric(horizontal: 5.0),
                      child: Text('+'),
                    ),
                    Icon(
                      secondIcon,
                      color: Colors.white,
                      size: 14,
                    ),
                  ],
                )
              : const SizedBox()
        ],
      ),
      label: Text(label,
          style: const TextStyle(color: Colors.white, fontSize: 12)),
      style: ElevatedButton.styleFrom(
        foregroundColor: Colors.white,
        backgroundColor: Colors.deepPurpleAccent,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        elevation: 2,
        padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
      ),
    );
  }

  Future<void> showCompressionDialog(
      {bool isVideo = false,
      bool isSourceCamera = false,
      bool isTimeStampNeeded = false}) async {
    CompressionLevel? selectedLevel = CompressionLevel.high;

    await showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text(
            'Select Compression Level',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          content: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  RadioListTile<CompressionLevel>(
                    title: const Text('High'),
                    value: CompressionLevel.high,
                    groupValue: selectedLevel,
                    onChanged: (CompressionLevel? value) {
                      setState(() {
                        selectedLevel = value;
                      });
                    },
                  ),
                  RadioListTile<CompressionLevel>(
                    title: const Text('Medium'),
                    value: CompressionLevel.medium,
                    groupValue: selectedLevel,
                    onChanged: (CompressionLevel? value) {
                      setState(() {
                        selectedLevel = value;
                      });
                    },
                  ),
                  RadioListTile<CompressionLevel>(
                    title: const Text('Low'),
                    value: CompressionLevel.low,
                    groupValue: selectedLevel,
                    onChanged: (CompressionLevel? value) {
                      setState(() {
                        selectedLevel = value;
                      });
                    },
                  ),
                ],
              );
            },
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Cancel'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: const Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
                if (selectedLevel != null) {
                  _pickMedia(
                    isVideo: isVideo,
                    isAudio: false,
                    isRecording: false,
                    isStartRecording: false,
                    isNeedTimeStamp: isTimeStampNeeded,
                    isSourceCamera: isSourceCamera,
                    isCompressionRequired: true,
                    compressionLevel: selectedLevel,
                  );
                }
              },
            ),
          ],
        );
      },
    );
  }
}
3
likes
0
points
74
downloads

Publisher

unverified uploader

Weekly Downloads

A versatile Flutter package for picking and handling images, videos, and audio, with compression, timestamps, and recording features.

Repository

License

unknown (license)

Dependencies

audioplayers, ffmpeg_kit_flutter, file_picker, flutter, flutter_image_compress, flutter_riverpod, image, image_picker, intl, path, path_provider, permission_handler, record, video_compress, video_player

More

Packages that depend on flutter_media_picker_pro