5

I am using the flutter_local_notification package to handle notifications from a third party server (not firebase cloud messaging). Because I am using firebase but not firebase messaging, I am using the onSelectNotification function of the flutter-local_notification package.

This is the function that I pass to onSelectNotification:

static _selectNotification(String payload, StreamChatClient client, RemoteMessage message) {
    debugPrint('notification payload: $payload');

    if(payload.contains('livestream')) {
      Utils.db.getLiveRoom(payload.split(":")[1]).then((liveRoom) {
        Navigator.push(
          NavigationService.navigatorKey.currentContext!,
          MaterialPageRoute<void>(builder: (context) => LiveRoomChat(liveRoom: liveRoom)),
        );
      });
    }
    else {
      List<String> ids = message.data['channel_id'].toString().split('_');
      String receiverId = '';
      if(ids[0] == Utils.user?.uid) {
        receiverId = ids[1];
      }
      else {
        receiverId = ids[0];
      }

      Navigator.push(
        NavigationService.navigatorKey.currentContext!,
        MaterialPageRoute<void>(builder: (context) => MessageApi(
            sourceType: Utils.friends.containsKey(receiverId) ? SourceType.friends : SourceType.justMet,
            receiverId: receiverId,
            channelId: payload.split(":")[1],
            streamToken: Utils.user?.streamToken ?? '',
            client: client
        )),
      );
    }
  }

I have a global navigator key which I have defined in a NavigationService class, and I also assign this navigator key in the main.dart. This notification handling above works for ios but it does not work for android because NavigationService.navigatorKey.currentContext is always null on android. Does anyone know why this is the case on android, and what is the way to handle it?

3 Answers3

1

Can you try to run your code inside that?

@override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
     _selectNotification();
    });
  }

if you are not running your code in initstate try sending buildcontext to your function

static _selectNotification(BuildContext context, String payload, StreamChatClient client, RemoteMessage message) {}
Cenk YAGMUR
  • 3,154
  • 2
  • 26
  • 42
  • I can't put _selectNotification in an initState because the code lives inside a singleton class and not a stateful widget. I also cannot pass the context to the function because the _selectNotification function is being called by a top-level function in another stateful widget. That is, the function calling it does not have access to the build context – youcantgetridofmestackoverflow Dec 10 '22 at 12:29
0

I will share my project work flow it may help you.

Initialized FlutterLocalNotificationsPlugin instance as global variable(above main() method).

Defined a class GlobalVariable in main.dart

passing GlobalVariable.navState to parameter nagavigatorKey of MaterialApp in MyApp class.

in initState method of _MyAppState, initialized the flutterLocalNotificationPlugin.

in onSelectNotification method, made Navigation call within SchedulerBinding.instance.addPostFrameCallback.

Defined route of page in routes.dart file.

Please check the code. You may find anything useful.

    import ....

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
            FlutterLocalNotificationsPlugin();

    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
        runApp(MyApp());
    }


  onSelectNotification(String payload) async {
            
    SchedulerBinding.instance.addPostFrameCallback((_) {
                GlobalVariable.navState.currentState.pushNamed(
                    give routeName,
                    arguments: givearguments);
              });    
     
  }


    class GlobalVariable {
       static final GlobalKey<NavigatorState> navState = GlobalKey<NavigatorState>();
    }

    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          navigatorKey: GlobalVariable.navState, //this is must
          debugShowCheckedModeBanner: false,
          title: 'Home',
          home: ScreenOne(),
          routes: routes,
        );
      }
    
      @override
      void initState() {
        var initializationSettingsAndroid =
            new AndroidInitializationSettings('@mipmap/ic_launcher');
    
        var initializationSettings = new InitializationSettings(
            android: initializationSettingsAndroid);
        flutterLocalNotificationsPlugin.initialize(initializationSettings,
            onSelectNotification: onSelectNotification);
        registerNotification();
        super.initState();
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super. Dispose();
      }
    }
Ajith Ramsaran
  • 181
  • 3
  • 9
0

Did you mention permission inside your android manifest file?

 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

you will find their manifest file for example here

Example manifest file link