4

This is the problem: notification is received by the app both with app in foreground or background (or terminated) but the snackbar for notification when the app is used doesn't work. I'm new in flutter so maybe I did some huge mistake.

I am showing my code below. If you want more information just ask and thanks for the help!

    // Import Package
    import 'dart:io';
    import 'package:app_gap_go/pages/admin/modifySingleMeeting.dart';
    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:firebase_messaging/firebase_messaging.dart';
    import 'package:flutter/material.dart';
    // import 'package:flutter/rendering.dart';

    // Import Other Package
    import 'package:provider/provider.dart';

    // Import Pagine
    import './pages/wrapper.dart';
    import './pages/setting/settings.dart';
    import './pages/riunioni/riunioni.dart';
    import './pages/auth/register.dart';
    import './pages/admin/pannelloAdmin.dart';
    import './pages/admin/modifyMeetings.dart';

    // Import Utility
    import 'utility/themeData.dart';

    // Import Services
    import './services/authService.dart';

    // Import Models
    import './models/user.dart';

    void main() {
      // debugPaintSizeEnabled = true;   
      // debugPaintBaselinesEnabled = true;
      // debugPaintPointersEnabled = true; 
      runApp(MyApp());
    }

    class MyApp extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _MyAppState();
      }
    }

    class _MyAppState extends State<MyApp> {
      final FirebaseMessaging _fcm = new FirebaseMessaging();
      final Firestore _db = Firestore.instance;
      final FirebaseAuth _auth = FirebaseAuth.instance;
      GlobalKey<ScaffoldState> scaffoldState = new GlobalKey<ScaffoldState>();

      // Request and save token
      Future _saveDeviceToken() async {
        String fcmToken = await _fcm.getToken();
        FirebaseUser user = await _auth.currentUser();
        if (fcmToken != null) {
          var tokenRef = _db
              .collection('utenti')
              .document(user.uid)
              .collection('tokens')
              .document(fcmToken);
          await tokenRef.setData({
            'token': fcmToken,
            'createdAt': FieldValue.serverTimestamp(),
            'platform': Platform.operatingSystem,
          });
        }
      }

      @override
      void initState() {
        _fcm.configure(
          onMessage: (Map<String, dynamic> message) async {
            print("onMessage: $message");

            final snackbar = SnackBar(
              content: Text(message['notification']['title']),
              action: SnackBarAction(
                label: 'Go',
                onPressed: () => null,
              ),
            );
            scaffoldState.currentState.showSnackBar(snackbar);
          },
          onResume: (Map<String, dynamic> message) async {
            print("onResume: $message");
          },
          onLaunch: (Map<String, dynamic> message) async {
            print("onLaunch: $message");
          },
        );
        if(Platform.isIOS) {
          _fcm.onIosSettingsRegistered.listen((data) {
            _saveDeviceToken();
          });
          _fcm.requestNotificationPermissions(IosNotificationSettings());
        } else {
          _saveDeviceToken();
        }
        _fcm.subscribeToTopic('meetings');
        super.initState();
      }

      @override
      Widget build(BuildContext context) {
        return StreamProvider<User>.value(
          key: scaffoldState,
          value: AuthService().user,
          child: MaterialApp(
            title: "GapGo",
            theme: themeApp,
            routes: {
              '/': (BuildContext context) => Wrapper(),
              '/register': (BuildContext context) => Register(),
              '/settings': (BuildContext context) => Settings(),
              '/riunioni': (BuildContext context) => Riunioni(),
              '/adminPanel': (BuildContext context) => PannelloAdmin(),
              '/modifyMeetings': (BuildContext context) => ModifyMeetings(),
              '/modifySingleMeeting': (BuildContext context) =>
                  ModifySingleMeeting(),
            },
          ),
        );
      }
    // End State
    }
Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
Dark Helmet
  • 81
  • 1
  • 6

4 Answers4

5

I literally faced the same issue, i neither could use a dialog nor a SnackBar, the problem is actually from not having the current context of your navigator route, here is my solution.

Bahij.Mik
  • 1,358
  • 2
  • 9
  • 22
  • 2
    Thanks! The problem was, as you said, I'm not having the current context of the widget tree. I solved moving the init state from main to the first widget displayed. – Dark Helmet Jan 05 '20 at 12:18
2

Change this:

SnackBarAction(
                label: 'Go',
                onPressed: () => null,
              ),

Into this:

SnackBarAction(
                label: 'Go',
                onPressed: () => print("pressed"),
              ),

According to the docs:

The label and onPressed arguments must be non-null.

https://api.flutter.dev/flutter/material/SnackBarAction/SnackBarAction.html

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • I changed but the snackbar still not working. I think the problem is related to this: `scaffoldState.currentState.showSnackBar(snackbar);` – Dark Helmet Jan 05 '20 at 11:57
  • @Peter Haddad that's incorrect. The argument can't be null e.g. `onPressed: null`, but function returning `null` should work just fine – Marcin Apr 14 '20 at 12:50
0

The problem is most likely due to the fact you're calling the scaffoldState key inside the StreamProvider.value widget but your routes are outside that widget. MaterialApp widget should be inside and incapsulate the Scaffold widget.

eyoeldefare
  • 2,136
  • 1
  • 15
  • 25
0

I have similar case in here the SnackBarAction show error because of const

 **const** SnackBar(
                      content: Text('Added item to the Cart '),
                      duration: Duration(seconds: 2),
                      action: SnackBarAction(
                        label: 'UNDO',
                        onPressed: () {},
                      ));
            },

SHOUD BE LIKE THIS

SnackBar(
                          content: Text('Added item to the Cart '),
                          duration: Duration(seconds: 2),
                          action: SnackBarAction(
                            label: 'UNDO',
                            onPressed: () {},
                          ));
                },
Ba khadher
  • 11
  • 3