Flutter 三方库 flutter_local_notifications 的鸿蒙化适配指南

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

一、引言

在移动应用开发领域,推送通知作为用户留存与互动的核心手段,其重要性不言而喻。随着开源鸿蒙生态的快速发展,越来越多的开发者开始将 Flutter 跨平台应用迁移至 OpenHarmony 平台。然而,由于平台架构差异,许多成熟的 Flutter 三方库在鸿蒙设备上无法直接运行,需要进行针对性适配。

flutter_local_notifications 作为 Flutter 生态中最流行的本地通知库之一,支持定时通知、通知渠道管理、自定义通知样式等核心功能,广泛应用于待办提醒、日程推送等场景。本文将围绕该库的鸿蒙化适配展开深入探讨,通过系统性分析与实践验证,为开发者提供一套可落地的适配方案。

二、适配背景与技术选型

2.1 技术背景

flutter_local_notifications 库最初基于 Android NotificationManager API 设计,通过 Flutter 平台通道实现跨平台调用。在 OpenHarmony 系统中,虽然提供了类似的 NotificationManager 服务,但在 API 设计、权限模型与系统行为上存在显著差异:

  1. API 兼容性差异:OpenHarmony NotificationManager 采用了全新的接口设计,与 Android 版本不完全兼容
  2. 权限模型差异:鸿蒙系统对通知权限采用更严格的分级管理
  3. 后台行为限制:鸿蒙系统对后台定时任务有更严格的资源调度策略

2.2 适配目标

本次适配旨在实现以下核心目标:

  1. 保持 Flutter API 层的一致性,降低开发者学习成本
  2. 实现鸿蒙平台 NotificationManager 服务的完整适配
  3. 确保定时通知在后台环境下的准确性
  4. 支持鸿蒙系统特有的通知渠道管理功能

三、鸿蒙化适配核心步骤

3.1 项目结构调整

在开始适配前,我们需要调整项目结构以支持 OpenHarmony 平台:

flutter_local_notifications/
├── android/
├── ios/
├── openharmony/          # 新增鸿蒙平台目录
│   ├── entry/
│   └── oh-package.json5
├── lib/
│   ├── flutter_local_notifications.dart
│   └── src/
└── pubspec.yaml

3.2 平台通道实现

在鸿蒙平台上,我们需要实现自定义的 MethodChannel 来处理 Flutter 侧的调用请求:

// lib/src/flutter_local_notifications.dart
class FlutterLocalNotificationsPlugin {
  static const MethodChannel _channel =
      MethodChannel('dexterous.com/flutter/local_notifications');
  
  // ... 原有代码 ...
  
  Future<void> initialize(
    InitializationSettings initializationSettings, {
    SelectNotificationCallback? onSelectNotification,
  }) async {
    // 适配鸿蒙平台初始化逻辑
    if (Platform.isOpenHarmony) {
      await _channel.invokeMethod('initialize', initializationSettings.toMap());
    } else {
      // 原有平台逻辑
    }
  }
}

3.3 NotificationManager 兼容性适配

在鸿蒙端,我们需要实现与 Android 类似的 NotificationManager 封装:

// openharmony/entry/src/main/java/com/dexterous/flutterlocalnotifications/FlutterLocalNotificationsPlugin.java
public class FlutterLocalNotificationsPlugin implements MethodCallHandler {
    private NotificationManager notificationManager;
    private Context context;
    
    @Override
    public void onMethodCall(MethodCall call, Result result) {
        switch (call.method) {
            case "initialize":
                initialize(call, result);
                break;
            case "show":
                showNotification(call, result);
                break;
            // 其他方法实现
        }
    }
    
    private void initialize(MethodCall call, Result result) {
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        result.success(null);
    }
    
    private void showNotification(MethodCall call, Result result) {
        // 鸿蒙通知构建逻辑
        NotificationRequest notificationRequest = new NotificationRequest(1);
        NotificationNormalContent content = new NotificationNormalContent();
        content.setTitle(call.argument("title"));
        content.setText(call.argument("body"));
        notificationRequest.setContent(content);
        
        notificationManager.publish(notificationRequest);
        result.success(null);
    }
}

3.4 通知渠道配置

鸿蒙系统要求所有通知必须属于特定渠道,我们需要实现渠道管理功能:

// lib/src/initialization_settings.dart
class AndroidInitializationSettings {
  final String? defaultIcon;
  final bool? requestSoundPermission;
  final bool? requestBadgePermission;
  final bool? requestAlertPermission;
  final bool? requestVibrationPermission;
  final bool? requestLightsPermission;
  
  // 新增鸿蒙渠道配置
  final List<AndroidNotificationChannel>? channels;
  
  const AndroidInitializationSettings(
    this.defaultIcon, {
    this.requestSoundPermission = true,
    this.requestBadgePermission = true,
    this.requestAlertPermission = true,
    this.requestVibrationPermission = true,
    this.requestLightsPermission = true,
    this.channels,
  });
}

3.5 定时通知适配

鸿蒙系统对后台定时任务有严格限制,我们需要使用 WorkScheduler 来实现定时通知:

// openharmony/entry/src/main/java/com/dexterous/flutterlocalnotifications/ScheduledNotificationWorker.java
public class ScheduledNotificationWorker extends Worker {
    @Override
    public Result doWork() {
        // 执行定时通知逻辑
        NotificationManager notificationManager = 
            (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
        
        // 构建并发送通知
        NotificationRequest notificationRequest = new NotificationRequest(1);
        // ... 通知内容构建 ...
        
        notificationManager.publish(notificationRequest);
        
        return Result.success();
    }
}

四、完整代码实现

4.1 Flutter 侧核心代码

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

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化通知配置
  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  
  const InitializationSettings initializationSettings =
      InitializationSettings(
    android: initializationSettingsAndroid,
  );
  
  await flutterLocalNotificationsPlugin.initialize(initializationSettings);
  
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('鸿蒙通知示例')),
        body: Center(
          child: ElevatedButton(
            onPressed: _showNotification,
            child: const Text('发送通知'),
          ),
        ),
      ),
    );
  }
  
  Future<void> _showNotification() async {
    const AndroidNotificationDetails androidNotificationDetails =
        AndroidNotificationDetails(
      'your channel id',
      'your channel name',
      channelDescription: 'your channel description',
      importance: Importance.max,
      priority: Priority.high,
    );
    
    const NotificationDetails notificationDetails =
        NotificationDetails(android: androidNotificationDetails);
    
    await flutterLocalNotificationsPlugin.show(
      0,
      '鸿蒙通知标题',
      '这是一条来自 Flutter 的鸿蒙通知',
      notificationDetails,
    );
  }
}

4.2 鸿蒙侧配置文件

// openharmony/entry/oh-package.json5
{
  "name": "flutter_local_notifications",
  "version": "0.0.1",
  "description": "Flutter local notifications plugin for OpenHarmony",
  "main": "index.ets",
  "dependencies": {
    "@ohos.notification": "^10.0.0"
  }
}

五、验证与测试

5.1 测试环境

  • 设备:华为 Mate 40 Pro(HarmonyOS 4.0)
  • Flutter 版本:3.13.0
  • OpenHarmony SDK 版本:4.0.10.1

5.2 测试步骤

  1. 权限配置:在 entry/src/main/module.json5 中添加通知权限:
{
  "module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.POST_NOTIFICATION"
      }
    ]
  }
}
  1. 编译运行
flutter build openharmony
hdc install flutter_local_notifications-ohos.apk

5.3 运行截图

在这里插入图片描述

六、常见问题与解决方案

6.1 通知权限问题

问题:应用无法发送通知,提示权限不足

解决方案

  1. module.json5 中声明 ohos.permission.POST_NOTIFICATION 权限
  2. 在应用启动时主动请求通知权限:
await flutterLocalNotificationsPlugin
    .resolvePlatformSpecificImplementation<
        AndroidFlutterLocalNotificationsPlugin>()
    ?.requestNotificationsPermission();

6.2 定时通知不准确

问题:后台定时通知延迟或不触发

解决方案

  1. 使用鸿蒙 WorkScheduler 替代 Android AlarmManager
  2. 优化后台任务优先级配置
  3. 避免在低电量模式下测试定时任务

七、性能优化建议

7.1 内存优化

  1. 避免在通知回调中执行耗时操作
  2. 及时释放通知资源,避免内存泄漏
  3. 优化通知图标资源,减少内存占用

7.2 电池优化

  1. 合理设置定时通知频率,避免频繁唤醒设备
  2. 使用鸿蒙系统的低功耗模式适配
  3. 优化后台任务调度策略

八、总结与展望

通过本次适配,我们成功实现了 flutter_local_notifications 库在 OpenHarmony 平台上的完整功能支持,验证了跨平台技术在鸿蒙生态中的可行性。适配过程中,我们遵循了以下核心原则:

  1. API 一致性原则:保持 Flutter 侧 API 不变,降低开发者迁移成本
  2. 平台原生原则:充分利用鸿蒙系统原生能力,确保性能与兼容性
  3. 可维护性原则:采用模块化设计,便于后续功能扩展
Logo

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

更多推荐