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

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐