mbakabilal
mbakabilal

Reputation: 596

Flutter download progress in notificaiton

Hi is there a way to show download progress in a notification in flutter apps, i know there are plugins that handle downloads and show download progress in notifications such as FlutterDownloader plugin.

I want to do this by myself using flutter, is there any way to do this or do i have to do it natively?.

Something Like this:

enter image description here

Upvotes: 6

Views: 7542

Answers (1)

mbakabilal
mbakabilal

Reputation: 596

This is for anyone who does not want to use a package like FlutterDownloader to handle downloads but might want to use http or Dio and flutter_local_notifications to show progress when app is in the foreground.

First the provider class to handle state of in app circular progress indicator:

    class DownloadProvider extends ChangeNotifier {
  var _progressList = <double>[];

  // double count = 0.0;

  double currentProgress(int index) {
    //fetch the current progress,
    //its in a list because we might want to download
    // multiple files at the same time,
    // so this makes sure the correct download progress
    // is updated.
    
    
    try {
      return _progressList[index];
    } catch (e) {
      _progressList.add(0.0);
      return 0;
    }
  }

  void download(String filePath, int index) async {
    NotificationService notificationService = NotificationService();

    final storageRef = FirebaseStorage.instance.ref().child(filePath);
    final downloadUrl = await storageRef.getDownloadURL();

    final fileName = storageRef.name;

    final dio = Dio();

    try {
      dio.download(downloadUrl, "/storage/emulated/0/Download/$fileName",
          onReceiveProgress: ((count, total) async {
        await Future.delayed(const Duration(seconds: 1), () {
          _progressList[index] = (count / total);
          notificationService.createNotification(
              100, ((count / total) * 100).toInt(), index);
          notifyListeners();
        });
      }));
    } on DioError catch (e) {
      print("error downloading file $e");
    }
  }
}

class NotificationService {
  //Hanle displaying of notifications.
  static final NotificationService _notificationService =
      NotificationService._internal();
  final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  final AndroidInitializationSettings _androidInitializationSettings =
      const AndroidInitializationSettings('ic_launcher');

  factory NotificationService() {
    return _notificationService;
  }

  NotificationService._internal() {
    init();
  }

  void init() async {
    final InitializationSettings initializationSettings =
        InitializationSettings(
      android: _androidInitializationSettings,
    );
    await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
  }

  void createNotification(int count, int i, int id) {
    //show the notifications.
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'progress channel', 'progress channel',
        channelDescription: 'progress channel description',
        channelShowBadge: false,
        importance: Importance.max,
        priority: Priority.high,
        onlyAlertOnce: true,
        showProgress: true,
        maxProgress: count,
        progress: i);
    var platformChannelSpecifics =
        NotificationDetails(android: androidPlatformChannelSpecifics);
    _flutterLocalNotificationsPlugin.show(id, 'progress notification title',
        'progress notification body', platformChannelSpecifics,
        payload: 'item x');
  }
}

Then in your main class for displaying the download you can connect to the provider, thus:

Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Consumer<DownloadProvider>(
            builder: (context, value, ch) {
              return Center(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                        onPressed: () {
                          value.download('your soul ft biswick', 0);
                        },
                        child: const Text("Download")),
                    CircularProgressIndicator(
                      value: value.currentProgress(0),
                    )
                  ],
                ),
              );
            },
          ),

I hope this helps whoever in the future, i will figure out how to make this run in the background and edit my answer in the future. 🤞

Upvotes: 11

Related Questions