flutter_media_picker_pro 1.0.0
flutter_media_picker_pro: ^1.0.0 copied to clipboard
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's gallery or camera. It includes features [...]
example/lib/main.dart
import 'dart:developer';
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_ffmpeg/flutter_ffmpeg.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:intl/intl.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:record/record.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: PictureScreen(),
);
}
}
class PictureScreen extends ConsumerStatefulWidget {
@override
_PictureScreenState createState() => _PictureScreenState();
}
class _PictureScreenState extends ConsumerState<PictureScreen> {
String _locationMessage = "";
String _addressMessage = "";
final FlutterMediaPickerPro mediaPicker = FlutterMediaPickerPro();
XFile? _mediaFile;
bool _isProcessing = false;
bool _isStartRecording = false;
final AudioPlayer _audioPlayer = AudioPlayer();
bool _isPlaying = false;
bool isPlayAudio = true;
String? audioPath;
File? randomFile;
@override
void initState() {
_requestPermissions();
_audioPlayer.onPlayerComplete.listen((_) {
setState(() {
isPlayAudio = true;
_isPlaying = false;
});
});
super.initState();
}
@override
void dispose() {
_audioPlayer.dispose();
super.dispose();
}
Future<void> _requestPermissions() async {
if (await Permission.storage.request().isGranted) {
// Permission is granted
} else {
// Handle the case where permission is not granted
}
}
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: 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: Icon(Icons.info_outline, color: Colors.white,),
onPressed: () {
// Handle info action (e.g., show package information)
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('About Media Picker Pro', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),),
content: Text(
'This package helps you pick and process media files including images, videos, and audio.', style: TextStyle( fontSize: 14),),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Close'),
),
],
),
);
},
),
],
),
body: PageView.builder(
physics: NeverScrollableScrollPhysics(),
controller: _pageController,
itemCount: 3,
onPageChanged: (int page) {
setState(() {
_activePage = page;
_mediaFile = null;
});
},
itemBuilder: (BuildContext context, int index) {
if (_activePage == 0) {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
_isProcessing
? Center(child: CircularProgressIndicator())
: _mediaFile == null
? Container(
height: 200,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Text(
'No media selected!',
style: TextStyle(
fontSize: 18,
),
),
)
)
: mediaPicker.displayImage(File(_mediaFile!.path)),
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;
});
},
);
print('Checking audio path at stop recording::${audioPath.toString()}');
setState(() {});
}
},
),
),
audioPath != null
? Text('$audioPath', textAlign: TextAlign.center,)
: SizedBox(),
audioPath != null
? IconButton(
icon: Icon(!isPlayAudio
? Icons.pause
: Icons.play_arrow),
onPressed: () async {
print('Checking audio path::${audioPath.toString()}');
if (isPlayAudio) {
isPlayAudio = false;
await _audioPlayer.play(DeviceFileSource(audioPath.toString()));
setState(() {});
} else {
isPlayAudio = true;
_audioPlayer.pause();
}
setState(() {});
},
)
: SizedBox(),
const SizedBox(height: 16),
],
),
),
),
const SizedBox(width: 10),
if (_isProcessing)
CircularProgressIndicator()
else if (_mediaFile == null)
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;
});
},
)
: 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 {
return SingleChildScrollView(
child: Column(
children: [
_isProcessing
? 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: 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);
},
),
],
),
],
),
);
}
},
),
// Center(
// child: _isProcessing
// ? CircularProgressIndicator()
// :_mediaFile == null
// ? Text('No media selected.')
// : _mediaFile!.path.endsWith('.mp4')
// ?
// mediaPicker.displayVideo(File(_mediaFile!.path))
// : _mediaFile!.path.endsWith('.mp3') || _mediaFile!.path.endsWith('.wav') || _mediaFile!.path.endsWith('.aac')
// ? Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text('Playing audio: ${_mediaFile!.name}'),
// IconButton(
// icon: Icon(_isPlaying ? Icons.pause : Icons.play_arrow),
// onPressed: () async {
// if (_isPlaying) {
// await _audioPlayer.pause();
// } else {
// await _audioPlayer.resume();
// }
// setState(() {
// _isPlaying = !_isPlaying;
// });
// },
// ),
// ],
// )
// : mediaPicker.displayImage(File(_mediaFile!.path)),
// ),
floatingActionButton: SpeedDial(
spacing: 8,
spaceBetweenChildren: 5,
animatedIcon: AnimatedIcons.menu_arrow,
children: [
SpeedDialChild(
child: Icon(Icons.image_outlined),
label: 'Image',
onTap: (){
_pageController.animateToPage(
0,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
),
SpeedDialChild(
child: Icon(Icons.video_call),
label: 'Video',
onTap: (){
_pageController.animateToPage(
2,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
),
SpeedDialChild(
child: Icon(Icons.audiotrack),
label: 'Audio',
onTap: (){
_pageController.animateToPage(
1,
duration: 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: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Text('+'),
),
Icon(secondIcon, color: Colors.white, size: 14,),
],
): SizedBox()
],
),
label: Text(label, style: TextStyle(color: Colors.white, fontSize: 12)),
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, backgroundColor: Colors.deepPurpleAccent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 2,
padding: 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: 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: Text('High'),
value: CompressionLevel.high,
groupValue: selectedLevel,
onChanged: (CompressionLevel? value) {
setState(() {
selectedLevel = value;
});
},
),
RadioListTile<CompressionLevel>(
title: Text('Medium'),
value: CompressionLevel.medium,
groupValue: selectedLevel,
onChanged: (CompressionLevel? value) {
setState(() {
selectedLevel = value;
});
},
),
RadioListTile<CompressionLevel>(
title: Text('Low'),
value: CompressionLevel.low,
groupValue: selectedLevel,
onChanged: (CompressionLevel? value) {
setState(() {
selectedLevel = value;
});
},
),
],
);
},
),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: 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,
);
}
},
),
],
);
},
);
}
}