Flutter-OH 三方库 devicelocale 鸿蒙适配

Flutter 三方库 devicelocale 鸿蒙适配

欢迎大家加入开源鸿蒙跨平台开发者社区

一、背景与库简介

devicelocale 是 Flutter 上用于获取设备当前语言与区域设置的插件,原版支持 Android、iOS、Web、Linux、macOS 等平台,通过 MethodChannel 与原生端通信,提供:

  • 设备偏好语言列表(preferredLanguages
  • 当前区域字符串(currentLocale,如 zh-Hans-CNen-US
  • 按应用设置语言(Android 13+ 的 setLanguagePerApp 等)

本文介绍如何为该库增加 OpenHarmony / 鸿蒙 平台支持,并给出 完整 ETS 实现代码,便于复用到其他类似插件。


二、适配思路概览

  1. 对齐已有平台协议 :Dart 侧使用固定 MethodChannel 名称 uk.spiralarm.flutter/devicelocale,并约定方法名:preferredLanguagescurrentLocalesetLanguagePerAppisLanguagePerAppSettingSupportedgetPlatformVersion。鸿蒙侧需实现同名 MethodChannel 与相同方法名。
  2. 参考 Android 实现 :Android 端使用 LocaleListCompat.getAdjustedDefault()Locale.getDefault().toLanguageTag() 等获取语言列表与当前区域;鸿蒙侧用 i18n.SystemgetPreferredLanguageList()getSystemLocale() 等 API 做等价实现。
  3. 平台能力差异 :「按应用设置语言」在鸿蒙上暂不实现,对应方法返回 false,与 Android 13 以下行为一致。

三、鸿蒙侧实现要点

3.1 依赖与入口

  • Flutter 鸿蒙插件 :使用 @ohos/flutter_ohosFlutterPluginMethodChannelMethodCallHandlerMethodResult 等。
  • 系统语言 API :使用 @kit.LocalizationKiti18n.SystemgetSystemLocalegetPreferredLanguageListgetFirstPreferredLanguagegetSystemLanguage)。若为纯 OpenHarmony 环境,可改为 @ohos.i18n 并按实际 API 微调。

3.2 MethodChannel 名称

必须与 Dart 端一致,否则无法通信:

ts 复制代码
this.channel = new MethodChannel(binding.getBinaryMessenger(), "uk.spiralarm.flutter/devicelocale");

3.3 方法映射与返回值

Dart 调用方法 MethodChannel 方法名 鸿蒙返回值说明
preferredLanguages preferredLanguages 字符串数组,首项为当前系统语言
currentLocale currentLocale 当前区域字符串,如 zh-Hans-CN、en-US
setLanguagePerApp setLanguagePerApp 暂不支持,返回 false
isLanguagePerAppSettingSupported 同名 返回 false
(可选)平台版本 getPlatformVersion "OpenHarmony"

3.4 异常与兼容

  • getSystemLocale() 在部分机型/版本可能不可用,建议用 getFirstPreferredLanguage()getSystemLanguage() 做降级。
  • getPreferredLanguageList() 返回值可能非数组,需做 Array.isArray(list) 判断,否则回退为仅包含当前 locale 的列表。

四、完整实现代码(DevicelocalePlugin.ets)

以下为鸿蒙侧插件的 完整 ETS 实现 ,可直接用于 ohos/src/main/ets/components/plugin/DevicelocalePlugin.ets

ets 复制代码
import {
  FlutterPlugin,
  FlutterPluginBinding,
  MethodCall,
  MethodCallHandler,
  MethodChannel,
  MethodResult,
} from '@ohos/flutter_ohos';
import { i18n } from '@kit.LocalizationKit';

/** DevicelocalePlugin - 参考 Android 实现,提供设备语言与偏好语言列表 */
export default class DevicelocalePlugin implements FlutterPlugin, MethodCallHandler {
  private channel: MethodChannel | null = null;

  constructor() {
  }

  getUniqueClassName(): string {
    return "DevicelocalePlugin";
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(binding.getBinaryMessenger(), "uk.spiralarm.flutter/devicelocale");
    this.channel.setMethodCallHandler(this);
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    if (this.channel != null) {
      this.channel.setMethodCallHandler(null);
    }
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    const method = call.method;
    switch (method) {
      case "preferredLanguages":
        result.success(this.getPreferredLanguages());
        break;
      case "currentLocale":
        result.success(this.getCurrentLocale());
        break;
      case "setLanguagePerApp":
        result.success(this.setLanguagePerAppSetting(call));
        break;
      case "isLanguagePerAppSettingSupported":
        result.success(this.isLanguagePerAppSettingSupported());
        break;
      case "getPlatformVersion":
        result.success("OpenHarmony");
        break;
      default:
        result.notImplemented();
    }
  }

  /** 当前系统区域标识,如 zh-Hans-CN、en-US */
  private getCurrentLocale(): string {
    try {
      return i18n.System.getSystemLocale();
    } catch (e) {
      try {
        return i18n.System.getFirstPreferredLanguage();
      } catch (_e) {
        return i18n.System.getSystemLanguage();
      }
    }
  }

  /** 系统偏好语言列表,与 Android LocaleListCompat.getAdjustedDefault() 对应 */
  private getPreferredLanguages(): Array<string> {
    try {
      const list = i18n.System.getPreferredLanguageList();
      return Array.isArray(list) ? list : [this.getCurrentLocale()];
    } catch (e) {
      return [this.getCurrentLocale()];
    }
  }

  /** OHOS 暂按不支持"按应用设置语言"处理,与 Android 13 以下行为一致 */
  private isLanguagePerAppSettingSupported(): boolean {
    return false;
  }

  /** 暂不支持,返回 false */
  private setLanguagePerAppSetting(call: MethodCall): boolean {
    return false;
  }
}

说明

  • 若使用 OpenHarmony 且无 @kit.LocalizationKit,可改为:import { i18n } from '@ohos.i18n';,并确认 i18n.System.getSystemLocale() / getPreferredLanguageList() 等在该环境下存在且命名一致。
  • setLanguagePerAppSetting 未使用 call 参数,保留参数是为与 Dart 侧 setLanguagePerApp(Locale locale) 的调用方式一致,便于日后扩展。

五、Dart 侧使用方式(无需改库核心代码)

插件在 pubspec.yaml 中声明 ohos 平台后,Dart 侧无需区分平台即可使用,例如:

dart 复制代码
import 'package:devicelocale/devicelocale.dart';

// 偏好语言列表(字符串)
final List? list = await Devicelocale.preferredLanguages;

// 当前区域字符串
final String? locale = await Devicelocale.currentLocale;

// 当前区域转 Locale
final Locale? localeObj = await Devicelocale.currentAsLocale;

鸿蒙上 isLanguagePerAppSettingSupportedfalsesetLanguagePerApp 会直接返回 false,不会走原生逻辑。


六、小结

  • 通过 对齐 MethodChannel 名称与方法名用鸿蒙 i18n.System API 实现与 Android 等价的"偏好语言列表 + 当前区域",即可在鸿蒙上完整支持 devicelocale 的读能力。
  • 上述 DevicelocalePlugin.ets 为完整实现,可直接复制到工程中使用;按应用设置语言在鸿蒙上暂不实现,接口保持与 Dart 一致即可。
  • 适配思路(参考 Android、统一 Channel、异常降级)也可复用到其他需要「设备语言/区域」的 Flutter 鸿蒙插件。

参考

相关推荐
2501_9219308310 小时前
进阶实战 Flutter for OpenHarmony:Isolate 多线程计算系统 - 并发任务处理实现
flutter
加农炮手Jinx10 小时前
Flutter for OpenHarmony 实战:JWT — 构建安全的无状态认证中心
网络·flutter·华为·harmonyos·鸿蒙
左手厨刀右手茼蒿10 小时前
Flutter for OpenHarmony: Flutter 三方库 hashlib 为鸿蒙应用提供军用级加密哈希算法支持(安全数据完整性卫士)
安全·flutter·华为·c#·哈希算法·linq·harmonyos
王码码203510 小时前
Flutter for OpenHarmony: Flutter 三方库 cryptography 在鸿蒙上实现金融级现代加解密(高性能安全库)
android·安全·flutter·华为·金融·harmonyos
亚历克斯神11 小时前
Flutter for OpenHarmony:Flutter 三方库 yaml_edit 精准修改 YAML 文件内容(保留注释与格式的编辑神器)
android·flutter·华为·harmonyos
加农炮手Jinx11 小时前
Flutter for OpenHarmony:image_picker 插件鸿蒙化适配指南
flutter·华为·harmonyos
左手厨刀右手茼蒿12 小时前
Flutter for OpenHarmony: Flutter 三方库 image_size_getter 零加载极速获取图片尺寸(鸿蒙 UI 布局优化必备)
android·服务器·flutter·ui·华为·harmonyos
亚历克斯神12 小时前
Flutter for OpenHarmony:zxing2 纯 Dart 条码扫描与生成库(不仅是扫码,更是编解码引擎) 深度解析与鸿蒙适配指南
android·flutter·华为·harmonyos
钛态12 小时前
Flutter for OpenHarmony:dio_cookie_manager 让 Dio 发挥会话管理能力,像浏览器一样自动处理 Cookie 深度解析与鸿蒙适配指南
android·linux·运维·flutter·ui·华为·harmonyos