0

I have tried to setup local notification. It works fine, except when I tap on the notification, it does not goes to the page I want. I have tried to on the simulator and also on my phone, but in both case, my application is not going to the page I want.

I do not understand what is the problem. Please, can you help? Thank you.

void initState() {
    super.initState();

    getSharedPreferences();

    NotificationApi.init();
    listenNotifications();

    saveQuotaLimit();
    retrieveQuotaLimit();

    MyNotification.initialize(flutterLocalNotificationsPlugin);

    subscription = Connectivity().onConnectivityChanged.listen((result) {
      setState(() => this.result = result);
    });

    internetSubscription =
        InternetConnectionChecker().onStatusChange.listen((status) {
          final hasInternet = status == InternetConnectionStatus.connected;

          setState(() => this.hasInternet = hasInternet);

          if (hasInternet != true) {
            msgSnackBar(context, tNoInternetError,);
          } else {return;}
        });
   // WidgetsBinding.instance.addObserver(this);
  }

void listenNotifications () =>
      NotificationApi.onNotifications.stream.listen((event) {
        onClickedNotifications;
      });
void onClickedNotifications(String? payload)
      {
      print ('myPayload = $payload');
      Navigator.of(context).push(
          MaterialPageRoute(builder: (context)=>FirestoreDataDisplay( documentId: payload,)));
}
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:manage_calendar_events/manage_calendar_events.dart';
import 'package:rxdart/rxdart.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
import 'package:flutter_native_timezone/flutter_native_timezone.dart';

class NotificationApi {
  static final _notifications = FlutterLocalNotificationsPlugin();
  static final onNotifications = BehaviorSubject<String?>();


  static Future<void> configureLocalTimeZone() async {
    tz.initializeTimeZones();
    final String timeZone = await FlutterNativeTimezone.getLocalTimezone();
    tz.setLocalLocation(tz.getLocation(timeZone));
  }


  static Future init({bool initScheduled = false}) async {
    const android = AndroidInitializationSettings('@mipmap/ic_launcher');
    const iOS = IOSInitializationSettings();
    const settings = InitializationSettings(android: android, iOS: iOS);

    /// Handle payload when app is closed
    final details = await _notifications.getNotificationAppLaunchDetails();
    if (details != null && details.didNotificationLaunchApp) {
      onNotifications.add(details.payload);
    }

    await _notifications.initialize(
      settings,
      onSelectNotification: (payload) async {
        onNotifications.add(payload);
      },
    );

    if (initScheduled) {
      tz.initializeTimeZones();
      final locationName = await FlutterNativeTimezone.getLocalTimezone();
      tz.setLocalLocation(tz.getLocation(locationName));
    }
  }

  /// Direct Notification
  static Future showNotification({
    int id = 0,
    String? title,
    String? body,
    String? payload,
  }) async =>
      _notifications.show(
        id,
        title,
        body,
        await _notificationDetails(),
        payload: payload,
      );

  /// Notification for specific DateTime
  static void showScheduledNotification({
    int? id ,
    String? title,
    String? body,
    String? payload,
    required DateTime scheduledDate,
  }) async =>
      _notifications.zonedSchedule(
        id!,
        title,
        body,
        tz.TZDateTime.from(scheduledDate, tz.local),
        await _notificationDetails(),
        payload: payload,
        androidAllowWhileIdle: true,
        uiLocalNotificationDateInterpretation:
        UILocalNotificationDateInterpretation.absoluteTime,
      );

  static Future _notificationDetails() async {

    /// Download: https://samplefocus.com/samples/chime-notification-alert
    const sound = 'notification_sound.wav';
    return NotificationDetails(
      android: AndroidNotificationDetails(
        'channel id 8',
        'channel name',
        channelDescription: 'channel description',
        importance: Importance.max,
        //playSound: false,
        sound: RawResourceAndroidNotificationSound(sound.split('.').first),
        enableVibration: false,
        //  styleInformation: styleInformation,
      ),
      iOS: const IOSNotificationDetails(
        presentSound: false,
        sound: sound,
      ),
    );
  }

  static tz.TZDateTime _scheduleDaily(Time time) {
    final now = tz.TZDateTime.now(tz.local);
    final scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day,
        time.hour, time.minute, time.second);

    return scheduledDate.isBefore(now)
        ? scheduledDate.add(const Duration(days: 1))
        : scheduledDate;
  }

  static List<tz.TZDateTime> _scheduleWeekly(Time time,
      {required List<int> days}) {
    return days.map((day) {
      tz.TZDateTime scheduledDate = _scheduleDaily(time);

      while (day != scheduledDate.weekday) {
        scheduledDate = scheduledDate.add(const Duration(days: 1));
      }
      return scheduledDate;
    }).toList();
  }

  static void cancel(int id) => _notifications.cancel(id);

  static void cancelAll() => _notifications.cancelAll();

  static int convertStringToHash (String id) {

    int notificationId = id.hashCode;

    return notificationId;
  }  
}

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';


class FirestoreDataDisplay extends StatefulWidget {
  final String? documentId;

  const FirestoreDataDisplay({super.key, required this.documentId});

  @override
  State<FirestoreDataDisplay> createState() => _FirestoreDataDisplayState();
}

class _FirestoreDataDisplayState extends State<FirestoreDataDisplay> {
  late Future<DocumentSnapshot> _documentSnapshot;

  @override
  void initState() {
    super.initState();

    print ('Mon test = ${widget.documentId}');
    _documentSnapshot = fetchData(widget.documentId!);
  }

  Future<DocumentSnapshot<Map<String, dynamic>>> fetchData(String documentId) async {
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    return await firestore.collection('Users').doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .doc(documentId)
        .get();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<DocumentSnapshot>(
      future: _documentSnapshot,
      builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasData) {
            Map<String, dynamic> data = snapshot.data!.data()! as Map<String, dynamic>;

            List<Widget> widgets = data.entries.map((entry) {
              return Column(
                children: [
                  Text('${entry.key}: ${entry.value}'),
                  // Ajoutez des DropdownButton ou des TextFormField ici si nécessaire
                ],
              );
            }).toList();

            return Scaffold(
              appBar: AppBar(title: const Text('Résultats')),
              body: SingleChildScrollView(
                child: Column(children: widgets),
              ),
            );
          } else {
            return Scaffold(
              appBar: AppBar(title: const Text('Erreur')),
              body: const Center(child: Text('Le document n\'a pas été trouvé')),
            );
          }
        } else {
          return Scaffold(
            appBar: AppBar(title: const Text('Chargement')),
            body: const Center(child: CircularProgressIndicator()),
          );
        }
      },
    );
  }
}

New code

void onClickedNotifications(String? payload)
      {
      print ('myPayload = $payload');

      navigatorKey.currentState!.pushNamed('/someRoute');

      Navigator.pushNamed(context, '/someRoute');
      
}
class MyApp  extends StatelessWidget {

  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case '/':
        return MaterialPageRoute(builder: (_) => HomePage(navigatorKey: navigatorKey));
      case '/someRoute':
        return MaterialPageRoute(builder: (_) => const testPayload());
      default:
        return MaterialPageRoute(builder: (_) => NotFoundPage());
    }}
 // final bool isDark;
   MyApp ({Key? key,
    //required this.isDark
  }) : super(key: key);
import 'package:flutter/material.dart';


class testPayload extends StatefulWidget {
  const testPayload({Key? key}) : super(key: key);

  @override
  State<testPayload> createState() => _testPayloadState();
}

class _testPayloadState extends State<testPayload> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Hello'),
      ),
    );
  }
}
Laurent Thomas
  • 232
  • 4
  • 24
  • Remove the Navigator.of(context).push() and try this: https://stackoverflow.com/a/53397266/14071053 – Aks Mar 26 '23 at 05:12
  • Thank you. I have tried, but unfortunatly it does not work. Neither on the simulator or my phone. It just stay on the current page. I have tried also when the app is in the background or when it is active on the screen. I do not understand why. – Laurent Thomas Mar 26 '23 at 13:44
  • You need to define GlobalKey outside of any class, and inside MaterialApp(navigatorKey: your_navigator_key). – Aks Mar 26 '23 at 15:35
  • I am missing something here. If you can give me more details it would be appreciated. Thank you. – Laurent Thomas Mar 26 '23 at 17:43
  • check out the answer and use the navigatorKey.currentState!.pushNamed("/otherScreen"); anywhere you want to navigate. – Aks Mar 27 '23 at 04:56

1 Answers1

0

Navigate without context.

main.dart

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
  debugShowCheckedModeBanner: false,
  navigatorKey: navigatorKey,
  home: const HomePage(),
  onGenerateRoute: (settings) {
    switch (settings.name) {
      case "/":
        return MaterialPageRoute(
          builder: (context) {
            return const HomePage();
          },
        );
      case OtherPage.route:
        return MaterialPageRoute(
          builder: (context) {
            return const OtherPage();
          },
        );
      default:
        return MaterialPageRoute(
          builder: (_) => const HomePage(),
        );
    }
  },
);
}
}

class HomePage extends StatelessWidget {
const HomePage({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
            onPressed: () {
              //navigate without context
              navigatorKey.currentState!.pushNamed("/otherScreen");
            },
            child: const Text("Navigate"))
      ],
    ),
  ),
);
 }
}

class OtherPage extends StatelessWidget {
const OtherPage({super.key});

 static const route = "/otherScreen";

 @override
 Widget build(BuildContext context) {
 return const Scaffold(
  body: Center(
    child: Text("Other screen!"),
  ),
);
}
}
Aks
  • 405
  • 4
  • 6