10

我正在尝试使用 flutter_local_notifications 包通过我的应用程序推送本地通知,并且在 FlutterNotificationsPlugin 上,“.schedule”已被弃用,我尝试使用“.zonedSchedule”,但它需要 TZDateTime 值。

var androidDetails = AndroidNotificationDetails(t.id, "Task Notifier",
        "Notifies if you have a task scheduled at a particular time");
    var generalNotificationDetails =
        NotificationDetails(android: androidDetails);
    var now = DateTime.now();
    var scheduledTime = DateTime(
            now.year, now.month, _dayTasks.date.day, t.time.hour, t.time.minute)
        .subtract(Duration(minutes: 5));
    //use zonedSchedule once you figure out how to convert datetime to TZdatetime
    // await notifications.zonedSchedule(
    //     0, "Task", t.description, scheduledTime, generalNotificationDetails,
    //     androidAllowWhileIdle: true,
    //     uiLocalNotificationDateInterpretation:
    //         UILocalNotificationDateInterpretation.wallClockTime);
    await notifications.schedule(0, "Ideal Day Task", t.description,
        scheduledTime, generalNotificationDetails);
4

3 回答 3

12

实际上, zonedSchedule() 需要 TZDateTime 值。我采用的方法是利用另一个包将原始 DateTime 值转换为 TZDateTime 值。下面是我使用的一个实现的摘录。看到第五行了吗?它涉及函数 TZDateTime.from()。它采用您最初可能使用的 DateTime 并将其转换为 TZDateTime。但是,它需要您当前的位置。这就是 TimeZone 类的用武之地。

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

    final timeZone = TimeZone();

    // The device's timezone.
    String timeZoneName = await timeZone.getTimeZoneName();

    // Find the 'current location'
    final location = await timeZone.getLocation(timeZoneName);

    final scheduledDate = tz.TZDateTime.from(dateTime, location);

    try {
      await _flutterLocalNotificationsPlugin.zonedSchedule(
        id,
        title,
        body,
        scheduledDate,
        platformChannelSpecifics,
        androidAllowWhileIdle: androidAllowWhileIdle,
        payload: payload,
        uiLocalNotificationDateInterpretation:
            uiLocalNotificationDateInterpretation,
      );
    } catch (ex) {
      id = -1;
    }
    return id;

我很快写了课,TimeZone。此类与另一个插件(flutter_native_timezone)一起使用,该插件查找设备的“当前位置”并提供该语言环境的标准名称:

import 'package:timezone/data/latest.dart';
import 'package:timezone/timezone.dart' as t;
import 'package:flutter_native_timezone/flutter_native_timezone.dart';

class TimeZone {
  factory TimeZone() => _this ?? TimeZone._();

  TimeZone._() {
    initializeTimeZones();
  }
  static TimeZone _this;

  Future<String> getTimeZoneName() async => FlutterNativeTimezone.getLocalTimezone();

  Future<t.Location> getLocation([String timeZoneName]) async {
    if(timeZoneName == null || timeZoneName.isEmpty){
      timeZoneName = await getTimeZoneName();
    }
    return t.getLocation(timeZoneName);
  }
}

使用该课程,您就可以开始了。

于 2020-10-16T18:28:46.323 回答
5

我刚刚试图解决同样的问题。要理解这一点,我们需要对平台渠道有一个基本的了解。

https://flutter.dev/docs/development/platform-integration/platform-channels?tab=android-channel-kotlin-tab

一旦我们理解了这一点,示例中的代码应该变得更容易理解: https ://github.com/MaikuB/flutter_local_notifications/blob/1fe78b9d129d674cd97cfba49734577b24c56925/flutter_local_notifications/example/android/app/src/main/java/com/dexterous/flutterlocalnotificationsexample /MainActivity.java

实践中的概念:

首先,我们需要像这样导入 tz。这可以在您的 main.dart 或帮助文件中完成。

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

要从普通日期时间创建一个TZDateTime,我们需要通过平台通道查询来使用设备时区。

Future<void> configureLocalTimeZone() async {
  tz.initializeTimeZones();
  final String timeZoneName = await platform.invokeMethod('getTimeZoneName');
  tz.setLocalLocation(tz.getLocation(timeZoneName));
}

getTimeZoneName平台具体实现中实现的地方。

请务必configureLocalTimeZone在下一步之前致电。

当我们想TZDateTime从一个DateTime对象创建时,我们通常可以这样做

var time = tz.TZDateTime.from(
    scheduledNotificationDateTime,
    tz.local,
);

完整的实现在这里的示例代码中展示: https ://github.com/MaikuB/flutter_local_notifications/blob/1fe78b9d129d674cd97cfba49734577b24c56925/flutter_local_notifications/example/lib/main.dart

在我非常简单的工作流程中,我没有考虑不同的边缘情况,所以 YMMV。希望这可以帮助!:)

于 2020-10-12T06:34:00.350 回答
2

我也遇到了同样的问题并试图找到解决方案,但有些解决方案要么已过时,要么正在使用不同的包。zonedSchedule() 函数需要 TZDateTime。所以在这里我们可以

Duration offsetTime= DateTime.now().timeZoneOffset;

这将为我们提供您的机器时间和 UTC 之间的差异,然后我们将从本地时间中减去它(默认为 UTC)

import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz; 
.
.
.
Future initializetimezone() async {
    tz.initializeTimeZones();
  }

Future<void> scheduleNotification()async{
await initializetimezone();
var androidChannel = AndroidNotificationDetails(
      'App',
      "Notifications",
      'Customize',
      importance: Importance.max,
      priority: Priority.high,
      playSound: true,
      enableLights: true,
      ongoing: false,
      visibility: NotificationVisibility.public,
    );
var iosChannel = IOSNotificationDetails();
var platfromChannel =
    NotificationDetails(android: androidChannel, iOS: iosChannel);
// year, month, etc can manually entered or you can use 
// DateTime.now() also for current time in local machine.
tz.TZDateTime zonedTime = tz.TZDateTime.local(year,month,day,hour,
                          minute).subtract(offsetTime);
 await flutterLocalNotificationsPlugin.zonedSchedule(
      0,
      'Some Notification',
      'Description',
      zonedTime ,
      platfromChannel,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      payload: 'Payload',
      androidAllowWhileIdle: true,
    );
}

我希望这有帮助。当 UTC 和本地机器之间的时差为正(+5:30:00.000000)时,这对我有用,我不确定负时差国家。

于 2021-05-01T08:39:17.903 回答