Flutter本地通知在后台不起作用?

13

我正在使用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 文件中添加了所有属性。但如果有人知道解决此问题的方法,请回答此问题。


1
我也有同样的问题。你解决了吗? - Flutter Supabase
不好意思,目前还没有解决。 - Zilaid
我遇到了同样的问题。我已经做了一切正确的事情。如果我将其安排在+1分钟后,它就会触发。但是,一旦设置超过那个时间,它就不会触发。 - Ammar Zahid
@AmmarZahid 最少需要15分钟。 - Dani
尝试在发布模式下检查应用程序。 - Kokila
4个回答

1

本地通知可能有点棘手。请查看flutter_local_notifications的README文件:

一些Android OEM具有自己定制的Android操作系统,可能会阻止应用在后台运行。因此,在某些设备上(例如小米、华为),当应用程序在后台运行时,预定通知可能无法正常工作。如果您遇到此类问题,则这将是原因。由于这是操作系统强加的限制,因此插件无法解决此问题。一些设备可能具有设置,允许用户控制哪些应用在后台运行。这些步骤可能会有所不同,但由于它是手机本身的设置,因此仍然由您的应用程序的用户来完成。

据报道,三星的Android实现已经对可以通过Alarm Manager API安排的最大500个警报进行了限制,并且在超过限制时可能会发生异常。

Source: https://pub.dev/packages/flutter_local_notifications#scheduled-android-notifications


1

1
如果您能提供主函数,那将会很有帮助。我将为您提供一个创建任何定时通知的一般示例。
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();
}

在主函数中,按照以下方式初始化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()
          
      );
}

每周排程多天对您是否适用?我有与您完全相同的代码,但它总是仅在指定列表中的第一天(在您的情况下为DateTime.tuesday)显示通知。其他日子(在您的情况下为DateTime.friday、DateTime.saturday和DateTime.sunday)将被忽略。 - Sebb
确保通知不会被取消,删除取消通知的代码 "static void cancelAll() => _notification.cancelAll();" 然后再试一次。 - dev.bojack
我已经尝试了,但仍然没有成功。_scheduleWeekly() 方法似乎无法在超过1天的情况下正常工作。你能用它吗? - Sebb
是的,我的工作完美无缺。请按照此视频中的说明操作:https://www.youtube.com/watch?v=bRy5dmts3X8&t=601s。如果您发现代码中的错误,我将非常感激您的回复。 - dev.bojack
视频中的函数仅返回一个DateTime对象,该对象基于您提供给函数的列表中的第一天进行自定义。但是,它仍然只是一个DateTime对象,因此它只会为这个特定的日期安排一个通知。 - Sebb

0
在你的 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"/>

更多信息请查看链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接