Android Local Notifications Not Working

Custom Code

I'm trying to set up my notifications to work on android, as I am now preparing to launch my app on the Google Play Store. Here is the code so far:

// Automatic FlutterFlow imports

import '/backend/backend.dart';

import '/flutter_flow/flutter_flow_theme.dart';

import '/flutter_flow/flutter_flow_util.dart';

import '/custom_code/actions/index.dart'; // Imports other custom actions

import '/flutter_flow/custom_functions.dart'; // Imports custom functions

import 'package:flutter/material.dart';

// Begin custom action code

// DO NOT REMOVE OR MODIFY THE CODE ABOVE!


import 'dart:io';

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

import 'package:cloud_firestore/cloud_firestore.dart';

import 'package:flutter_timezone/flutter_timezone.dart';

import 'package:timezone/data/latest_all.dart' as tz;

import 'package:timezone/timezone.dart' as tz;

import 'package:flutter/foundation.dart';


Future<void> scheduleNotificationsForEvent(String eventId) async {

if (kIsWeb) return;


try {

final plugin = FlutterLocalNotificationsPlugin();


// 1) Initialize plugin on BOTH platforms, first thing.

const androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');

const iosInit = DarwinInitializationSettings();

const initSettings =

InitializationSettings(android: androidInit, iOS: iosInit);

await plugin.initialize(initSettings);


// 2) Android permission + channel (must exist before schedule).

final android = plugin.resolvePlatformSpecificImplementation<

AndroidFlutterLocalNotificationsPlugin>();

await android?.requestNotificationsPermission();

if (Platform.isAndroid) {

const ch = AndroidNotificationChannel(

'event_channel',

'Event Reminders',

description: 'Notifications for scheduled events',

importance: Importance.max,

playSound: true,

);

await android?.createNotificationChannel(ch);

}


// 3) Timezone setup (once, robust fallback).

tz.initializeTimeZones();

try {

final tzName = await FlutterTimezone.getLocalTimezone();

if (tz.timeZoneDatabase.locations.containsKey(tzName)) {

tz.setLocalLocation(tz.getLocation(tzName));

} else {

tz.setLocalLocation(tz.getLocation('UTC'));

}

} catch (e) {

tz.setLocalLocation(tz.getLocation('UTC'));

print('⚠️ Using UTC fallback for timezone: $e');

}


// 4) Fetch event.

final snap = await FirebaseFirestore.instance

.collection('events')

.doc(eventId)

.get();

if (!snap.exists || snap.data() == null) {

print('⚠️ Event not found or empty: $eventId');

return;

}

final data = snap.data()!;

final eventName = (data['event_name'] as String?)?.trim() ?? 'Event';

final ts = data['event_dateTime'] as Timestamp?;

if (ts == null) {

print('⚠️ event_dateTime is null for $eventId');

return;

}


// 5) Times.

final now = tz.TZDateTime.now(tz.local);

final eventTime = tz.TZDateTime.from(ts.toDate(), tz.local);

final oneHourBefore = eventTime.subtract(const Duration(hours: 1));


// 6) Stable IDs

// Android: 32-bit safe ids; iOS: keep original approach.

int _stableId(String seed) {

int h = 5381;

for (final code in seed.codeUnits) {

h = ((h << 5) + h) ^ code; // h*33 ^ code

}

return h & 0x7fffffff; // 0..2^31-1

}


late final int id1;

late final int id2;


if (Platform.isAndroid) {

// 32-bit safe (Android)

id1 = _stableId('$eventId|pre|${oneHourBefore.millisecondsSinceEpoch}');

id2 = _stableId('$eventId|at|${eventTime.millisecondsSinceEpoch}');

} else {

// Original logic for iOS (and others)

final base = eventId.codeUnits.fold<int>(0, (a, b) => a + b);

id1 = base ^ oneHourBefore.millisecondsSinceEpoch;

id2 = base ^ eventTime.millisecondsSinceEpoch;

}


// 7) Notification details.

const androidDetails = AndroidNotificationDetails(

'event_channel',

'Event Reminders',

channelDescription: 'Notifications for scheduled events',

importance: Importance.max,

priority: Priority.high,

playSound: true,

enableVibration: true,

);

const iosDetails = DarwinNotificationDetails(

presentAlert: true,

presentBadge: true,

presentSound: true,

);

const details =

NotificationDetails(android: androidDetails, iOS: iosDetails);


// 8) Schedule (no matchDateTimeComponents for one-offs).

print(

'🕒 now=$now event=$eventTime oneHourBefore=$oneHourBefore tz=${tz.local}');


if (oneHourBefore.isAfter(now)) {

await plugin.zonedSchedule(

id1,

'Upcoming event in 1 hour',

eventName,

oneHourBefore,

details,

androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,

androidAllowWhileIdle: true,

uiLocalNotificationDateInterpretation:

UILocalNotificationDateInterpretation.absoluteTime,

);

print('⏰ Scheduled -1h @ $oneHourBefore (local) [id=$id1]');

} else {

print('⏭️ Skipped -1h (past)');

}


if (eventTime.isAfter(now)) {

await plugin.zonedSchedule(

id2,

eventName,

'',

eventTime,

details,

androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,

androidAllowWhileIdle: true,

uiLocalNotificationDateInterpretation:

UILocalNotificationDateInterpretation.absoluteTime,

);

print('✅ Scheduled event @ $eventTime (local) [id=$id2]');

} else {

print('⏭️ Skipped event-time (past)');

}

} catch (e) {

print('🔥 scheduleNotificationsForEvent error: $e');

}

}

in the device logs when i run on an android emulator, the logs show the the notification is scheduled, but when the time comes, nothing fires.

What have you tried so far?

Extensively used ChatGpt, searched through the flutterflow documentation and other community posts, looked through YouTube. Nothing I do is working for this.

Did you check FlutterFlow's Documentation for this topic?
Yes
1