Как отправлять ежедневные запланированные уведомления. У меня есть мгновенные уведомления, которые работают, но планировAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как отправлять ежедневные запланированные уведомления. У меня есть мгновенные уведомления, которые работают, но планиров

Сообщение Anonymous »

У меня возникли проблемы с отправкой ежедневных уведомлений на Android. У меня такое чувство, будто я попробовал все. Я использую приведенный ниже код, а затем инициализирую init в main.dart.
Я не вижу ошибок, я вижу правильные журналы для расчетов планирования (как показано внизу), но уведомление так и не приходит. Я также вставил разрешения на использование, которые у меня есть, в androidmanifest. Будем очень признательны за любую помощь.
Функция InstantDebugNotification работает отлично, не работают только уведомления по расписанию
import 'dart:io';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_timezone/flutter_timezone.dart';

import 'package:shared_preferences/shared_preferences.dart';
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/data/latest_all.dart' as tz_data;
import 'package:timezone/timezone.dart' as tz;
import 'package:flutter/foundation.dart';

class NotificationHelper {
static final NotificationHelper _instance = NotificationHelper._internal();
factory NotificationHelper() => _instance;
NotificationHelper._internal();

final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();

// Storage Keys
static const String _prefHasAsked = 'has_asked_notification_permission';
static const String _prefIsEnabled = 'is_notifications_enabled';

// 1. INITIALIZATION
Future init() async {
// 1. Initialize Timezone Database
tz_data.initializeTimeZones();

// 2. GET DEVICE TIMEZONE (Robust Fix)
String timeZoneName;
try {
// Fetches the timezone info (might be Object or String depending on version)
final dynamic localTz = await FlutterTimezone.getLocalTimezone();

// Extract the string ID safely
if (localTz is String) {
timeZoneName = localTz;
} else {
// Tries standard property names for TimezoneInfo objects
// try .id first, then .name, then .identifier
try {
timeZoneName = localTz.id;
} catch (_) {
try {
timeZoneName = localTz.name;
} catch (__) {
// If your specific version used .identifier, this catches it
try {
timeZoneName = localTz.identifier;
} catch (___) {
timeZoneName = 'UTC';
}
}
}
}
} catch (e) {
if (kDebugMode) print("⚠️ Timezone Error: $e");
timeZoneName = 'UTC';
}

// 3. Set Local Location
try {
tz.setLocalLocation(tz.getLocation(timeZoneName));
} catch (e) {
tz.setLocalLocation(tz.getLocation('UTC'));
}

// 4. Android Settings (Matches your drawable file name)
const AndroidInitializationSettings androidSettings =
AndroidInitializationSettings('launcher_icon');

// 5. iOS Settings
final DarwinInitializationSettings iosSettings =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
);

final InitializationSettings settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
);

await _notificationsPlugin.initialize(
settings,
onDidReceiveNotificationResponse: (details) {
if (kDebugMode) log.i("Notification clicked: ${details.payload}");
},
);

// 6. RE-SCHEDULE (Safety Check)
// Check if notifications were previously enabled by the user
final prefs = await SharedPreferences.getInstance();
final bool isEnabled = prefs.getBool(_prefIsEnabled) ?? false;

if (isEnabled) {
// If they are enabled, refresh the schedule to ensure it's accurate
// (e.g. correct timezone, correct icon, etc.)
await _scheduleDailyReminders();
if (kDebugMode) print("🔄 Daily schedule refreshed on startup");
}

if (kDebugMode)
log.i("🔔 NotificationHelper Initialized. Timezone: $timeZoneName");
}

// 2. CHECK IF WE SHOULD ASK (The "Once Only" Logic)
// 3. ENABLE FLOW (User clicked "Yes")
Future shouldAskForPermission() async {
final prefs = await SharedPreferences.getInstance();
log.i(prefs.getBool(_prefHasAsked));
return !(prefs.getBool(_prefHasAsked) ?? false);
}

// 3. ENABLE FLOW
Future enableNotifications() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_prefHasAsked, true);

if (Platform.isAndroid) {
final androidPlugin = _notificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
>();
final granted = await androidPlugin?.requestNotificationsPermission();
if (granted != null && !granted) return false;
} else if (Platform.isIOS) {
final iosPlugin = _notificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin
>();
final granted = await iosPlugin?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
if (granted != true && granted != null) return false;
}

await prefs.setBool(_prefIsEnabled, true);
await _scheduleDailyReminders();
return true;
}

// 4. DISABLE FLOW (User clicked "No" or turned off in settings)
Future disableNotifications() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_prefHasAsked, true); // Still counts as "asked"
await prefs.setBool(_prefIsEnabled, false);
await _notificationsPlugin.cancelAll();
}

// 5. SCHEDULE LOGIC (The 00:05 Magic)
Future _scheduleDailyReminders() async {
// Schedule for 00:05 tomorrow/today
/* await _scheduleDaily(
id: 1,
title: "Daily Puzzle Ready! 🧩",
body: "Keep your streak alive. A new puzzle awaits.",
hour: 0,
minute: 5,
); */

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

// Schedule for 2 minutes from NOW
await _scheduleDaily(
id: 1,
title: "Test Alarm",
body: "If you see this, scheduling works!",
hour: now.hour,
minute: now.minute + 2,
);

// Add Weekly Logic here later (id: 2)
}

Future _scheduleDaily({
required int id,
required String title,
required String body,
required int hour,
required int minute,
}) async {
final now = tz.TZDateTime.now(tz.local);

// Calculate next 00:05 instance
var scheduledDate = tz.TZDateTime(
tz.local,
now.year,
now.month,
now.day,
hour,
minute,
);

// If 00:05 has passed today, schedule for tomorrow
if (scheduledDate.isBefore(now)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}

log.i("📅 Scheduling Notification for: $scheduledDate");

await _notificationsPlugin.zonedSchedule(
id,
title,
body,
scheduledDate,
NotificationDetails(
android: AndroidNotificationDetails(
'daily_reminders_v2', // Channel ID
'Daily Reminders', // Channel Name
channelDescription: 'Reminds you when the daily puzzle resets',
importance: Importance.max,
priority: Priority.high,
icon: 'launcher_icon',
),
iOS: DarwinNotificationDetails(),
),
androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,

// matchDateTimeComponents: DateTimeComponents.time,
);
}

Future instantDebugNotification() async {
await _notificationsPlugin.show(
999,
'Test Notification',
'If you see this, the instant notification',
const NotificationDetails(
android: AndroidNotificationDetails(
'test_channel',
'Test Channel',
importance: Importance.max,
priority: Priority.high,
icon: 'launcher_icon', //

Подробнее здесь: https://stackoverflow.com/questions/798 ... s-that-doe
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»