I am working on one project which have list of short videos and i want to donwload in external storage. I am using following packages:
- video_player: ^2.6.1
- path_provider: ^2.0.15
- flutter_downloader: ^1.10.2
- permission_handler: ^10.2.0
- gallery_saver: ^2.3.2
Successfully video is downloaded in external storage and I am able to play video from notification(from download status). but after once i opened video i can not seen any where in external storage, unable to find downloaded video.
As a solution i tried gallery_saver package but it shows msg video file not found. Please anybody can solve this issue.
Following are my code:
Added code in Mainifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="${applicationId}.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
FullCode
import 'dart:io';
import 'dart:isolate';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(debug: true);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late VideoPlayerController _controller ;
late Future<void> _initializeVideoPlayerFuture;
Duration _position = Duration.zero;
Duration _duration = Duration.zero;
int _progress = 0;
ReceivePort receivePort = ReceivePort();
static downloadCallback(id,status,progress){
SendPort? sendPort = IsolateNameServer.lookupPortByName("downloadingVideo");
sendPort?.send(progress);
}
@override
void initState(){
// TODO: implement initState
FlutterDownloader.registerCallback(downloadCallback);
IsolateNameServer.registerPortWithName(receivePort.sendPort, "downloadingVideo");
receivePort.listen((message) {
setState(() {
_progress = message;
});
});
_controller = VideoPlayerController.network("https://aleyia.tech/Noha_Status/Ramzan_Status/ramzan.mp4")
..addListener(() {
if (mounted) {
setState(() {
_position = _controller.value.position;
_duration = _controller.value.duration;
});
}
});
//_controller = VideoPlayerController.asset("assets/ramzan.mp4");
_initializeVideoPlayerFuture = _controller.initialize().then((value) => setState((){}));
_controller.setVolume(1.0);
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_controller.dispose();
}
String _formatDuration(Duration duration) {
final HH = (duration.inHours).toString().padLeft(2, '0');
final mm = (duration.inMinutes % 60).toString().padLeft(2, '0');
final ss = (duration.inSeconds % 60).toString().padLeft(2, '0');
return '$mm:$ss';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Video from url"),),
body: Column(
children: [
Center(
child: _controller.value.isInitialized ?
AspectRatio(aspectRatio: _controller.value.aspectRatio,
child: GestureDetector(
//behavior: HitTestBehavior.opaque,
onTap: (){
setState(() {
_controller.value.isPlaying ? _controller.pause() :
_controller.play();
});
},
child: Stack(
children: [
VideoPlayer(_controller),
_controller.value.isPlaying ? Container():
Container(
alignment: Alignment.center,
color: Colors.black26,
child: Icon(Icons.play_arrow,color: Colors.white,size: 80,)),
Positioned(
bottom: 0,
right: 0,
left: 0,
child: VideoProgressIndicator(_controller, allowScrubbing: true)),
Positioned(
bottom: 0,
right: 0,
child:
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
_formatDuration(_position),
style: TextStyle(fontSize: 11,color: Colors.white),
),
Text("/",style: TextStyle(fontSize: 12,color: Colors.white),),
Text(
_formatDuration(_duration),
style: TextStyle(fontSize: 11,color: Colors.white),
),
],
),
),),
Positioned(
right: 0,
top: 0,
child: IconButton(onPressed: () {
print("download tap");
_downloadFile();
},
icon: Icon(Icons.download, color: Colors.white,),))
],
),
),) :
const CircularProgressIndicator()
),
Text("Download percentage $_progress")
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
if(_controller.value.isPlaying){
_controller.pause();
}else{
_controller.play();
}
});
},
child: Icon(_controller.value.isPlaying ? Icons.pause : Icons.play_arrow_outlined),
),
);
}
void _downloadFile() async{
var url = "https://server/video.mp4";
final status = await Permission.storage.request();
if(status.isGranted){
final baseStorage = await getExternalStorageDirectory();
final id = await FlutterDownloader.enqueue(url: url,
savedDir: baseStorage!.path,
fileName: "status_video.mp4",
openFileFromNotification: true,
showNotification: true,
//headers: {"Content-Type": "video/mp4"},
);
print('Download started: $id');
print('File saved at: $baseStorage');
final file = File('$baseStorage/status_video.mp4');
final isFileExists = await file.exists();
if (isFileExists) {
final result = await GallerySaver.saveVideo(file.path);
print('Video file saved: $result');
} else {
print('Video file not found.');
}
} else {
print('Storage permission not granted.');
}
}
}