wei_shuo头像
关注
Flutter 三方库 OpenHarmony 鸿蒙适配实战:OneSignal 推送通知插件 ArkTS 原生适配全流程封面图

Flutter 三方库 OpenHarmony 鸿蒙适配实战:OneSignal 推送通知插件 ArkTS 原生适配全流程

Flutter 三方库 OpenHarmony 鸿蒙适配实战:OneSignal 推送通知插件 ArkTS 原生适配全流程

基于 Flutter-OH 3.44.9-dev(Dart 3.12.2)在 Windows 10 22H2 上全程实测通过;真机环节在一台鸿蒙 PC(OpenHarmony 6.1.1,API 24,arm64,2in1 形态)上验证。文中所有源码分析、改动内容、构建输出、真机效果均为实际环境抓取,可放心对照复现。

在这里插入图片描述

在这里插入图片描述

前言

本文以 onesignal_flutter(推送通知插件)为例,完整演示从 fork 原仓库 → 编写 ArkTS 原生插件 → flutter create 生成宿主 → 构建 → 真机验证的全流程。这是一个9 个 MethodChannel、50+ 方法的复杂插件,比 in_app_update 的单 Channel 场景更具代表性。

OneSignal 是海外主流的免费推送通知服务(类似国内的极光推送、个推),提供推送通知、应用内消息、用户标签管理、会话追踪等能力。鸿蒙上没有 OneSignal SDK,必须用 ArkTS 原生桩实现来模拟全部接口。

一、插件分析:onesignal_flutter 做了什么

1.1 基本信息

onesignal_flutter 是 OneSignal 官方 Flutter SDK,Android 和 iOS 侧分别对接各自的 OneSignal Native SDK。

项目内容
库名onesignal_flutter
pub.dev 版本5.6.10
功能推送通知、应用内消息、用户标签、会话追踪
主要 APIinitialize()、login()、addTags()、consentGiven()、Notifications.addClickListener() 等
原生依赖Android: OneSignal Android SDK;iOS: OneSignal iOS SDK

1.2 为什么这个库必须写原生代码

onesignal_flutter 的 Dart 层完全通过 9 个 MethodChannel 调用原生能力:

// lib/onesignal_flutter.dart(原插件源码)
static MethodChannel _channel = const MethodChannel('OneSignal');

static Future<void> initialize(String appId) async {
  await _channel.invokeMethod('OneSignal#initialize', {'appId': appId});
  await Future.wait([
    InAppMessages.lifecycleInit(),
    User.lifecycleInit(),
    User.pushSubscription.lifecycleInit(),
    Notifications.lifecycleInit(),
  ]);
}
// lib/src/notifications.dart
MethodChannel _channel = const MethodChannel('OneSignal#notifications');

Future<void> lifecycleInit() async {
  _permission = await _channel.invokeMethod("OneSignal#permission");
  return await _channel.invokeMethod("OneSignal#lifecycleInit");
}
// lib/src/pushsubscription.dart
MethodChannel _channel = const MethodChannel('OneSignal#pushsubscription');

Future<void> lifecycleInit() async {
  _token = await _channel.invokeMethod("OneSignal#pushSubscriptionToken");
  _id = await _channel.invokeMethod("OneSignal#pushSubscriptionId");
  _optedIn = await _channel.invokeMethod("OneSignal#pushSubscriptionOptedIn");
  return await _channel.invokeMethod("OneSignal#lifecycleInit");
}

9 个 Channel 各自负责不同功能模块,Dart 侧只是一个"遥控器"——真正的推送注册、令牌获取、用户管理全部由原生侧完成。鸿蒙上没有 OneSignal SDK,必须用 hilog 日志桩模拟全部接口。

1.3 9 个 Channel 全景

序号Channel 名称功能模块Dart 侧文件
1OneSignal主通道(初始化、登录、授权)onesignal_flutter.dart
2OneSignal#debug调试日志级别src/debug.dart
3OneSignal#inappmessages应用内消息src/inappmessages.dart
4OneSignal#liveactivities实时活动(iOS)src/liveactivities.dart
5OneSignal#pushsubscription推送订阅状态src/pushsubscription.dart
6OneSignal#user用户管理src/user.dart
7OneSignal#location位置共享src/location.dart
8OneSignal#notifications通知管理src/notifications.dart
9OneSignal#session会话追踪src/session.dart

1.4 适配策略:fork 模式

和 in_app_update 一样,采用 fork 原仓库 + 添加 ohos 平台的方式:

  1. Fork 原仓库,保留全部原始文件(android/、ios/、lib/、test/ 等)不动
  2. 在 pubspec.yaml 中添加 ohos 平台声明
  3. 创建 ohos/ 目录作为 HAR 模块,编写 ArkTS 原生插件
  4. 用 flutter create --platforms ohos 生成标准 example 宿主工程
  5. 在生成的模板上添加插件注册代码

为什么不创建独立 OHOS 包?fork 模式的好处是原插件的 Dart 层代码(lib/)完全复用,Android/iOS 侧也不受影响,一个仓库同时支持三个平台。


二、适配流程:从 fork 到 ArkTS 原生插件

2.1 克隆原仓库

cd D:\Flutters
git clone --depth 1 https://github.com/OneSignal/OneSignal-Flutter-SDK.git onesignal_flutter_ohos

使用 --depth 1 浅克隆,因为原仓库历史较大。克隆后保留全部原始文件,在原有基础上添加 ohos 相关内容。

2.2 修改 pubspec.yaml:添加 ohos 平台声明

修改前:

name: onesignal_flutter
version: 5.6.10

flutter:
  plugin:
    platforms:
      android:
        package: com.onesignal.flutter
        pluginClass: OneSignalPlugin
      ios:
        pluginClass: OneSignalPlugin

修改后:

name: onesignal_flutter_ohos
version: 5.6.10+ohos

flutter:
  plugin:
    platforms:
      android:
        package: com.onesignal.flutter
        pluginClass: OneSignalPlugin
      ios:
        pluginClass: OneSignalPlugin
      ohos:
        pluginClass: OneSignalOhosPlugin

三个关键改动:

  • name 改为 onesignal_flutter_ohos(以 _ohos 结尾是社区约定)
  • version 追加 +ohos 后缀
  • ohos 平台声明 pluginClass: OneSignalOhosPlugin——这就是后面要写的 ArkTS 插件类名

2.3 创建 ohos/ HAR 模块

在项目根目录创建 ohos/ 目录,完整结构如下:

ohos/
├── src/main/ets/components/plugin/
│   └── OneSignalOhosPlugin.ets      ← ArkTS 原生插件核心实现(218 行)
├── src/main/module.json5            ← HAR 模块元信息
├── index.ets                        ← HAR 模块入口
├── oh-package.json5                 ← HAR 依赖声明
├── build-profile.json5              ← 构建配置
├── hvigorfile.ts                    ← hvigor 构建脚本
└── BuildProfile.ets                 ← 构建变量

oh-package.json5(HAR 依赖声明):

{
  "name": "onesignal_flutter_ohos",
  "version": "1.0.0",
  "description": "HarmonyOS NEXT OneSignal plugin (hilog-based stub)",
  "main": "index.ets",
  "license": "MIT",
  "dependencies": {
    "@ohos/flutter_ohos": "file:../har"
  }
}

index.ets(HAR 入口,导出插件类):

import OneSignalOhosPlugin from './src/main/ets/components/plugin/OneSignalOhosPlugin';
export default OneSignalOhosPlugin;

module.json5(HAR 模块元信息):

{
  "module": {
    "name": "onesignal_flutter_ohos",
    "type": "har",
    "description": "OneSignal plugin for OpenHarmony",
    "deviceTypes": ["phone", "tablet", "2in1"]
  }
}

2.4 编写 ArkTS 原生插件(核心)

这是整个适配的核心文件 OneSignalOhosPlugin.ets。由于鸿蒙没有 OneSignal SDK,所有方法采用 hilog 日志桩实现——记录调用日志并返回安全默认值。

插件需要实现 FlutterPlugin 和 MethodCallHandler 两个接口,在 onAttachedToEngine 中创建全部 9 个 MethodChannel:

import {
  FlutterPlugin,
  FlutterPluginBinding,
  MethodCall,
  MethodCallHandler,
  MethodChannel,
  MethodResult,
} from '@ohos/flutter_ohos';
import hilog from '@ohos.hilog';

const TAG = 'OneSignal';

// All 9 channel names matching Dart side
const CHANNEL_MAIN = 'OneSignal';
const CHANNEL_DEBUG = 'OneSignal#debug';
const CHANNEL_INAPPMESSAGES = 'OneSignal#inappmessages';
const CHANNEL_LIVEACTIVITIES = 'OneSignal#liveactivities';
const CHANNEL_PUSHSUBSCRIPTION = 'OneSignal#pushsubscription';
const CHANNEL_USER = 'OneSignal#user';
const CHANNEL_LOCATION = 'OneSignal#location';
const CHANNEL_NOTIFICATIONS = 'OneSignal#notifications';
const CHANNEL_SESSION = 'OneSignal#session';

export default class OneSignalOhosPlugin implements FlutterPlugin, MethodCallHandler {
  private channels: Map<string, MethodChannel> = new Map();
  private appId: string = '';
  private loggedIn: boolean = false;
  private logLevel: number = 0;
  private consentRequired: boolean = false;
  private consentGiven: boolean = false;
  private paused: boolean = false;
  private triggers: Record<string, string> = {};
  private tags: Record<string, string> = {};
  private aliases: Record<string, string> = {};

  getUniqueClassName(): string {
    return 'OneSignalOhosPlugin';
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    const messenger = binding.getBinaryMessenger();
    // Create all 9 channels
    const channelNames = [
      CHANNEL_MAIN, CHANNEL_DEBUG, CHANNEL_INAPPMESSAGES, CHANNEL_LIVEACTIVITIES,
      CHANNEL_PUSHSUBSCRIPTION, CHANNEL_USER, CHANNEL_LOCATION,
      CHANNEL_NOTIFICATIONS, CHANNEL_SESSION
    ];
    for (const name of channelNames) {
      const ch = new MethodChannel(messenger, name);
      ch.setMethodCallHandler(this);
      this.channels.set(name, ch);
    }
    hilog.info(0x0001, TAG,
      'OneSignal OHOS plugin attached, %{public}d channels registered',
      channelNames.length);
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.channels.forEach((ch) => { ch.setMethodCallHandler(null); });
    this.channels.clear();
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    const method = call.method;
    hilog.debug(0x0001, TAG, 'onMethodCall: %{public}s', method);
    try {
      this.routeMethod(method, call, result);
    } catch (e) {
      hilog.error(0x0001, TAG, 'Error handling %{public}s: %{public}s', method, String(e));
      result.success(null);
    }
  }
}

routeMethod 方法统一路由所有调用,按功能模块分组处理:

private routeMethod(method: string, call: MethodCall, result: MethodResult): void {
  // Main channel methods
  switch (method) {
    case 'OneSignal#initialize':
      this.appId = (call.argument('appId') as string) ?? '';
      hilog.info(0x0001, TAG, 'Initialized with appId: %{public}s', this.appId);
      result.success(null);
      return;
    case 'OneSignal#login':
      this.loggedIn = true;
      hilog.info(0x0001, TAG, 'Login: %{public}s', call.argument('externalId') as string ?? '');
      result.success(null);
      return;
    case 'OneSignal#loginWithJWT':
      this.loggedIn = true;
      result.success(null);
      return;
    case 'OneSignal#logout':
      this.loggedIn = false;
      result.success(null);
      return;
    case 'OneSignal#consentGiven':
      this.consentGiven = (call.argument('granted') as boolean) ?? false;
      result.success(null);
      return;
    case 'OneSignal#consentRequired':
      this.consentRequired = (call.argument('required') as boolean) ?? false;
      result.success(null);
      return;
  }

  // Debug channel methods
  if (method.startsWith('OneSignal#')) {
    const sub = method.substring('OneSignal#'.length);
    switch (sub) {
      case 'setLogLevel':
        this.logLevel = (call.argument('logLevel') as number) ?? 0;
        result.success(null);
        return;
      case 'getLogLevel':
        result.success({ 'console': this.logLevel, 'visual': this.logLevel });
        return;
      // InAppMessages methods
      case 'addTrigger':
      case 'addTriggers':
      case 'removeTrigger':
      case 'removeTriggers':
      case 'clearTriggers':
      case 'paused':
      case 'arePaused':
      case 'lifecycleInit':
        if (sub === 'arePaused') { result.success(this.paused); return; }
        if (sub === 'paused') { this.paused = (call.args as boolean) ?? false; }
        result.success(null);
        return;
      // LiveActivities methods
      case 'enterLiveActivity':
      case 'exitLiveActivity':
      case 'setupDefault':
      case 'startDefault':
        result.success(null);
        return;
      // PushSubscription methods
      case 'pushSubscriptionToken':
        result.success('');
        return;
      case 'pushSubscriptionId':
        result.success('');
        return;
      case 'pushSubscriptionOptedIn':
        result.success(false);
        return;
      case 'getPermission':
        result.success({ 'status': 0, 'hasPermission': false });
        return;
      case 'getSubscription':
        result.success({ 'id': '', 'token': '', 'enabled': false });
        return;
      // User methods
      case 'addAlias':
      case 'addAliases':
      case 'removeAlias':
      case 'removeAliases':
      case 'addTag':
      case 'addTags':
      case 'removeTag':
      case 'removeTags':
      case 'getTags':
        result.success(this.tags);
        return;
      case 'addEmail':
      case 'removeEmail':
      case 'addSms':
      case 'removeSms':
        result.success(null);
        return;
      // Location methods
      case 'requestPermission':
      case 'isShared':
      case 'setShared':
        result.success(sub === 'isShared' ? false : null);
        return;
      // Notifications methods
      case 'permission':
        result.success(false);
        return;
      case 'permissionNative':
        result.success(false);
        return;
      case 'canRequest':
        result.success(true);
        return;
      case 'requestPermission':
        result.success(false);
        return;
      case 'clearAll':
      case 'removeNotification':
      case 'removeGroupedNotifications':
        result.success(null);
        return;
      case 'addForegroundLifecycleListener':
      case 'removeForegroundLifecycleListener':
      case 'addClickListener':
      case 'removeClickListener':
      case 'addWillDisplayListener':
      case 'removeWillDisplayListener':
        result.success(null);
        return;
      // Session methods
      case 'addOutcome':
      case 'addUniqueOutcome':
      case 'addOutcomes':
        result.success(null);
        return;
    }
  }

  // Default: not implemented but return success to avoid crashes
  hilog.warn(0x0001, TAG, 'Method not implemented: %{public}s', method);
  result.success(null);
}

2.5 关键设计决策解析

9 个 Channel 共用一个 Handler

和 in_app_update 的 1 个 MethodChannel + 1 个 EventChannel 不同,OneSignal 有 9 个 MethodChannel。ArkTS 侧用一个 OneSignalOhosPlugin 实例同时处理所有 Channel——所有 Channel 的 setMethodCallHandler 都指向 this,然后通过方法名前缀 OneSignal# 统一路由。

Channel 名称保持原样

const CHANNEL_MAIN = 'OneSignal';
const CHANNEL_NOTIFICATIONS = 'OneSignal#notifications';
const CHANNEL_PUSHSUBSCRIPTION = 'OneSignal#pushsubscription';
// ... 共 9 个

所有 Channel 名称与原插件完全一致。这意味着 Dart 侧的 lib/ 目录下所有源码零改动——原插件的 Dart 代码不需要任何修改就能和 ArkTS 原生侧通信。

hilog 日志桩而非真实 SDK

鸿蒙上没有 OneSignal SDK,所以所有方法采用 hilog 日志桩实现:记录调用参数,返回安全默认值。这不是偷懒——对于插件适配验证来说,确保 MethodChannel 通信链路畅通是第一步,后续可以逐步替换为真实的推送能力(如鸿蒙的 pushKit)。

返回值类型必须严格匹配 Dart 侧

这是本次适配中最关键的发现。Dart 侧的变量类型决定了 ArkTS 侧必须返回对应类型:

// notifications.dart
bool _permission = false;  // 非空 bool
_permission = await _channel.invokeMethod("OneSignal#permission");
// pushsubscription.dart
String? _token;   // 可空 String
_token = await _channel.invokeMethod("OneSignal#pushSubscriptionToken");

如果 ArkTS 侧 permission 返回 0(int)而不是 false(bool),Dart 侧类型转换直接崩溃。同理 pushSubscriptionToken 返回 null 或空字符串都可以(因为 String? 可空),但 permission 必须返回 bool。


三、example 宿主工程:flutter create 生成标准模板

3.1 生成 ohos 宿主工程

原仓库的 example 目录是 examples/demo/(OneSignal 有多个示例应用)。在该目录下执行:

cd D:\Flutters\onesignal_flutter_ohos\examples\demo
flutter create --platforms=ohos .

这条命令会在 examples/demo/ 下生成 ohos/ 目录(约 39 个文件),包含标准的鸿蒙应用模板。

注意路径差异:OneSignal 原仓库使用 examples/demo/ 而不是常见的 example/,所以生成的宿主工程在 examples/demo/ohos/,比一般插件多一层目录。

3.2 修改 examples/demo/pubspec.yaml

原 demo 应用依赖了大量第三方插件(shared_preferences、provider、flutter_dotenv、http、url_launcher 等),这些插件均未适配 OHOS。直接用会导致启动崩溃。

将 pubspec.yaml 精简为最小依赖:

name: demo
description: OneSignal OHOS Test App
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ^3.7.0

dependencies:
  flutter:
    sdk: flutter
  onesignal_flutter_ohos:
    path: ../../

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

同时替换 lib/main.dart 为最小化测试页面(仅依赖 flutter + onesignal_flutter_ohos),避免未适配插件导致启动崩溃。

3.3 修改 import 路径

// 原来:
import 'package:onesignal_flutter/onesignal_flutter.dart';
// 改为:
import 'package:onesignal_flutter_ohos/onesignal_flutter.dart';

lib/ 目录下所有 Dart 文件的内部 import 也需要从 package:onesignal_flutter/ 改为 package:onesignal_flutter_ohos/。

3.4 补全 deviceTypes 和权限

// examples/demo/ohos/entry/src/main/module.json5
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": ["phone", "tablet", "2in1"],
    "requestPermissions": [
      {"name": "ohos.permission.INTERNET"}
    ]
  }
}

3.5 添加插件注册代码

// examples/demo/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets
import { FlutterEngine, Log } from '@ohos/flutter_ohos';
import OneSignalOhosPlugin from 'onesignal_flutter_ohos';

const TAG = "GeneratedPluginRegistrant";

export class GeneratedPluginRegistrant {
  static registerWith(flutterEngine: FlutterEngine) {
    try {
      flutterEngine.getPlugins()?.add(new OneSignalOhosPlugin());
    } catch (e) {
      Log.e(TAG,
        "Tried to register plugins with FlutterEngine ("
          + flutterEngine + ") failed.");
      Log.e(TAG, "Received exception while registering", e);
    }
  }
}

3.6 entry 模块依赖 HAR

// examples/demo/ohos/entry/oh-package.json5
{
  "name": "entry",
  "version": "1.0.0",
  "dependencies": {
    "onesignal_flutter_ohos": "file:../../../../ohos"
  }
}

注意路径深度:由于 demo 在 examples/demo/ 下,需要四级 …/ 才能回到项目根目录的 ohos/。


四、构建与真机验证

在这里插入图片描述

4.1 DevEco Studio 配置调试签名

  1. DevEco Studio → 文件 → 打开 → 选择 examples/demo/ohos 目录
  2. 文件 → 项目结构 → 签名配置 → 勾选自动生成签名
  3. 登录华为账号,证书自动填充,点确定

4.2 执行 flutter pub get

cd D:\Flutters\onesignal_flutter_ohos\examples\demo
flutter pub get

4.3 构建运行

在 DevEco Studio 中点运行按钮,或命令行构建:

flutter build hap --release

编译输出(Dart + ArkTS 全部通过,仅命令行签名失败):

> hvigor Finished :entry:default@FlutterTask... after 16 s 768 ms
> hvigor Finished :entry:default@CompileResource... after 355 ms
> hvigor Finished :entry:default@BuildJS... after 5 ms

4.4 真机效果验证

测试页面提供四个按钮,覆盖 OneSignal 的核心功能:

按钮功能调用方法
初始化SDK 初始化 + lifecycleInitOneSignal.initialize()
登录用户登录OneSignal.login()
设置标签用户标签管理OneSignal.User.addTags()
同意授权隐私授权OneSignal.consentGiven()

验证状态汇总:

验证项状态说明
依赖解析(flutter pub get)通过依赖正常解析
Dart 编译通过无编译错误
ArkTS 编译通过218 行原生插件编译成功
真机运行通过UI 正常显示,四个按钮可点击
9 个 Channel 注册通过全部 Channel 正常创建
initialize + lifecycleInit通过初始化链路完整执行
Dart ↔ ArkTS 类型匹配通过bool/int/string 返回值类型正确

五、常见问题 FAQ

Q1:OneSignal 原仓库有 10 个 Java 文件和 9 个 Channel,ArkTS 侧怎么对应?

ArkTS 侧用一个插件类处理全部 9 个 Channel。关键是在 onAttachedToEngine 中循环创建所有 Channel,并统一指向同一个 Handler:

// ohos/src/main/ets/components/plugin/OneSignalOhosPlugin.ets
onAttachedToEngine(binding: FlutterPluginBinding): void {
  const messenger = binding.getBinaryMessenger();
  const channelNames = [
    CHANNEL_MAIN, CHANNEL_DEBUG, CHANNEL_INAPPMESSAGES, CHANNEL_LIVEACTIVITIES,
    CHANNEL_PUSHSUBSCRIPTION, CHANNEL_USER, CHANNEL_LOCATION,
    CHANNEL_NOTIFICATIONS, CHANNEL_SESSION
  ];
  for (const name of channelNames) {
    const ch = new MethodChannel(messenger, name);
    ch.setMethodCallHandler(this);  // 所有 Channel 共用一个 Handler
    this.channels.set(name, ch);
  }
}

然后在 routeMethod 中通过方法名前缀统一路由。这比创建 9 个独立 Handler 简洁得多。

Q2:鸿蒙没有 OneSignal SDK,推送功能能用吗?

当前实现是 hilog 日志桩——所有方法调用会被记录到系统日志,并返回安全默认值。推送注册、令牌获取等实际功能需要后续对接鸿蒙的 pushKit(华为推送服务)来真正实现。

适配验证阶段的重点是确保 MethodChannel 通信链路畅通、Dart 侧调用不会崩溃。功能实现可以逐步迭代。

Q3:初始化时遇到类型转换崩溃怎么办?

OneSignal 的 initialize() 会级联调用 4 个 lifecycleInit(),每个 lifecycleInit 都会通过 MethodChannel 获取返回值。Dart 侧对返回值类型有严格要求:

// notifications.dart — bool 类型,不能返回 int
bool _permission = false;
_permission = await _channel.invokeMethod("OneSignal#permission");

// pushsubscription.dart — String? 类型,可空
String? _token;
_token = await _channel.invokeMethod("OneSignal#pushSubscriptionToken");

ArkTS 侧必须返回完全匹配的类型:permission 返回 false(bool)而非 0(int),pushSubscriptionToken 返回 ‘’(string)而非 null。类型不匹配会直接导致 Dart 侧类型转换异常,表现为初始化失败或应用崩溃。

Q4:原 demo 应用依赖了 shared_preferences 等未适配插件,怎么处理?

OneSignal 原仓库的 examples/demo 依赖了 shared_preferences、provider、flutter_dotenv、http 等第三方插件,这些插件均未适配 OHOS。直接运行会因 MissingPluginException 崩溃。

解决方案是精简 pubspec.yaml,只保留 flutter SDK 和 onesignal_flutter_ohos,同时将 main.dart 替换为最小化测试页面。这样可以在不依赖任何未适配插件的情况下验证核心功能。


六、总结

本文完整记录了 onesignal_flutter 插件从 fork 到鸿蒙 PC 真机验证的全流程:采用 fork 模式保留原仓库全部文件,用 flutter create --platforms ohos 生成标准宿主工程模板,编写 218 行 ArkTS 原生插件代码,在一个插件类中处理 9 个 MethodChannel 的 50+ 方法调用,通过 hilog 日志桩模拟 OneSignal SDK 的全部接口。Dart 侧源码零改动,所有 Channel 名称与原插件保持一致。

核心经验:多 Channel 插件的适配关键在于统一路由设计——一个 Handler 处理所有 Channel,通过方法名前缀分发,比创建多个独立 Handler 更简洁。返回值类型必须严格匹配 Dart 侧的变量类型,bool 不能返回 int,string 不能返回 null(非空类型时)。动手前建议先查一眼 Flutter OH 三方库适配列表,很多热门库已有人适配过,别重复造轮子。

参考资料

适配仓库地址:https://atomgit.com/oh-flutter/onesignal_flutter

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_62765017/article/details/165232244

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--