Flutter本地通知插件flutter_local_notifications的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter本地通知插件flutter_local_notifications的使用

flutter_local_notifications 是一个跨平台的Flutter插件,用于在应用中显示本地通知。它支持Android、iOS、macOS和Linux等平台,并提供了丰富的功能,如基本通知显示、定时通知、周期性通知等。本文将详细介绍如何配置和使用此插件。

目录

安装

首先,在pubspec.yaml文件中添加依赖:

dependencies:
  flutter_local_notifications: ^16.0.0

然后执行以下命令来安装插件:

flutter pub get

初始化

在使用flutter_local_notifications之前,需要进行初始化设置。下面是一个完整的初始化示例:

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化时区数据库
  await _configureLocalTimeZone();

  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  
  // 获取启动时是否由通知触发的信息
  final NotificationAppLaunchDetails? notificationAppLaunchDetails = !kIsWeb && Platform.isLinux
      ? null
      : await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
      
  String initialRoute = HomePage.routeName;
  if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
    selectedNotificationPayload = notificationAppLaunchDetails!.notificationResponse?.payload;
    initialRoute = SecondPage.routeName;
  }

  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('app_icon');

  final List<DarwinNotificationCategory> darwinNotificationCategories = [
    DarwinNotificationCategory(
      darwinNotificationCategoryText,
      actions: [
        DarwinNotificationAction.text(
          'text_1',
          'Action 1',
          buttonTitle: 'Send',
          placeholder: 'Placeholder',
        ),
      ],
    ),
    DarwinNotificationCategory(
      darwinNotificationCategoryPlain,
      actions: [
        DarwinNotificationAction.plain('id_1', 'Action 1'),
        DarwinNotificationAction.plain(
          'id_2',
          'Action 2 (destructive)',
          options: {DarwinNotificationActionOption.destructive},
        ),
        DarwinNotificationAction.plain(
          navigationActionId,
          'Action 3 (foreground)',
          options: {DarwinNotificationActionOption.foreground},
        ),
        DarwinNotificationAction.plain(
          'id_4',
          'Action 4 (auth required)',
          options: {DarwinNotificationActionOption.authenticationRequired},
        ),
      ],
      options: {DarwinNotificationCategoryOption.hiddenPreviewShowTitle},
    )
  ];

  final DarwinInitializationSettings initializationSettingsDarwin =
      DarwinInitializationSettings(
    requestAlertPermission: false,
    requestBadgePermission: false,
    requestSoundPermission: false,
    notificationCategories: darwinNotificationCategories,
  );

  final LinuxInitializationSettings initializationSettingsLinux =
      LinuxInitializationSettings(
    defaultActionName: 'Open notification',
    defaultIcon: AssetsLinuxIcon('icons/app_icon.png'),
  );

  final InitializationSettings initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    iOS: initializationSettingsDarwin,
    macOS: initializationSettingsDarwin,
    linux: initializationSettingsLinux,
  );

  await flutterLocalNotificationsPlugin.initialize(
    initializationSettings,
    onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) {
      switch (notificationResponse.notificationResponseType) {
        case NotificationResponseType.selectedNotification:
          selectNotificationStream.add(notificationResponse.payload);
          break;
        case NotificationResponseType.selectedNotificationAction:
          if (notificationResponse.actionId == navigationActionId) {
            selectNotificationStream.add(notificationResponse.payload);
          }
          break;
      }
    },
    onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
  );

  runApp(MyApp());
}

@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
  print('notification(${notificationResponse.id}) action tapped: '
      '${notificationResponse.actionId} with'
      ' payload: ${notificationResponse.payload}');
  if (notificationResponse.input?.isNotEmpty ?? false) {
    print('notification action tapped with input: ${notificationResponse.input}');
  }
}

显示基本通知

要显示一个简单的通知,可以使用show方法:

Future<void> _showNotification() async {
  const AndroidNotificationDetails androidPlatformChannelSpecifics =
      AndroidNotificationDetails(
    'your channel id',
    'your channel name',
    channelDescription: 'your channel description',
    importance: Importance.max,
    priority: Priority.high,
    ticker: 'ticker',
  );
  const NotificationDetails platformChannelSpecifics =
      NotificationDetails(android: androidPlatformChannelSpecifics);
  await flutterLocalNotificationsPlugin.show(
    0,
    'plain title',
    'plain body',
    platformChannelSpecifics,
    payload: 'item x',
  );
}

调度通知

从版本2.0开始,调度通知需要指定特定的时间区域。这可以通过zonedSchedule方法实现:

Future<void> _zonedScheduleNotification() async {
  tz.initializeTimeZones();
  final String timeZoneName = await FlutterTimezone.getLocalTimezone();
  tz.setLocalLocation(tz.getLocation(timeZoneName));

  await flutterLocalNotificationsPlugin.zonedSchedule(
    0,
    'scheduled title',
    'scheduled body',
    tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
    const NotificationDetails(
      android: AndroidNotificationDetails(
        'your channel id',
        'your channel name',
        channelDescription: 'your channel description',
      ),
    ),
    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
    uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
  );
}

周期性通知

如果你想每隔一段时间显示一次通知,可以使用periodicallyShow方法:

Future<void> _repeatNotification() async {
  const AndroidNotificationDetails androidNotificationDetails =
      AndroidNotificationDetails(
    'repeating channel id',
    'repeating channel name',
    channelDescription: 'repeating description',
  );
  const NotificationDetails notificationDetails =
      NotificationDetails(android: androidNotificationDetails);
  await flutterLocalNotificationsPlugin.periodicallyShow(
    0,
    'repeating title',
    'repeating body',
    RepeatInterval.everyMinute,
    notificationDetails,
    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
  );
}

获取待处理的通知请求

你可以通过pendingNotificationRequests方法获取所有未处理的通知请求:

Future<void> _checkPendingNotificationRequests() async {
  final List<PendingNotificationRequest> pendingNotificationRequests =
      await flutterLocalNotificationsPlugin.pendingNotificationRequests();
  print('${pendingNotificationRequests.length} pending notification requests');
}

取消通知

取消单个或所有通知分别使用cancelcancelAll方法:

Future<void> _cancelNotification() async {
  await flutterLocalNotificationsPlugin.cancel(0);
}

Future<void> _cancelAllNotifications() async {
  await flutterLocalNotificationsPlugin.cancelAll();
}

通知分组

对于Android平台,可以通过设置groupKey属性来分组通知:

Future<void> _showGroupedNotifications() async {
  const String groupKey = 'com.android.example.WORK_EMAIL';
  const String groupChannelId = 'grouped channel id';
  const String groupChannelName = 'grouped channel name';
  const String groupChannelDescription = 'grouped channel description';

  const AndroidNotificationDetails firstNotificationAndroidSpecifics =
      AndroidNotificationDetails(groupChannelId, groupChannelName,
          channelDescription: groupChannelDescription,
          importance: Importance.max,
          priority: Priority.high,
          groupKey: groupKey);

  const NotificationDetails firstNotificationPlatformSpecifics =
      NotificationDetails(android: firstNotificationAndroidSpecifics);

  await flutterLocalNotificationsPlugin.show(
      0, 'Alex Faarborg', 'You will not believe...', firstNotificationPlatformSpecifics);

  const AndroidNotificationDetails secondNotificationAndroidSpecifics =
      AndroidNotificationDetails(groupChannelId, groupChannelName,
          channelDescription: groupChannelDescription,
          importance: Importance.max,
          priority: Priority.high,
          groupKey: groupKey);

  const NotificationDetails secondNotificationPlatformSpecifics =
      NotificationDetails(android: secondNotificationAndroidSpecifics);

  await flutterLocalNotificationsPlugin.show(
      1, 'Jeff Chang', 'Please join us to celebrate the...', secondNotificationPlatformSpecifics);

  const List<String> lines = ['Alex Faarborg  Check this out', 'Jeff Chang    Launch Party'];
  const InboxStyleInformation inboxStyleInformation =
      InboxStyleInformation(lines, contentTitle: '2 messages', summaryText: 'janedoe@example.com');

  const AndroidNotificationDetails androidNotificationDetails =
      AndroidNotificationDetails(groupChannelId, groupChannelName,
          channelDescription: groupChannelDescription,
          styleInformation: inboxStyleInformation,
          groupKey: groupKey,
          setAsGroupSummary: true);

  const NotificationDetails notificationDetails =
      NotificationDetails(android: androidNotificationDetails);

  await flutterLocalNotificationsPlugin.show(2, 'Attention', 'Two messages', notificationDetails);
}

权限管理

在某些平台上(如iOS和macOS),你需要请求用户授权才能发送通知:

Future<void> _requestPermissions() async {
  if (Platform.isIOS || Platform.isMacOS) {
    await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
        ?.requestPermissions(
          alert: true,
          badge: true,
          sound: true,
        );
    await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<MacOSFlutterLocalNotificationsPlugin>()
        ?.requestPermissions(
          alert: true,
          badge: true,
          sound: true,
        );
  } else if (Platform.isAndroid) {
    final bool? grantedNotificationPermission =
        await flutterLocalNotificationsPlugin
            .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
            ?.requestNotificationsPermission();
    setState(() {
      _notificationsEnabled = grantedNotificationPermission ?? false;
    });
  }
}

通知动作

为通知添加自定义动作,可以在用户点击这些动作时触发相应的回调:

Future<void> _showNotificationWithActions() async {
  const AndroidNotificationDetails androidNotificationDetails =
      AndroidNotificationDetails(
    'your channel id',
    'your channel name',
    channelDescription: 'your channel description',
    importance: Importance.max,
    priority: Priority.high,
    ticker: 'ticker',
    actions: [
      AndroidNotificationAction(
        urlLaunchActionId,
        'Action 1',
        icon: DrawableResourceAndroidBitmap('food'),
        contextual: true,
      ),
      AndroidNotificationAction(
        'id_2',
        'Action 2',
        titleColor: Color.fromARGB(255, 255, 0, 0),
        icon: DrawableResourceAndroidBitmap('secondary_icon'),
      ),
      AndroidNotificationAction(
        navigationActionId,
        'Action 3',
        icon: DrawableResourceAndroidBitmap('secondary_icon'),
        showsUserInterface: true,
        cancelNotification: false,
      ),
    ],
  );

  const DarwinNotificationDetails iosNotificationDetails =
      DarwinNotificationDetails(categoryIdentifier: darwinNotificationCategoryPlain);

  const DarwinNotificationDetails macOSNotificationDetails =
      DarwinNotificationDetails(categoryIdentifier: darwinNotificationCategoryPlain);

  const LinuxNotificationDetails linuxNotificationDetails =
      LinuxNotificationDetails(actions: [
        LinuxNotificationAction(key: urlLaunchActionId, label: 'Action 1'),
        LinuxNotificationAction(key: navigationActionId, label: 'Action 2'),
      ]);

  const NotificationDetails notificationDetails = NotificationDetails(
    android: androidNotificationDetails,
    iOS: iosNotificationDetails,
    macOS: macOSNotificationDetails,
    linux: linuxNotificationDetails,
  );

  await flutterLocalNotificationsPlugin.show(
    0,
    'plain title',
    'plain body',
    notificationDetails,
    payload: 'item z',
  );
}

以上就是flutter_local_notifications插件的基本用法和一些高级功能的演示。希望这篇文章能帮助你更好地理解和使用这个强大的Flutter插件!如果你有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter本地通知插件flutter_local_notifications的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地通知插件flutter_local_notifications的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flutter_local_notifications插件来实现本地通知的示例代码。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加flutter_local_notifications依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_local_notifications: ^9.0.0  # 请使用最新版本

然后运行flutter pub get来安装依赖。

2. 配置Android和iOS

Android

android/app/src/main/AndroidManifest.xml中添加以下权限(如果还没有):

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

iOS

ios/Runner/Info.plist中添加必要的权限:

<key>NSLocalNetworkUsageDescription</key>
<string>This app needs access to local network to send notifications</string>
<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
</array>

3. 初始化插件

在你的main.dart文件中初始化flutter_local_notifications插件:

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Local Notifications Example'),
        ),
        body: HomePage(),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  var initializationSettingsAndroid;
  var initializationSettingsIOS;
  var initializationSettings;

  @override
  void initState() {
    super.initState();
    var androidInitializationSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
    initializationSettingsAndroid = androidInitializationSettings.build();

    var iOSInitializationSettings = IOSInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestSoundPermission: true,
    );
    initializationSettingsIOS = iOSInitializationSettings.build();

    initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS);

    flutterLocalNotificationsPlugin.initialize(initializationSettings, onInitializationComplete: (status) {
      print('Flutter Local Notifications initialized: $status');
    });
  }

  void showNotification() {
    var channel = NotificationChannel(
      'high_importance_channel',
      'High Importance Notifications',
      'This channel is used for important notifications.',
      importance: Importance.High,
    );

    flutterLocalNotificationsPlugin.channelManagement().createChannel(channel);

    var notificationDetails = NotificationDetails(
      android: AndroidNotificationDetails(
        'high_importance_channel',
        'High importance channel',
        'Channel description',
        importance: Importance.High,
        priority: Priority.High,
      ),
      iOS: IOSNotificationDetails(
        presentAlert: true,
        presentSound: true,
        presentBadge: true,
      ),
    );

    flutterLocalNotificationsPlugin.show(
      hashCode.toString(),
      'Hello, Flutter!',
      'This is a local notification!',
      notificationDetails,
      payload: 'item x',
    );
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: showNotification,
        child: Text('Show Notification'),
      ),
    );
  }
}

4. 处理通知点击事件

要在用户点击通知时执行某些操作,你需要添加一个通知监听器。例如,在_HomePageStateinitState方法中:

@override
void initState() {
  super.initState();
  // 初始化代码...

  // 添加通知点击监听器
  FlutterLocalNotificationsPlugin().NOTIFICATION_CLICK_EVENT.listen((String payload) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Payload'),
          content: Text('$payload'),
          actions: <Widget>[
            FlatButton(
              child: Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  });
}

这段代码将监听通知点击事件,并在用户点击通知时显示一个对话框,显示通知的负载(payload)。

总结

这个示例展示了如何在Flutter中使用flutter_local_notifications插件来发送本地通知,并处理通知点击事件。你可以根据实际需求修改和扩展这些代码。

回到顶部