我正在使用 flutter 本地通知在我的应用程序中显示日程通知。但不幸的是,当应用程序处于终止状态时,它无法工作。
这是我的代码:
class Notifications {
static final FlutterLocalNotificationsPlugin _notifications =
FlutterLocalNotificationsPlugin();
static Future<NotificationDetails> _notificationDetails() async {
return const NotificationDetails(
android: AndroidNotificationDetails(
'weekly notification channel id',
'weekly notification channel name',
channelDescription: 'weekly notification description',
playSound: true,
sound: RawResourceAndroidNotificationSound('azan1'),
importance: Importance.high,
),
iOS: IOSNotificationDetails(sound: 'azan1.mp3', presentSound: true));
}
static void init() async {
tz.initializeTimeZones();
const AndroidInitializationSettings android =
AndroidInitializationSettings('@mipmap/ic_launcher');
const IOSInitializationSettings iOS = IOSInitializationSettings();
InitializationSettings settings =
const InitializationSettings(android: android, iOS: iOS);
await _notifications.initialize(settings);
final String locationName = await FlutterNativeTimezone.getLocalTimezone();
tz.setLocalLocation(tz.getLocation(locationName));
}
static void showScheduledNotification(
int id, {
required DateTime scheduledDate,
String? title,
String? body,
String? payload,
}) async {
await _notifications.zonedSchedule(
id,
'Azan Time',
'$body Prayer Time',
_scheduleDaily(
Time(scheduledDate.hour, scheduledDate.minute, scheduledDate.second)),
await _notificationDetails(),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time,
payload: payload,
);
}
static tz.TZDateTime _scheduleDaily(Time time) {
tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime schdeuledDate = tz.TZDateTime(tz.local, now.year, now.month,
now.day, time.hour, time.minute, time.second);
return schdeuledDate.isBefore(now)
? schdeuledDate.add(const Duration(days:1))
: schdeuledDate;
}
static Future<void> cancelNotification(int id) async {
await _notifications.cancel(id);
}
static Future<void> cancelAllNotifications() async {
await _notifications.cancelAll();
}
}
我还在 Android.xml 文件中添加了所有属性。 但它仍然不起作用,如果有人知道这个问题的解决方案,请回答这个问题。
本地通知可能有点棘手。查看
flutter_local_notifications
自述文件:
一些 Android OEM 拥有自己定制的 Android 操作系统,可以阻止应用程序在后台运行。因此,当应用程序在某些设备(例如小米、华为)上处于后台时,预定通知可能不起作用。如果您遇到这样的问题,那么这就是原因。由于这是操作系统施加的限制,因此插件无法解决此问题。某些设备可能具有允许用户控制哪些应用程序在后台运行的设置。这些步骤可能会有所不同,但考虑到这是手机本身的设置,仍然取决于应用程序的用户来执行。
据报道,三星的 Android 实施规定最多可通过 Alarm Manager API 安排 500 个警报,超过限制时可能会发生异常。
来源: https://pub.dev/packages/flutter_local_notifications#scheduled-android-notifications
根据我的理解(可能不正确),在后台工作和终止是两个完全不同的事情。
如果应用程序被终止,即被迫退出并完全死亡,则无法显示本地通知,应使用 firebase 推送通知。
有关 AppLifecycleState 的更多信息。
如果您能提供您的主要功能,那将会很有帮助。我将为您提供一个有关如何创建任何计划通知的一般示例。
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:rxdart/rxdart.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class NotificationApi {
static final _notification = FlutterLocalNotificationsPlugin();
static final onNotifications = BehaviorSubject<String?>();
static Future _notificationDetails() async {
return const NotificationDetails(
android: AndroidNotificationDetails(
'channel id',
'channel name',
channelDescription: 'Update users on new deal',
importance: Importance.max,
enableLights: true,
),
iOS: IOSNotificationDetails(),
);
}
static Future init({bool initScheduled = true}) async {
const android = AndroidInitializationSettings('@drawable/ic_notcion');
const iOS = IOSInitializationSettings();
const settings = InitializationSettings(android: android, iOS: iOS);
/// when app is closed
final details = await _notification.getNotificationAppLaunchDetails();
if (details != null && details.didNotificationLaunchApp) {
onNotifications.add(details.payload);
}
await _notification.initialize(
settings,
onSelectNotification: (payload) async {
onNotifications.add(payload);
},
);
if(initScheduled){
tz.initializeTimeZones();
final locationName = await FlutterNativeTimezone.getLocalTimezone();
tz.setLocalLocation(tz.getLocation(locationName));
}
}
static tz.TZDateTime _scheduledDaily(Time time) {
final now = tz.TZDateTime.now(tz.local);
final scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day,
time.hour);
return scheduledDate.isBefore(now)
? scheduledDate.add(const Duration(days: 1))
: scheduledDate;
}
static tz.TZDateTime _scheduleWeekly(Time time, {required List<int> days}) {
tz.TZDateTime scheduledDate = _scheduledDaily(time);
while (!days.contains(scheduledDate.weekday)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}
return scheduledDate;
}
static Future showWeeklyScheduledNotification({
int id = 8,
String? title,
String? body,
String? payload,
required DateTime scheduledDate,
}) async =>
_notification.zonedSchedule(
id,
title,
body,
_scheduleWeekly(const Time(17), days: [
DateTime.tuesday,
DateTime.friday,
DateTime.saturday,
DateTime.sunday,
]),
// tz.TZDateTime.from(scheduledDate, tz.local),
await _notificationDetails(),
payload: payload,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.dayOfWeekAndTime,
);
static void cancelAll() => _notification.cancelAll();
}
在main函数中,初始化NotificationApi如下:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
//__________________________________Notification and Time Zone
tz.initializeTimeZones();
await NotificationApi.init();
await NotificationApi.init(initScheduled: true);
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// This widget is the root of your application.
///_____________________Init state initialising notifications
@override
void initState() {
loadAllNotifications;
super.initState();
}
loadAllNotifications() {
NotificationApi.showWeeklyScheduledNotification(
title: '🏆 New Deals Available 🏆',
body: '✨ Don\'t miss your opportunity to win BIG 💰💰',
scheduledDate: DateTime.now().add(const Duration(seconds: 12)));
NotificationApi.init(initScheduled: true);
listenNotifications();
}
//___________________________Listen to Notifications
void listenNotifications() =>
NotificationApi.onNotifications.stream.listen(onClickedNotification);
//__________________________On Notification Clicked
void onClickedNotification(String? payload) => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AppWrapper(updates: updates)));
//________________________________________Widget Build
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Alpha Deals',
home: MyHomePage()
);
}
在你的Application.java中,如果这部分不起作用,你可以转义它来运行应用程序。
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channelHigh = new NotificationChannel(
CHANNEL_HIGH,
"Notificación Importante",
NotificationManager.IMPORTANCE_HIGH
);
channelHigh.setDescription("Canal Alto");
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channelHigh);
}
}
检查清单文件,不要忘记添加
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="default"/>
了解更多请查看此链接
我认为可以在后台使用它之前再次初始化它,因为它使用单独的环境