Flutter 开源鸿蒙跨平台应用消息推送与本地通知实战指南
摘要:本文详细讲解如何使用 flutter_local_notifications、firebase_messaging 与 flutter_background_service 三大库,为开源鸿蒙跨平台应用实现消息推送、本地通知展示、点击跳转逻辑,并重点解决鸿蒙系统适配、权限申请、后台消息接收及应用被杀状态下的消息处理等关键问题,附完整可运行代码与实战避坑指南。
一、前言:鸿蒙跨平台通知开发的痛点与选型
在开源鸿蒙应用开发中,消息推送与本地通知是提升用户活跃度的核心能力,但鸿蒙系统的通知管理机制、后台运行限制,以及三方库的适配问题,一直是开发者的痛点。
本次实战开发选用三款主流稳定三方开发库,兼顾功能完整性与鸿蒙系统适配性,flutter_local_notifications 主要用来实现本地通知的创建、展示、样式定制与点击事件处理,开发重点放在鸿蒙通知渠道配置与通知权限申请上。firebase_messaging 负责实现远程推送消息全场景接收,覆盖前台、后台以及应用离线状态,开发过程中需要做好鸿蒙后台消息接收适配以及推送令牌获取存储工作。flutter_background_service 用于搭建稳定后台运行任务,有效突破鸿蒙系统自带的后台进程限制,完成后台服务声明与进程保活相关开发工作。
二、环境准备与依赖配置

  1. 环境要求
    Flutter 3.19 及以上版本,完美兼容开源鸿蒙平台,开源鸿蒙 SDK 4.0 及以上版本,搭配鸿蒙实体开发设备或者模拟器即可完成调试运行,同时提前搭建好 Firebase 项目环境,用于实现远程 FCM 推送服务。
  2. 依赖添加
    在项目根目录 pubspec.yaml 文件中引入全部所需开发依赖,直接复制配置即可使用:
dependencies:
  flutter:
    sdk: flutter
  flutter_local_notifications: ^16.1.0+1
  firebase_messaging: ^14.7.10
  flutter_background_service: ^5.0.5
  shared_preferences: ^2.2.2
  1. 鸿蒙平台配置
    在 ohos/build-profile.json5 文件内完成应用基础配置、页面配置、服务声明以及系统权限申请,只有完成权限和服务配置,通知和后台推送功能才能正常生效:
{
  "app": {
    "bundleName": "com.example.notificationdemo",
    "vendor": "example",
    "signConfigs": [
      {
        "name": "debug",
        "signConfigType": "debug"
      }
    ]
  },
  "module": {
    "name": "entry",
    "deviceTypes": ["phone"],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      },
      {
        "name": "PushExtensionAbility",
        "srcEntry": "./ets/pushextension/PushExtensionAbility.ets",
        "type": "service",
        "exported": true
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.NOTIFICATION_CONTROL",
        "reason": "$string:permission_notification_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.RUN_BACKGROUND_PROCESSES",
        "reason": "$string:permission_background_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

三、核心功能实现

  1. 本地通知初始化与鸿蒙渠道适配
    鸿蒙系统有着严格的通知管理规则,所有展示在通知栏的通知消息,都必须提前绑定专属通知渠道,未配置通知渠道会直接导致通知无法弹出展示。下面封装完整本地通知工具类,包含初始化、通知点击监听、本地消息推送全部逻辑:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class NotificationService {
  final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();

  Future<void> initialize() async {
    const initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    const initializationSettingsOhos = OhosInitializationSettings();
    const initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      ohos: initializationSettingsOhos,
    );

    await _notificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse: _onNotificationTapped,
    );

    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'high_importance_channel',
      '重要通知',
      description: '用于接收高优先级推送通知',
      importance: Importance.max,
    );

    await _notificationsPlugin
        .resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin>()
        ?.createNotificationChannel(channel);
  }

  void _onNotificationTapped(NotificationResponse response) {
    final payload = response.payload;
    if (payload != null) {
      print('通知点击,携带数据: $payload');
    }
  }

  Future<void> showLocalNotification({
    required String title,
    required String body,
    String? payload,
  }) async {
    const notificationDetails = NotificationDetails(
      android: AndroidNotificationDetails(
        'high_importance_channel',
        '重要通知',
        importance: Importance.max,
        priority: Priority.high,
      ),
      ohos: OhosNotificationDetails(),
    );

    await _notificationsPlugin.show(
      0,
      title,
      body,
      notificationDetails,
      payload: payload,
    );
  }
}
  1. FCM 推送消息接收全场景实现
    firebase_messaging 是目前跨平台通用的远程推送解决方案,能够完美区分应用前台运行、后台挂起、彻底关闭离线三种运行状态,针对性接收推送消息,同时实现推送令牌本地持久化存储,方便后端绑定用户设备下发推送:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:shared_preferences/shared_preferences.dart';

class FCMService {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
  final NotificationService _notificationService = NotificationService();

  Future<void> initialize() async {
    NotificationSettings settings = await _firebaseMessaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );

    if (settings.authorizationStatus != AuthorizationStatus.authorized) {
      print('用户未授权通知权限');
      return;
    }

    String? token = await _firebaseMessaging.getToken();
    if (token != null) {
      print('FCM Token: $token');
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('fcm_token', token);
    }

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      print('收到前台消息: ${message.messageId}');
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;

      if (notification != null && android != null) {
        _notificationService.showLocalNotification(
          title: notification.title ?? '',
          body: notification.body ?? '',
          payload: message.data['payload'],
        );
      }
    });

    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
      if (message != null) {
        print('应用被杀时点击通知: ${message.messageId}');
      }
    });
  }
}

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print('收到后台消息: ${message.messageId}');
  await NotificationService().showLocalNotification(
    title: message.notification?.title ?? '',
    body: message.notification?.body ?? '',
  );
}
  1. 后台任务保活适配鸿蒙系统
    鸿蒙系统对于后台应用进程管控十分严格,长时间闲置后台进程会被系统自动清理终止,借助 flutter_background_service 搭建常驻后台服务,提升推送消息接收稳定性,保障后台任务持续运行:
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:flutter_background_service_ohos/flutter_background_service_ohos.dart';

Future<void> initializeBackgroundService() async {
  final service = FlutterBackgroundService();

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onBackgroundServiceStart,
      isForegroundMode: true,
    ),
    ohosConfiguration: OhosConfiguration(
      onStart: onBackgroundServiceStart,
    ),
  );

  await service.start();
}

@pragma('vm:entry-point')
void onBackgroundServiceStart(ServiceInstance service) {
  DartPluginRegistrant.ensureInitialized();

  service.on('receivePushMessage').listen((event) {
    if (event != null) {
      print('后台服务收到推送消息: $event');
    }
  });

  service.on('stopService').listen((event) {
    service.stopSelf();
  });
}

四、鸿蒙适配关键问题与解决方案

  1. 通知权限申请失效问题
    仅仅在配置文件中声明通知权限无法完成权限授予,鸿蒙高版本系统必须在应用内主动调用代码动态申请通知权限,用户手动确认授权后,通知功能才能正常使用,权限申请核心代码如下:
Future<bool> requestNotificationPermission() async {
  final status = await _notificationsPlugin.resolvePlatformSpecificImplementation<
      OhosFlutterLocalNotificationsPlugin>()?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
  return status ?? false;
}
  1. 后台推送消息接收不稳定
    开发中经常遇到应用退至后台后无法正常接收推送消息,出现这类问题首先检查项目配置文件内是否完整声明推送扩展服务能力,其次后台消息全局处理函数必须添加指定注解,保证鸿蒙系统能够正常识别调用该方法。同时精简后台执行逻辑,杜绝大量耗时运算,避免系统判定应用违规直接冻结进程。
  2. 应用离线状态推送消息丢失
    应用彻底关闭杀死进程后,普通应用后台服务会全部终止,无法自主接收推送消息。实际项目开发中优先依托 FCM 系统级推送通道实现离线消息下发,国内正式项目开发可以舍弃 FCM,直接接入鸿蒙原生推送服务,借助官方推送能力大幅提升离线消息到达率。日常开发中也可以搭配轻量级后台心跳任务,维持应用基础进程活跃度,减少离线消息丢失情况。
    五、完整运行验证步骤
    首先完成 Firebase 后台项目搭建,按照平台指引创建鸿蒙端应用,下载官方配置文件放入项目指定目录中。完成全部代码编写与配置修改后,使用 flutter run -d ohos 命令将项目编译安装至鸿蒙测试设备。
    部署完成后进入应用手动开启全部通知与后台运行权限,登录应用获取设备推送令牌,将令牌提交至后端推送平台。最后在推送后台编辑测试推送内容,依次测试应用前台运行、后台挂起、离线关闭三种状态下的消息接收效果,同时点击通知验证页面跳转与数据传递功能是否正常运行。
    六、实战开发避坑经验总结
    日常开发调用本地通知方法后通知栏无任何消息弹出,大概率是遗漏创建鸿蒙专属通知渠道,或是未完成通知权限授权,补齐渠道配置并引导用户开启权限即可解决。后台推送消息监听失效,基本都是后台消息处理函数书写格式错误,未设置为全局顶级函数或者遗漏核心注解,调整函数书写格式就能恢复正常监听。
    项目运行过程中无法正常获取 FCM 推送令牌,优先检查 Firebase 配置文件是否放置正确、文件内容是否匹配当前应用包名,同时排查设备网络环境,确保可以正常连通推送服务网络。后台服务频繁被系统清理关闭,需要优化后台运行代码,降低后台进程资源占用,开启前台服务运行模式,适配鸿蒙系统后台管控规则。
    七、结语
    借助三款主流 Flutter 开发库组合开发,能够快速在开源鸿蒙跨平台应用中搭建完整的本地通知 + 远程推送整套功能体系,覆盖日常开发绝大多数推送业务场景。在鸿蒙生态下做跨平台推送开发,核心开发重点始终围绕系统权限管控、通知渠道规范、后台进程限制三大核心要点展开,贴合系统原生开发规则进行功能适配,就能有效规避大部分兼容问题。
    后续项目迭代优化过程中,可以逐步替换第三方海外推送服务,深度对接鸿蒙官方原生推送套件,贴合国内移动端网络环境,进一步提升推送消息到达率与推送功能运行稳定性,适配更多鸿蒙低端机型,优化整体用户使用体验。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐