Newby Coder header banner

Flutter Local Notification

Local Notifications in Flutter Android/iOS application

flutter_local_notifications package allows to show different types of notifications like plain notifications, notification with picture and big text, schedule notifications etc

Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here local_notification_app) :

flutter create local_notification_app

Dependency

Implementation

Importing Package
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// for getApplicationDocumentsDirectory()
import 'package:path_provider/path_provider.dart';
// for BehaviorSubject
import 'package:rxdart/subjects.dart';

Initialize

flutterLocalNotificationsPlugin.initialize() method is to be called in main() function

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();
final BehaviorSubject<String> selectNotificationSubject =
    BehaviorSubject<String>();

Future<void> main() async {
  // To initialize in the `main` function
  WidgetsFlutterBinding.ensureInitialized();
  // To find out if the app was launched via notification, the following call can be used and then something like
  // changing the default route of the app can be done
  var notificationAppLaunchDetails =
      await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
  print("launch details : ${notificationAppLaunchDetails}");
  var initializationSettingsAndroid = AndroidInitializationSettings('app_icon');
  var initializationSettingsIOS = IOSInitializationSettings(
        requestSoundPermission: false,
        requestBadgePermission: false,
        requestAlertPermission: false
    );
  var initializationSettings = InitializationSettings(
      initializationSettingsAndroid, initializationSettingsIOS);
  await flutterLocalNotificationsPlugin.initialize(initializationSettings,
      onSelectNotification: (String payload) async {
    if (payload != null) {
      debugPrint('notification payload: ' + payload);
    }
    selectNotificationSubject.add(payload);
  });
  runApp(
    MaterialApp(
      home: HomePage(),
    ),
  );
}

Sending plain notification

Following worked for both android and ios

flutterLocalNotificationsPlugin.show() method is used to show a notification

Future<void> _showNotification() async {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'plain channel id', 'plain channel name', 'plain channel description',
        importance: Importance.Max, priority: Priority.High, ticker: 'ticker');
    var platformChannelSpecifics = NotificationDetails(
        androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(
        0, 'plain title', 'plain body', platformChannelSpecifics,
        payload: 'plain notification payload');
}

Scheduling notification

Future<void> _scheduleNotification() async {
    var scheduledNotificationDateTime =
        DateTime.now().add(Duration(seconds: 5));
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'schedule channel id',
        'schedule channel name',
        'schedule channel description',
        icon: 'secondary_icon',
        );
    var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.schedule( 1, 'scheduled_notification title',
        'scheduled_notification body', scheduledNotificationDateTime,
        platformChannelSpecifics, androidAllowWhileIdle: true,
        payload: 'scheduled notification payload');
}

App Code

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:rxdart/subjects.dart';
//import 'package:flutter/cupertino.dart';


final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();
final BehaviorSubject<String> selectNotificationSubject =
    BehaviorSubject<String>();
final BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject =
    BehaviorSubject<ReceivedNotification>();

class ReceivedNotification {
  final int id;
  final String title;
  final String body;
  final String payload;

  ReceivedNotification( {@required this.id, @required this.title,
      @required this.body, @required this.payload});
}


Future<void> main() async {
  // To initialize in the `main` function
  WidgetsFlutterBinding.ensureInitialized();
  // To find out if the app was launched via notification, the following call can be used and then default route of the
  // app can be changed or something similar
  var notificationAppLaunchDetails =
      await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
  print("launch details : ${notificationAppLaunchDetails}");
  var initializationSettingsAndroid = AndroidInitializationSettings('app_icon');
  var initializationSettingsIOS = IOSInitializationSettings(
        requestSoundPermission: false,
        requestBadgePermission: false,
        requestAlertPermission: false
    );
  var initializationSettings = InitializationSettings(
      initializationSettingsAndroid, initializationSettingsIOS);
  await flutterLocalNotificationsPlugin.initialize(initializationSettings,
      onSelectNotification: (String payload) async {
    if (payload != null) {
      debugPrint('notification payload: ' + payload);
    }
    selectNotificationSubject.add(payload);
  });
  runApp(
    MaterialApp(
      home: HomePage(),
    ),
  );
}

class PaddedRaisedButton extends StatelessWidget {
  final String buttonText;
  final VoidCallback onPressed;
  const PaddedRaisedButton(
      {@required this.buttonText, @required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 8.0),
      child: RaisedButton(child: Text(buttonText), onPressed: onPressed),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();

    selectNotificationSubject.stream.listen((String payload) async {
      await Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => SecondScreen(payload)),
      );
    });
  }

  @override
  void dispose() {
    selectNotificationSubject.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Notifications example app'),
        ),
        body: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: Padding(
            padding: EdgeInsets.all(8.0),
            child: Center(
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 8.0),
                    child: Text(
                        'Tap on a notification when it appears to trigger navigation'),
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Show plain notification with payload',
                    onPressed: () async {
                      await _showNotification();
                    },
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Schedule notification to appear in 5 seconds',
                    onPressed: () async {
                      await _scheduleNotification();
                    },
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Show big picture notification [Android]',
                    onPressed: () async {
                      await _showBigPictureNotification();
                    },
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Show ongoing notification [Android]',
                    onPressed: () async {
                      await _showOngoingNotification();
                    },
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Check pending notifications',
                    onPressed: () async {
                      await _checkPendingNotificationRequests();
                    },
                  ),
                  PaddedRaisedButton(
                    buttonText: 'Cancel all notifications',
                    onPressed: () async {
                      await _cancelAllNotifications();
                    },
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  Future<void> _showNotification() async {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'plain channel id', 'plain channel name', 'plain channel description',
        importance: Importance.Max, priority: Priority.High, ticker: 'ticker');
    var platformChannelSpecifics = NotificationDetails(
        androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(
        0, 'plain title', 'plain body', platformChannelSpecifics,
        payload: 'plain notification payload');
  }

  Future<void> _scheduleNotification() async {
    var scheduledNotificationDateTime =
        DateTime.now().add(Duration(seconds: 5));
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'schedule channel id',
        'schedule channel name',
        'schedule channel description',
        icon: 'secondary_icon',
        );
    var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.schedule( 1, 'scheduled_notification title',
        'scheduled_notification body', scheduledNotificationDateTime,
        platformChannelSpecifics, androidAllowWhileIdle: true,
        payload: 'scheduled notification payload');
  }

  Future<String> _downloadAndSaveImage(String url, String fileName) async {
    var directory = await getApplicationDocumentsDirectory();
    var filePath = '${directory.path}/$fileName';
    var response = await http.get(url);
    var file = File(filePath);
    await file.writeAsBytes(response.bodyBytes);
    return filePath;
  }

  Future<void> _showBigPictureNotification() async {
    var largeIconPath = await _downloadAndSaveImage(
        'http://via.placeholder.com/128x128/00FF00/000000', 'largeIcon');
    var bigPicturePath = await _downloadAndSaveImage(
        'http://via.placeholder.com/400x800', 'bigPicture');
    var bigPictureStyleInformation = BigPictureStyleInformation(
        FilePathAndroidBitmap(bigPicturePath),
        largeIcon: FilePathAndroidBitmap(largeIconPath),
        contentTitle: 'overridden <b>big</b> content title',
        htmlFormatContentTitle: true,
        summaryText: 'summary <i>text</i>',
        htmlFormatSummaryText: true);
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'big_picture channel id',
        'big_picture channel name',
        'big_picture channel description',
        styleInformation: bigPictureStyleInformation);
    var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(
        2, 'big_picture_minimized title', 'big_picture_minimized body', platformChannelSpecifics);
  }

  Future<void> _showOngoingNotification() async {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'ongoing channel id', 'ongoing channel name', 'ongoing channel description',
        importance: Importance.Max,
        priority: Priority.High,
        ongoing: true,
        autoCancel: false);
    var platformChannelSpecifics = NotificationDetails(
        androidPlatformChannelSpecifics, null);
    await flutterLocalNotificationsPlugin.show(4, 'ongoing_notification title',
        'ongoing_notification body', platformChannelSpecifics);
  }

  Future<void> _checkPendingNotificationRequests() async {
    var pendingNotificationRequests =
        await flutterLocalNotificationsPlugin.pendingNotificationRequests();
    for (var pendingNotificationRequest in pendingNotificationRequests) {
      debugPrint(
          'pending notification: [id: ${pendingNotificationRequest.id}, title: ${pendingNotificationRequest.title}, body: ${pendingNotificationRequest.body}, payload: ${pendingNotificationRequest.payload}]');
    }
    return showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Text(
              '${pendingNotificationRequests.length} pending notification requests'),
          actions: [
            FlatButton(
              child: Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  Future<void> _cancelAllNotifications() async {
    await flutterLocalNotificationsPlugin.cancelAll();
  }
}

class SecondScreen extends StatefulWidget {
  SecondScreen(this.payload);

  final String payload;

  @override
  State<StatefulWidget> createState() => SecondScreenState();
}

class SecondScreenState extends State<SecondScreen> {
  String _payload;
  @override
  void initState() {
    super.initState();
    _payload = widget.payload;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen with payload: ${(_payload ?? '')}'),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

Run instructions

Ensure a supported device is connected or emulator/simulator is started

Go to project directory

Use flutter run command to run

flutter run

It builds and runs app on an available android/ios device


Screenshot/Screencast

Android

cl-flutter-notifications

iOS

cm_flutter_local_notification_as1cm_flutter_local_notification_as2cm_flutter_local_notification_as3
cm_flutter_local_notification_as4