fix: ensure notifications use correct channels and dates
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<uses-permission android:name="android.permission.READ_SMS" />
|
<uses-permission android:name="android.permission.READ_SMS" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<!-- 재부팅 후 예약 복구를 위해 필요 -->
|
<!-- 재부팅 후 예약 복구를 위해 필요 -->
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<!-- 정확 알람(결제/캘린더 등 정확 시각 필요시) 사용 -->
|
<!-- 정확 알람(결제/캘린더 등 정확 시각 필요시) 사용 -->
|
||||||
@@ -40,6 +41,20 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||||
android:value="ca-app-pub-6691216385521068~6638409932" />
|
android:value="ca-app-pub-6691216385521068~6638409932" />
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver"
|
||||||
|
android:exported="false" />
|
||||||
|
<receiver
|
||||||
|
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import '../services/subscription_url_matcher.dart';
|
|||||||
import '../widgets/common/snackbar/app_snackbar.dart';
|
import '../widgets/common/snackbar/app_snackbar.dart';
|
||||||
import '../l10n/app_localizations.dart';
|
import '../l10n/app_localizations.dart';
|
||||||
import '../utils/billing_date_util.dart';
|
import '../utils/billing_date_util.dart';
|
||||||
import '../utils/business_day_util.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart' as permission;
|
import 'package:permission_handler/permission_handler.dart' as permission;
|
||||||
|
|
||||||
/// AddSubscriptionScreen의 비즈니스 로직을 관리하는 Controller
|
/// AddSubscriptionScreen의 비즈니스 로직을 관리하는 Controller
|
||||||
@@ -495,7 +494,6 @@ class AddSubscriptionController {
|
|||||||
);
|
);
|
||||||
var adjustedNext =
|
var adjustedNext =
|
||||||
BillingDateUtil.ensureFutureDate(originalDateOnly, billingCycle);
|
BillingDateUtil.ensureFutureDate(originalDateOnly, billingCycle);
|
||||||
adjustedNext = BusinessDayUtil.nextBusinessDay(adjustedNext);
|
|
||||||
|
|
||||||
await Provider.of<SubscriptionProvider>(context, listen: false)
|
await Provider.of<SubscriptionProvider>(context, listen: false)
|
||||||
.addSubscription(
|
.addSubscription(
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import '../widgets/dialogs/delete_confirmation_dialog.dart';
|
|||||||
import '../widgets/common/snackbar/app_snackbar.dart';
|
import '../widgets/common/snackbar/app_snackbar.dart';
|
||||||
import '../l10n/app_localizations.dart';
|
import '../l10n/app_localizations.dart';
|
||||||
import '../utils/billing_date_util.dart';
|
import '../utils/billing_date_util.dart';
|
||||||
import '../utils/business_day_util.dart';
|
|
||||||
|
|
||||||
/// DetailScreen의 비즈니스 로직을 관리하는 Controller
|
/// DetailScreen의 비즈니스 로직을 관리하는 Controller
|
||||||
class DetailScreenController extends ChangeNotifier {
|
class DetailScreenController extends ChangeNotifier {
|
||||||
@@ -414,8 +413,6 @@ class DetailScreenController extends ChangeNotifier {
|
|||||||
_nextBillingDate.year, _nextBillingDate.month, _nextBillingDate.day);
|
_nextBillingDate.year, _nextBillingDate.month, _nextBillingDate.day);
|
||||||
var adjustedNext =
|
var adjustedNext =
|
||||||
BillingDateUtil.ensureFutureDate(originalDateOnly, _billingCycle);
|
BillingDateUtil.ensureFutureDate(originalDateOnly, _billingCycle);
|
||||||
// 주말/고정 공휴일 보정 → 다음 영업일로 이월
|
|
||||||
adjustedNext = BusinessDayUtil.nextBusinessDay(adjustedNext);
|
|
||||||
subscription.nextBillingDate = adjustedNext;
|
subscription.nextBillingDate = adjustedNext;
|
||||||
subscription.categoryId = _selectedCategoryId;
|
subscription.categoryId = _selectedCategoryId;
|
||||||
subscription.currency = _currency;
|
subscription.currency = _currency;
|
||||||
|
|||||||
@@ -20,6 +20,24 @@ class NotificationService {
|
|||||||
static const _reminderHourKey = 'reminder_hour';
|
static const _reminderHourKey = 'reminder_hour';
|
||||||
static const _reminderMinuteKey = 'reminder_minute';
|
static const _reminderMinuteKey = 'reminder_minute';
|
||||||
static const _dailyReminderKey = 'daily_reminder_enabled';
|
static const _dailyReminderKey = 'daily_reminder_enabled';
|
||||||
|
static const int _maxDailyReminderSlots = 7;
|
||||||
|
static const String _paymentPayloadPrefix = 'payment:';
|
||||||
|
static const String _paymentChannelId = 'subscription_channel_v2';
|
||||||
|
static const String _expirationChannelId = 'expiration_channel_v2';
|
||||||
|
|
||||||
|
static String get paymentChannelId => _paymentChannelId;
|
||||||
|
static String get expirationChannelId => _expirationChannelId;
|
||||||
|
|
||||||
|
static String _paymentPayload(String subscriptionId) =>
|
||||||
|
'$_paymentPayloadPrefix$subscriptionId';
|
||||||
|
|
||||||
|
static bool _matchesPaymentPayload(String? payload) =>
|
||||||
|
payload != null && payload.startsWith(_paymentPayloadPrefix);
|
||||||
|
|
||||||
|
static String? _subscriptionIdFromPaymentPayload(String? payload) =>
|
||||||
|
_matchesPaymentPayload(payload)
|
||||||
|
? payload!.substring(_paymentPayloadPrefix.length)
|
||||||
|
: null;
|
||||||
|
|
||||||
// 초기화 상태를 추적하기 위한 플래그
|
// 초기화 상태를 추적하기 위한 플래그
|
||||||
static bool _initialized = false;
|
static bool _initialized = false;
|
||||||
@@ -69,14 +87,14 @@ class NotificationService {
|
|||||||
try {
|
try {
|
||||||
await androidImpl
|
await androidImpl
|
||||||
.createNotificationChannel(const AndroidNotificationChannel(
|
.createNotificationChannel(const AndroidNotificationChannel(
|
||||||
'subscription_channel',
|
_paymentChannelId,
|
||||||
'Subscription Notifications',
|
'Subscription Notifications',
|
||||||
description: 'Channel for subscription reminders',
|
description: 'Channel for subscription reminders',
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
));
|
));
|
||||||
await androidImpl
|
await androidImpl
|
||||||
.createNotificationChannel(const AndroidNotificationChannel(
|
.createNotificationChannel(const AndroidNotificationChannel(
|
||||||
'expiration_channel',
|
_expirationChannelId,
|
||||||
'Expiration Notifications',
|
'Expiration Notifications',
|
||||||
description: 'Channel for subscription expiration reminders',
|
description: 'Channel for subscription expiration reminders',
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
@@ -152,20 +170,32 @@ class NotificationService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 기존 알림 모두 취소
|
final pendingRequests =
|
||||||
await cancelAllNotifications();
|
await _notifications.pendingNotificationRequests();
|
||||||
|
|
||||||
// 알림 설정 가져오기
|
|
||||||
final isPaymentEnabled = await isPaymentNotificationEnabled();
|
final isPaymentEnabled = await isPaymentNotificationEnabled();
|
||||||
if (!isPaymentEnabled) return;
|
if (!isPaymentEnabled) {
|
||||||
|
await _cancelOrphanedPaymentReminderNotifications(
|
||||||
|
const <String>{},
|
||||||
|
pendingRequests,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final reminderDays = await getReminderDays();
|
final reminderDays = await getReminderDays();
|
||||||
final reminderHour = await getReminderHour();
|
final reminderHour = await getReminderHour();
|
||||||
final reminderMinute = await getReminderMinute();
|
final reminderMinute = await getReminderMinute();
|
||||||
final isDailyReminder = await isDailyReminderEnabled();
|
final isDailyReminder = await isDailyReminderEnabled();
|
||||||
|
|
||||||
// 각 구독에 대해 알림 재설정
|
final activeSubscriptionIds =
|
||||||
|
subscriptions.map((subscription) => subscription.id).toSet();
|
||||||
|
|
||||||
for (final subscription in subscriptions) {
|
for (final subscription in subscriptions) {
|
||||||
|
await _cancelPaymentReminderNotificationsForSubscription(
|
||||||
|
subscription,
|
||||||
|
pendingRequests,
|
||||||
|
);
|
||||||
|
|
||||||
await schedulePaymentReminder(
|
await schedulePaymentReminder(
|
||||||
subscription: subscription,
|
subscription: subscription,
|
||||||
reminderDays: reminderDays,
|
reminderDays: reminderDays,
|
||||||
@@ -174,11 +204,78 @@ class NotificationService {
|
|||||||
isDailyReminder: isDailyReminder,
|
isDailyReminder: isDailyReminder,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _cancelOrphanedPaymentReminderNotifications(
|
||||||
|
activeSubscriptionIds,
|
||||||
|
pendingRequests,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('알림 일정 재설정 중 오류 발생: $e');
|
debugPrint('알림 일정 재설정 중 오류 발생: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> _cancelPaymentReminderNotificationsForSubscription(
|
||||||
|
SubscriptionModel subscription,
|
||||||
|
List<PendingNotificationRequest> pendingRequests,
|
||||||
|
) async {
|
||||||
|
final baseId = subscription.id.hashCode;
|
||||||
|
final payload = _paymentPayload(subscription.id);
|
||||||
|
|
||||||
|
final idsToCancel = <int>{};
|
||||||
|
|
||||||
|
for (final request in pendingRequests) {
|
||||||
|
final matchesPayload = request.payload == payload;
|
||||||
|
final matchesIdPattern = request.id == baseId ||
|
||||||
|
(request.id > baseId &&
|
||||||
|
request.id <= baseId + _maxDailyReminderSlots);
|
||||||
|
|
||||||
|
if (matchesPayload || matchesIdPattern) {
|
||||||
|
idsToCancel.add(request.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final id in idsToCancel) {
|
||||||
|
try {
|
||||||
|
await _notifications.cancel(id);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('결제 알림 취소 중 오류 발생: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idsToCancel.isNotEmpty) {
|
||||||
|
pendingRequests
|
||||||
|
.removeWhere((request) => idsToCancel.contains(request.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _cancelOrphanedPaymentReminderNotifications(
|
||||||
|
Set<String> activeSubscriptionIds,
|
||||||
|
List<PendingNotificationRequest> pendingRequests,
|
||||||
|
) async {
|
||||||
|
final idsToCancel = <int>{};
|
||||||
|
|
||||||
|
for (final request in pendingRequests) {
|
||||||
|
final subscriptionId = _subscriptionIdFromPaymentPayload(request.payload);
|
||||||
|
if (subscriptionId != null &&
|
||||||
|
!activeSubscriptionIds.contains(subscriptionId)) {
|
||||||
|
idsToCancel.add(request.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final id in idsToCancel) {
|
||||||
|
try {
|
||||||
|
await _notifications.cancel(id);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('고아 결제 알림 취소 중 오류 발생: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idsToCancel.isNotEmpty) {
|
||||||
|
pendingRequests
|
||||||
|
.removeWhere((request) => idsToCancel.contains(request.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future<bool> requestPermission() async {
|
static Future<bool> requestPermission() async {
|
||||||
// 웹 플랫폼인 경우 false 반환
|
// 웹 플랫폼인 경우 false 반환
|
||||||
if (_isWeb) return false;
|
if (_isWeb) return false;
|
||||||
@@ -276,12 +373,42 @@ class NotificationService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<AndroidScheduleMode> _resolveAndroidScheduleMode() async {
|
||||||
|
if (_isWeb) {
|
||||||
|
return AndroidScheduleMode.exactAllowWhileIdle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
try {
|
||||||
|
final canExact = await canScheduleExactAlarms();
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[NotificationService] canScheduleExactAlarms result: $canExact');
|
||||||
|
}
|
||||||
|
if (!canExact) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[NotificationService] exact alarm unavailable → use inexact mode');
|
||||||
|
}
|
||||||
|
return AndroidScheduleMode.inexactAllowWhileIdle;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('정확 알람 권한 확인 중 오류 발생: $e');
|
||||||
|
return AndroidScheduleMode.inexactAllowWhileIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AndroidScheduleMode.exactAllowWhileIdle;
|
||||||
|
}
|
||||||
|
|
||||||
// 알림 스케줄 설정
|
// 알림 스케줄 설정
|
||||||
static Future<void> scheduleNotification({
|
static Future<void> scheduleNotification({
|
||||||
required int id,
|
required int id,
|
||||||
required String title,
|
required String title,
|
||||||
required String body,
|
required String body,
|
||||||
required DateTime scheduledDate,
|
required DateTime scheduledDate,
|
||||||
|
String? payload,
|
||||||
|
String? channelId,
|
||||||
}) async {
|
}) async {
|
||||||
// 웹 플랫폼이거나 초기화되지 않은 경우 건너뛰기
|
// 웹 플랫폼이거나 초기화되지 않은 경우 건너뛰기
|
||||||
if (_isWeb || !_initialized) {
|
if (_isWeb || !_initialized) {
|
||||||
@@ -291,16 +418,26 @@ class NotificationService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final ctx = navigatorKey.currentContext;
|
final ctx = navigatorKey.currentContext;
|
||||||
final channelName = ctx != null
|
String channelName;
|
||||||
|
if (channelId == _expirationChannelId) {
|
||||||
|
channelName = ctx != null
|
||||||
|
? AppLocalizations.of(ctx).expirationReminder
|
||||||
|
: 'Expiration Notifications';
|
||||||
|
} else {
|
||||||
|
channelName = ctx != null
|
||||||
? AppLocalizations.of(ctx).notifications
|
? AppLocalizations.of(ctx).notifications
|
||||||
: 'Subscription Notifications';
|
: 'Subscription Notifications';
|
||||||
|
}
|
||||||
|
|
||||||
|
final effectiveChannelId = channelId ?? _paymentChannelId;
|
||||||
|
|
||||||
final androidDetails = AndroidNotificationDetails(
|
final androidDetails = AndroidNotificationDetails(
|
||||||
'subscription_channel',
|
effectiveChannelId,
|
||||||
channelName,
|
channelName,
|
||||||
channelDescription: channelName,
|
channelDescription: channelName,
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
priority: Priority.high,
|
priority: Priority.high,
|
||||||
|
autoCancel: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
const iosDetails = DarwinNotificationDetails(
|
const iosDetails = DarwinNotificationDetails(
|
||||||
@@ -334,15 +471,19 @@ class NotificationService {
|
|||||||
target = nowTz.add(const Duration(minutes: 1));
|
target = nowTz.add(const Duration(minutes: 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final scheduleMode = await _resolveAndroidScheduleMode();
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[NotificationService] scheduleNotification scheduleMode=$scheduleMode');
|
||||||
|
}
|
||||||
await _notifications.zonedSchedule(
|
await _notifications.zonedSchedule(
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
target,
|
target,
|
||||||
NotificationDetails(android: androidDetails, iOS: iosDetails),
|
NotificationDetails(android: androidDetails, iOS: iosDetails),
|
||||||
uiLocalNotificationDateInterpretation:
|
androidScheduleMode: scheduleMode,
|
||||||
UILocalNotificationDateInterpretation.absoluteTime,
|
payload: payload,
|
||||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('알림 예약 중 오류 발생: $e');
|
debugPrint('알림 예약 중 오류 발생: $e');
|
||||||
@@ -388,11 +529,12 @@ class NotificationService {
|
|||||||
|
|
||||||
final notificationDetails = NotificationDetails(
|
final notificationDetails = NotificationDetails(
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
'subscription_channel',
|
_paymentChannelId,
|
||||||
title,
|
title,
|
||||||
channelDescription: title,
|
channelDescription: title,
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
priority: Priority.high,
|
priority: Priority.high,
|
||||||
|
autoCancel: false,
|
||||||
),
|
),
|
||||||
iOS: const DarwinNotificationDetails(
|
iOS: const DarwinNotificationDetails(
|
||||||
presentAlert: true,
|
presentAlert: true,
|
||||||
@@ -435,15 +577,19 @@ class NotificationService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final scheduleMode = await _resolveAndroidScheduleMode();
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[NotificationService] scheduleSubscriptionNotification scheduleMode=$scheduleMode');
|
||||||
|
}
|
||||||
|
|
||||||
await _notifications.zonedSchedule(
|
await _notifications.zonedSchedule(
|
||||||
notificationId,
|
notificationId,
|
||||||
title,
|
title,
|
||||||
_buildExpirationBody(subscription),
|
_buildExpirationBody(subscription),
|
||||||
fireAt,
|
fireAt,
|
||||||
notificationDetails,
|
notificationDetails,
|
||||||
uiLocalNotificationDateInterpretation:
|
androidScheduleMode: scheduleMode,
|
||||||
UILocalNotificationDateInterpretation.absoluteTime,
|
|
||||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('구독 알림 예약 중 오류 발생: $e');
|
debugPrint('구독 알림 예약 중 오류 발생: $e');
|
||||||
@@ -515,11 +661,12 @@ class NotificationService {
|
|||||||
tz.TZDateTime.from(reminderDate, location),
|
tz.TZDateTime.from(reminderDate, location),
|
||||||
const NotificationDetails(
|
const NotificationDetails(
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
'expiration_channel',
|
_expirationChannelId,
|
||||||
'Expiration Notifications',
|
'Expiration Notifications',
|
||||||
channelDescription: 'Channel for subscription expiration reminders',
|
channelDescription: 'Channel for subscription expiration reminders',
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
priority: Priority.high,
|
priority: Priority.high,
|
||||||
|
autoCancel: false,
|
||||||
),
|
),
|
||||||
iOS: DarwinNotificationDetails(
|
iOS: DarwinNotificationDetails(
|
||||||
presentAlert: true,
|
presentAlert: true,
|
||||||
@@ -527,9 +674,7 @@ class NotificationService {
|
|||||||
presentSound: true,
|
presentSound: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
uiLocalNotificationDateInterpretation:
|
androidScheduleMode: await _resolveAndroidScheduleMode(),
|
||||||
UILocalNotificationDateInterpretation.absoluteTime,
|
|
||||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('만료 알림 예약 중 오류 발생: $e');
|
debugPrint('만료 알림 예약 중 오류 발생: $e');
|
||||||
@@ -605,6 +750,12 @@ class NotificationService {
|
|||||||
// 이벤트 종료로 인한 가격 변동 확인
|
// 이벤트 종료로 인한 가격 변동 확인
|
||||||
final body = await _buildPaymentBody(subscription, daysText);
|
final body = await _buildPaymentBody(subscription, daysText);
|
||||||
|
|
||||||
|
final scheduleMode = await _resolveAndroidScheduleMode();
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[NotificationService] schedulePaymentReminder(base) scheduleMode=$scheduleMode');
|
||||||
|
}
|
||||||
|
|
||||||
await _notifications.zonedSchedule(
|
await _notifications.zonedSchedule(
|
||||||
subscription.id.hashCode,
|
subscription.id.hashCode,
|
||||||
title,
|
title,
|
||||||
@@ -612,11 +763,12 @@ class NotificationService {
|
|||||||
scheduledDate,
|
scheduledDate,
|
||||||
NotificationDetails(
|
NotificationDetails(
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
'subscription_channel',
|
_paymentChannelId,
|
||||||
title,
|
title,
|
||||||
channelDescription: title,
|
channelDescription: title,
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
priority: Priority.high,
|
priority: Priority.high,
|
||||||
|
autoCancel: false,
|
||||||
),
|
),
|
||||||
iOS: const DarwinNotificationDetails(
|
iOS: const DarwinNotificationDetails(
|
||||||
presentAlert: true,
|
presentAlert: true,
|
||||||
@@ -624,9 +776,8 @@ class NotificationService {
|
|||||||
presentSound: true,
|
presentSound: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
uiLocalNotificationDateInterpretation:
|
androidScheduleMode: scheduleMode,
|
||||||
UILocalNotificationDateInterpretation.absoluteTime,
|
payload: _paymentPayload(subscription.id),
|
||||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 매일 반복 알림 설정 (2일 이상 전에 알림 시작 & 반복 알림 활성화된 경우)
|
// 매일 반복 알림 설정 (2일 이상 전에 알림 시작 & 반복 알림 활성화된 경우)
|
||||||
@@ -670,11 +821,12 @@ class NotificationService {
|
|||||||
dailyDate,
|
dailyDate,
|
||||||
NotificationDetails(
|
NotificationDetails(
|
||||||
android: AndroidNotificationDetails(
|
android: AndroidNotificationDetails(
|
||||||
'subscription_channel',
|
_paymentChannelId,
|
||||||
title,
|
title,
|
||||||
channelDescription: title,
|
channelDescription: title,
|
||||||
importance: Importance.high,
|
importance: Importance.high,
|
||||||
priority: Priority.high,
|
priority: Priority.high,
|
||||||
|
autoCancel: false,
|
||||||
),
|
),
|
||||||
iOS: const DarwinNotificationDetails(
|
iOS: const DarwinNotificationDetails(
|
||||||
presentAlert: true,
|
presentAlert: true,
|
||||||
@@ -682,9 +834,8 @@ class NotificationService {
|
|||||||
presentSound: true,
|
presentSound: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
uiLocalNotificationDateInterpretation:
|
androidScheduleMode: scheduleMode,
|
||||||
UILocalNotificationDateInterpretation.absoluteTime,
|
payload: _paymentPayload(subscription.id),
|
||||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user