flutter本地推送 flutter_local_notifications的使用记录

flutter_local_notifications

效果

安卓配置(AndroidManifest.xml)

<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

可参考下面

XML 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application
        android:label="whisp"
        android:name="${applicationName}"
        android:icon="@mipmap/launcher_icon">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:taskAffinity=""
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android.com/training/package-visibility and
         https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>

ios配置AppDelegate.swift(参考下面)

import flutter_local_notifications
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in

GeneratedPluginRegistrant.register(with: registry)

}

if #available(iOS 10.0, *) {

UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate

}

(参考下面)

Dart 复制代码
import UIKit
import Flutter
import flutter_local_notifications

@main
@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    // This is required to make any communication available in the action isolate.
    FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
        GeneratedPluginRegistrant.register(with: registry)
    }

    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

封装类

Dart 复制代码
import 'dart:async';
import 'dart:io';

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

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

class NotificationHelper {
  static NotificationHelper? _instance;
  static NotificationHelper getInstance() {
    _instance ??= NotificationHelper._initial();
    return _instance!;
  }

  factory NotificationHelper() => _instance ??= NotificationHelper._initial();

  //创建命名构造函数
  NotificationHelper._initial() {
    initialize();
  }

  // FlutterLocalNotificationsPlugin实例
  final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
  final StreamController<NotificationResponse> selectNotificationStream = StreamController<NotificationResponse>.broadcast();
  // 常量定义
  static const String _channelId = 'message_notifications';
  static const String _channelName = 'message notification';
  static const String _channelDescription = 'Notifications for receiving new messages';
  static const String _ticker = 'ticker';
  static const String _darwinNotificationCategoryPlain = 'plainCategory';
  static const String darwinNotificationCategoryText = 'textCategory';
  int id = 0;
  bool _notificationsEnabled = false;

  // 初始化通知插件
  Future<void> initialize() async {
    try {
      const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/launcher_icon');
      const DarwinInitializationSettings initializationSettingsIOS =
          DarwinInitializationSettings(requestSoundPermission: false, requestBadgePermission: false, requestAlertPermission: false);
      const InitializationSettings initializationSettings = InitializationSettings(
        android: initializationSettingsAndroid,
        iOS: initializationSettingsIOS,
      );
      await _notificationsPlugin.initialize(
        initializationSettings,
        onDidReceiveNotificationResponse: selectNotificationStream.add,
        onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
      );
    } catch (e) {
      print('初始化通知插件失败: $e');
    }
  }

  initPermission() {
    _isAndroidPermissionGranted();
    _requestPermissions();
    _configureSelectNotificationSubject();
  }

  closeSubject() {
    selectNotificationStream.close();
  }

  Future<void> _isAndroidPermissionGranted() async {
    if (Platform.isAndroid) {
      final bool granted =
          await _notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.areNotificationsEnabled() ??
              false;
      _notificationsEnabled = granted;
    }
  }

  Future<void> _requestPermissions() async {
    if (Platform.isIOS) {
      await _notificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
    } else if (Platform.isAndroid) {
      final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
          _notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();

      final bool? grantedNotificationPermission = await androidImplementation?.requestNotificationsPermission();
      _notificationsEnabled = grantedNotificationPermission ?? false;
    }
  }

  void _configureSelectNotificationSubject() {
    selectNotificationStream.stream.listen((NotificationResponse? response) async {
      // await Navigator.of(context).push(MaterialPageRoute<void>(
      //   builder: (BuildContext context) =>
      //       SecondPage(response?.payload, data: response?.data),
      // ));
      print("点击消息携带的数据$response");
    });
  }

  // 显示通知
  Future<void> showNotification({required String title, required String body, String payload = ""}) async {
    const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails(
      _channelId,
      _channelName,
      channelDescription: _channelDescription,
      importance: Importance.max,
      priority: Priority.high,
      ticker: _ticker,
    );
    const DarwinNotificationDetails iosNotificationDetails = DarwinNotificationDetails(categoryIdentifier: _darwinNotificationCategoryPlain);
    const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails, iOS: iosNotificationDetails);
    await _notificationsPlugin.show(
      id++,
      title,
      body,
      notificationDetails,
      payload: payload,
    );
  }

  /// 取消全部通知
  cancelAll() {
    _notificationsPlugin.cancelAll();
  }

  /// 取消对应ID的通知
  cancelId(int id) {
    _notificationsPlugin.cancel(id);
  }
}

使用

main方法中初始化

NotificationHelper.getInstance().initialize();

首页中进行权限和方法回调绑定和卸载

首页的instate

NotificationHelper.getInstance().initPermission();
首页的dispose

NotificationHelper.getInstance().closeSubject();

调用提示 接收消息直接调用

NotificationHelper.getInstance().showNotification(title: "科学研究", body: "研究开始了", payload: "payload");

这里可以监控点击推送后动作,如跳转页面 response?.data 是携带的数据

Dart 复制代码
 void _configureSelectNotificationSubject() {
    selectNotificationStream.stream.listen((NotificationResponse? response) async {
      // await Navigator.of(context).push(MaterialPageRoute<void>(
      //   builder: (BuildContext context) =>
      //       SecondPage(response?.payload, data: response?.data),
      // ));
      print("点击消息携带的数据$response");
    });
  }
相关推荐
恋猫de小郭17 小时前
Android 17 + OkHttp 5.5.0 ,全新 ECH 下你的 HTTPS 域名可以请求时被安全隐藏
android·前端·flutter
「、皓子~2 天前
海狸IM 2.1 正式发布
flutter·微服务·golang·electron·开源软件·im·海狸im
里欧跑得慢2 天前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
恋猫de小郭2 天前
AI 时代,一个优化 Flutter 的重复代码工具 Deslop
android·前端·flutter
ljt27249606613 天前
Flutter笔记--envied
前端·笔记·flutter
加农炮手Jinx3 天前
Flutter for OpenHarmony 实战:flutter_animate 声明式动画让 UI 灵动如原生
flutter·ui·华为·harmonyos·鸿蒙
里欧跑得慢3 天前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
里欧跑得慢3 天前
Flutter 三方库 function_tree — 鸿蒙应用开发中的动态数学公式解析与计算神器,实现鸿蒙深度适配下的复杂函数逻辑运行时求值实战(适配鸿蒙 HarmonyOS Next ohos)
android·前端·安全·flutter·华为·harmonyos