Search code examples
flutterfirebase-cloud-messagingflutter-getx

FirebaseMessaging.instance.getInitialMessage() not working with Splash Screen


I have integrated Firebase Cloud Messaging to my Flutter mobile app with the help of GetX State Management. Also I used Laravel with Firebase Admin SDK to send notification to my app.

The notification is working fine on both foreground state and background state (paused). The problem starts when I click the notification where the app is in terminated state (app closed). Do I have to set a delay between the splashscreen and main page?

I have tried to do this but error still occur

//open notif content from terminated state of the app
FirebaseMessaging.instance.getInitialMessage().then((message) {
  if (message != null) {
    print('TERMINATED');
    if (FirebaseAuth.instance.currentUser != null) {
      final redirectRoute = message.data['route'];
      if (redirectRoute != null) {    
        //adding delay here since my splashscreen have the same delay        
        Future.delayed(const Duration(seconds: 6));
        bottomnavbarController.updateIndex(int.parse(redirectRoute));
      }
    } else {
      Get.offAllNamed(Routes.LOGIN);
    }
  }
});

I get this error

Unhandled Exception: 
You are trying to use contextless 
navigation without a GetMaterialApp or Get.key

Here is my main.dart

    //open notif content from terminated state of the app
    FirebaseMessaging.instance.getInitialMessage().then((message) {
      if (message != null) {
        if (FirebaseAuth.instance.currentUser == null) {
          Get.offAllNamed(Routes.LOGIN);
        } else {
          final redirectRoute = message.data['route'];
          if (redirectRoute != null) {
            print('TERMINATED');
            bottomnavbarController.updateIndex(int.parse(redirectRoute));
          }
        }
      }
    });
   

  @override
  Widget build(BuildContext context) {
    final authController = Get.put(AuthController(), permanent: true);
    return FutureBuilder(
      future: Future.delayed(const Duration(seconds: 6)),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return Obx(
            () => GetMaterialApp(
              debugShowCheckedModeBanner: false,              
              title: "Application",
              theme: ThemeData(
                appBarTheme: const AppBarTheme(
                    elevation: 0.2,
                    foregroundColor: Colors.black,
                    backgroundColor: Colors.white),
              ),
              initialRoute: authController.isSkipIntro.isTrue
                  ? authController.isAuthAndVerified.isTrue
                      ? Routes.PAGEWRAPPER
                      : Routes.LOGIN
                  : Routes.INTRODUCTION,
              getPages: AppPages.routes,
            ),
          );
        }

        return FutureBuilder(
          future: authController.firstInitialize(),
          builder: (context, snapshot) {
            return const SplashScreen();
          },
        );
      },
    );
  }

Here is my bottom nav controller

class BottomnavbarController extends GetxController {
  final bottomNavIndex = 0.obs;  
  
  void updateIndex(int index){
    bottomNavIndex.value = index;
    Get.offAllNamed(Routes.PAGEWRAPPER);
  }
}

Here's the log

Launching lib\main.dart on RNE L22 in release mode...
Running Gradle task 'assembleRelease'...                           76.4s
√  Built build\app\outputs\flutter-apk\app-release.apk (10.0MB).
Installing build\app\outputs\flutter-apk\app.apk...                 3.4s

Flutter run key commands.
h List all available interactive commands.       
c Clear the screen
q Quit (terminate the application on the device).
W/FlutterJNI(10061): FlutterJNI.loadLibrary called more than once
W/FlutterJNI(10061): FlutterJNI.prefetchDefaultFontManager called more than once
W/FlutterJNI(10061): FlutterJNI.init called more than once
W/FlutterJNI(10239): FlutterJNI.loadLibrary called more than once
W/FlutterJNI(10239): FlutterJNI.init called more than once
I/flutter (10239): Handling a background message: 0:1646807530074172%f77b2610f77b2610
I/flutter (10239): TERMINATED
E/flutter (10239): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: You are trying to use contextless navigation without
E/flutter (10239):       a GetMaterialApp or Get.key.
E/flutter (10239):       If you are testing your app, you can use:
E/flutter (10239):       [Get.testMode = true], or if you are running your app on
E/flutter (10239):       a physical device or emulator, you must exchange your [MaterialApp]
E/flutter (10239):       for a [GetMaterialApp].
E/flutter (10239):
E/flutter (10239): #0      GetNavigation.global (package:get/get_navigation/src/extension_navigation.dart:1094)
E/flutter (10239): #1      GetNavigation.offAllNamed (package:get/get_navigation/src/extension_navigation.dart:786)
E/flutter (10239): #2      BottomnavbarController.updateIndex (package:prototypeapp/app/modules/bottomnavbar/controllers/bottomnavbar_controller.dart:9)
E/flutter (10239): #3      _MyAppState.initState.<anonymous closure> (package:prototypeapp/main.dart:64)
E/flutter (10239): #4      _rootRunUnary (dart:async/zone.dart:1434)
E/flutter (10239): <asynchronous suspension>
E/flutter (10239): 
I/flutter (10239): Null check operator used on a null value
I/flutter (10239): #0      PageRedirect.page (package:get/get_navigation/src/routes/route_middleware.dart:199)
I/flutter (10239): #1      GetMaterialApp.initialRoutesGenerate (package:get/get_navigation/src/root/get_material_app.dart:348)
I/flutter (10239): #2      _WidgetsAppState.build.<anonymous closure> (package:flutter/src/widgets/app.dart:1556)
I/flutter (10239): #3      NavigatorState.restoreState (package:flutter/src/widgets/navigator.dart:3290)
I/flutter (10239): #4      RestorationMixin._doRestore (package:flutter/src/widgets/restoration.dart:887)
I/flutter (10239): #5      RestorationMixin.didChangeDependencies (package:flutter/src/widgets/restoration.dart:873)
I/flutter (10239): #6      NavigatorState.didChangeDependencies (package:flutter/src/widgets/navigator.dart:3336)
I/flutter (10239): #7      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4914)
I/flutter (10239): #8      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #9      Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #10     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #11     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #12     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #13     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #14     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #15     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #16     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #17     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #18     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #19     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #20     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #21     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #22     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #23     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #24     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #25     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #26     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #27     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #28     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #29     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #30     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #31     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #32     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #33     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #34     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #35     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #36     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #37     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #38     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #39     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #40     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #41     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #42     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #43     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #44     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #45     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #46     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #47     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #48     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #49     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #50     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #51     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #52     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #53     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #54     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #55     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #56     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #57     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #58     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #59     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #60     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928)
I/flutter (10239): #61     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #62     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #63     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4919)
I/flutter (10239): #64     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #65     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #66     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #67     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #68     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #69     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #70     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #71     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #72     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #73     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #74     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928)
I/flutter (10239): #75     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #76     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #77     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4919)
I/flutter (10239): #78     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #79     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #80     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #81     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #82     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #83     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #84     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #85     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #86     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #87     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #88     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #89     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #90     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #91     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #92     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #93     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)
I/flutter (10239): #94     Element.rebuild (package:flutter/src/widgets/framework.dart:4477)
I/flutter (10239): #95     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4735)
I/flutter (10239): #96     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729)
I/flutter (10239): #97     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790)
I/flutter (10239): #98     Element.updateChild (package:flutter/src/widgets/framework.dart:3540)
I/flutter (10239): #99     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780)

Solution

  • I have solved this problem with an alternative solution for now. Here is the main.dart

    @override
    void initState() {
      super.initState();
    
      //open notif content from terminated state of the app
      FirebaseMessaging.instance.getInitialMessage().then((message) {
        if (message != null) {
          print('TERMINATED');
          final redirectRoute = message.data['route'];
          print('redirectRoute $redirectRoute');
          bottomnavbarController.updateIndex(int.parse(redirectRoute));
          //remove redirect route here, so the unknownRoute will trigger the default route
        }
      });
    
      //only works if app in foreground
      FirebaseMessaging.onMessage.listen((message) {
        LocalNotificationService.display(message);
      });
    
      //onclick notif system tray only works if app in background but not termi
      FirebaseMessaging.onMessageOpenedApp.listen((message) {
        final redirectRoute = message.data['route'];
        if (redirectRoute != null) {
          print('BACKGROUND');
          print('redirectRoute $redirectRoute');
          bottomnavbarController.updateIndex(int.parse(redirectRoute));
          Get.offAllNamed(Routes.PAGEWRAPPER);
        }
      });
    }
    
    @override
    Widget build(BuildContext context) {
      final authController = Get.put(AuthController(), permanent: true);
      return FutureBuilder(
        future: Future.delayed(const Duration(seconds: 6)),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Obx(
              () => GetMaterialApp(
                  debugShowCheckedModeBanner: false,
                  title: "Application",
                  theme: ThemeData(
                    appBarTheme: const AppBarTheme(
                        elevation: 0.2,
                        foregroundColor: Colors.black,
                        backgroundColor: Colors.white),
                  ),
                  initialRoute: authController.isSkipIntro.isTrue
                      ? authController.isAuthAndVerified.isTrue
                          ? Routes.PAGEWRAPPER
                          : Routes.LOGIN
                      : Routes.INTRODUCTION,
                  getPages: AppPages.routes,
                  unknownRoute: authController.isAuthAndVerified.isTrue ? AppPages.routes[11] : AppPages.routes[1],
              ),
            );
          }
          return FutureBuilder(
            future: authController.firstInitialize(),
            builder: (context, snapshot) {
              return const SplashScreen();
            },
          );
        },
      );
    }
    

    I added this unknownRoute: on GetMaterialApp if the route is null which passing an array to the index of pagewrapper o login page inside AppPages class since the route in getInitialMessage() returns null.

    I have define using Get.key and still returns null. Maybe app_routes.dart is not created yet before GetMaterialApp. Maybe that is why it returns null.

    I still don't know why this is happening. Maybe it is a bug for GetX plugin. Anyway, this still works for me since I have updated the bottom nav index.