Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Flutter_udid 三方库鸿蒙适配之旅:从零到一的深度实践

Flutter_udid 三方库鸿蒙适配之旅:从零到一的深度实践

作者头像
徐建国
发布于 2025-04-24 05:37:22
发布于 2025-04-24 05:37:22
19400
代码可运行
举报
文章被收录于专栏:个人路线个人路线
运行总次数:0
代码可运行

不是所有牛奶都叫特仑苏,唯有鸿蒙化的 Flutter 库,才显非凡。

坚果派已适配的鸿蒙版flutter库

序号

原仓

版本

适配仓

文章解读

1

https://pub.dev/packages/fluttertoast

8.2.12

https://gitcode.com/nutpi/FlutterToast

https://www.nutpi.net/thread?topicId=1575

2

https://pub.dev/packages/flutter_udid

4.0.0

https://gitcode.com/nutpi/flutter_udid

https://www.nutpi.net/thread?topicId=1574

3

https://pub.dev/packages/flutter_exit_app

1.1.4

https://gitcode.com/nutpi/flutter_exit_app

https://www.nutpi.net/thread?topicId=1577

4

https://pub.dev/packages/flutter_phone_direct_caller

2.2.1

https://gitcode.com/nutpi/flutter-phone-direct-caller

5

https://pub.dev/packages/flutter_native_contact_picker

0.0.10

https://gitcode.com/nutpi/flutter_native_contact_picker

https://www.nutpi.net/thread?topicId=1578

6

https://pub.dev/packages/torch_light

https://gitcode.com/nutpi/flutter_torch_light

https://www.nutpi.net/thread?topicId=1579

Flutter_udid 三方库鸿蒙适配之旅:从零到一的深度实践

在数字化浪潮的推动下,跨平台开发框架如 Flutter 凭借其高效、便捷的特性,成为了开发者们的宠儿。而鸿蒙系统的崛起,更是为跨平台开发注入了新的活力。为了助力开发者在鸿蒙生态中快速实现 Flutter_udid 获取设备标识符功能,本文将深入浅出地为大家解析如何适配 Flutter_udid 三方库至鸿蒙平台。

一、OAID 介绍

开放匿名设备标识符(Open Anonymous Device Identifier, OAID,以下简称 OAID):是一种非永久性设备标识符,基于开放匿名设备标识符,OAID 是基于华为自有算法生成的 32 位类 UUID(Universally Unique Identifier)标识符,格式为 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx。

OAID 的特性:

  • OAID 是设备级标识符,同一台设备上不同的 App 获取到的 OAID 值一样。
  • OAID 的获取受应用的“跨应用关联访问权限”开关影响:当应用的“跨应用关联访问权限”开关开启时,该应用可获取到非全 0 的有效 OAID;当应用的“跨应用关联访问权限”开关关闭时,该应用仅能获取到全 0 的 OAID。
  • 同一台设备上首个应用开启应用“跨应用关联访问权限”开关时,会首次生成 OAID

OAID 会在下述场景中发生变化:

  • 用户恢复手机出厂设置。
  • 用户操作重置 OAID。

鸿蒙原生开发步骤

在模块的 module.json5 文件中,申请广告跟踪权限ohos.permission.APP_TRACKING_CONSENT[1],该权限为 user_grant 权限,当申请的权限为 user_grant 权限时,reason,abilities 标签必填,配置方式参见requestPermissions 标签说明[2],示例代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.APP_TRACKING_CONSENT",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "EntryFormAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

应用在需要获取 OAID 信息时,应通过调用 requestPermissionsFromUser 接口获取对应权限。注意:其中 context 的获取方式参见各类 Context 的获取方式[3]。示例代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { identifier } from '@kit.AdsKit';
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

function requestOAIDTrackingConsentPermissions(context: common.Context): void {
  // 进入页面时,向用户请求授权广告跨应用关联访问权限
  const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  try {
    atManager.requestPermissionsFromUser(context, ["ohos.permission.APP_TRACKING_CONSENT"]).then((data) => {
      if (data.authResults[0] === 0) {
        hilog.info(0x0000, 'testTag', '%{public}s', 'succeeded in requesting permission');
        identifier.getOAID((err: BusinessError, data: string) => {
          if (err.code) {
            hilog.error(0x0000, 'testTag', '%{public}s', `get oaid failed, error: ${err.code}${err.message}`);
          } else {
            const oaid: string = data;
            hilog.info(0x0000, 'testTag', '%{public}s', `succeeded in getting oaid by callback , oaid: ${oaid}`);
          }
        });
      } else {
        hilog.error(0x0000, 'testTag', '%{public}s', 'user rejected');
      }
    }).catch((err: BusinessError) => {
      hilog.error(0x0000, 'testTag', '%{public}s', `request permission failed, error: ${err.code}${err.message}`);
    })
  } catch (err) {
    hilog.error(0x0000, 'testTag', '%{public}s', `catch err->${err.code}, ${err.message}`);
  }
}

今天我们一起来看一下如何适配与使用这个三方库

二、flutter_udid 介绍

flutter_udid 是一个 Flutter 插件,用于在 iOSAndroid、Mac、WindowsLinux 平台上检索跨应用重新安装的持久性唯一设备标识符 (UDID)。它的主要特点是提供一种方法来生成和存储设备的唯一标识符,即使在卸载应用后,仍然能保持一致。今天我们会适配支持鸿蒙。

三、插件库使用

适配 OpenHarmony 平台的详细使用指导可以参考:Flutter 使用指导文档[4]

在项目中使用该插件库时,只需在 pubspec.yaml 文件的 dependencies 中新增如下配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dependencies:
  flutter_udid:
    git:
      url: "https://gitcode.com/nutpi/flutter_udid.git"
      path: ""

然后在项目根目录运行 flutter pub get,即可完成依赖添加

接下来是具体的适配过程。

四、适配过程详解

(一)准备工作

确保已经配置好了 Flutter 开发环境,具体可参考 Flutter 配置指南[5]。同时,从 官方插件库[6] 下载待适配的三方插件。本指导书, 以适配 fflutter_udid4.0.0[7] 为例

(二)插件目录结构

下载并解压插件后,我们会看到以下目录结构:

  • lib :对接 Dart 端代码的入口,由此文件接收到参数后,通过 channel 将数据发送到原生端。
  • android :安卓端代码实现目录。
  • ios :iOS 原生端实现目录。
  • example :一个依赖于该插件的 Flutter 应用程序,用于说明如何使用它。
  • README.md :介绍包的文件。
  • CHANGELOG.md :记录每个版本中的更改。
  • LICENSE :包含软件包许可条款的文件。

(三)创建插件的鸿蒙模块

在插件目录下,打开 Terminal,执行以下命令来创建一个鸿蒙平台的 Flutter 模块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
flutter create . --template=plugin --platforms=ohos

步骤:

  1. 用 vscode/trae 打开刚刚下载好的插件。
  2. 打开 Terminal,cd 到插件目录下。
  3. 执行命令flutter create . --template=plugin --platforms=ohos 创建一个 ohos 平台的 flutter 模块。

(四)在根目录下添加鸿蒙平台配置

在项目根目录的 pubspec.yaml 文件中,添加鸿蒙平台的相关配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
name: flutter_udid
description:PlugintoretrieveapersistentUDIDacrossreinstallsoniOSandAndroid
version:4.0.0
homepage:https://github.com/GigaDroid/flutter_udid

environment:
sdk:">=3.0.0 <4.0.0"
flutter:">=3.10.0"

dependencies:
flutter:
    sdk:flutter
crypto:^3.0.0

dev_dependencies:
flutter_test:
    sdk:flutter
flutter_lints:^4.0.0

flutter:
plugin:
    platforms:
      android:
        package:de.gigadroid.flutter_udid
        pluginClass:FlutterUdidPlugin
      ios:
        pluginClass:FlutterUdidPlugin
      macos:
        pluginClass:FlutterUdidPlugin
      windows:
        pluginClass:FlutterUdidPluginCApi
      linux:
        pluginClass:FlutterUdidPlugin
      ohos:
        pluginClass:FlutterUdidPlugin

(五)编写鸿蒙插件的原生 ETS 模块

1. 创建鸿蒙插件模块

使用 DevEco Studio 打开鸿蒙项目。

2. 修改相关配置文件

ohos 目录内的 oh-package.json5 文件中添加 libs/flutter.har 依赖,并创建 .gitignore 文件,添加以下内容以忽略 libs 目录:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/node_modules
/oh_modules
/local.properties
/.preview
/.idea
/build
/libs
/.cxx
/.test
*.har
/BuildProfile.ets
/oh-package-lock.json5

oh-package.json5 文件内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "name": "flutter_udid",
"version": "1.0.0",
"description": "Plugin to retrieve a persistent UDID accross reinstalls on HarmonyOS and OpenHarmony",
"main": "index.ets",
"author": "nutpi",
"license": "Apache-2.0",
"dependencies": {
    "@ohos/flutter_ohos": "file:./libs/flutter.har"
  },
"modelVersion": "5.0.4"
}

ohos 目录下创建 index.ets 文件,导出配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制


import FlutterUdidPlugin from './src/main/ets/de/gigadroid/flutter_udid/FlutterUdidPlugin'

export default FlutterUdidPlugin
3. 编写 ETS 代码

文件结构和代码逻辑可以参考安卓或 iOS 的实现,鸿蒙的 API 文档可以参考 :https://gitcode.com/openharmony-sig/flutter_packages/tree/master/packages/path_provider/path_provider_android

ohos 的 api 可以参考:https://gitcode.com/openharmony/docs

以下是 FlutterUdidPlugin.ets 文件的代码示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

import {
  MethodCallHandler,
  FlutterPlugin,
  BinaryMessenger,
  FlutterPluginBinding,
  AbilityPluginBinding,
  MethodCall,
  MethodChannel,
  MethodResult,
  Log
} from'@ohos/flutter_ohos';
import {  common } from'@kit.AbilityKit';
import { identifier } from'@kit.AdsKit';
import { UIAbility } from'@kit.AbilityKit';
import { requestPermissions } from'./RequestPermissions';

const TAG: string = "FlutterUdidPlugin";

exportdefaultclass FlutterUdidPlugin implements MethodCallHandler, FlutterPlugin {
  private channel: MethodChannel | null = null
  private applicationContext: common.Context | null = null
  private ability: UIAbility | null = null;

constructor(context?: common.Context) {
    if (context) {
      this.applicationContext = context;
    }
  }

static registerWith(): void {
  }

  getUniqueClassName(): string {
    return TAG;
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.onAttachedToEngine1(binding.getApplicationContext(), binding.getBinaryMessenger());
  }

  private onAttachedToEngine1(applicationContext: Context, messenger: BinaryMessenger) {
    this.applicationContext = applicationContext;
    this.channel = new MethodChannel(messenger, "flutter_udid")
    this.channel.setMethodCallHandler(this)
  }

  onAttachedToAbility(binding: AbilityPluginBinding): void {
    this.ability = binding.getAbility()
  }

  onDetachedFromAbility(): void {
    this.ability = null;
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    if (call.method == "getUDID") {
      this.requestPermissions().then((data: boolean) => {
        this.getUDID().then((udid: string | null) => {
          if (udid == null || udid == "") {
            result.error("UNAVAILABLE", "UDID not available.", null)

          } else {
            result.success(udid)
          }
        })
      })
    } else {
      result.notImplemented()
    }
  }

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

  private async getUDID(): Promise<string | null> {
    try {
      returnawait identifier.getOAID()
    } catch (err) {
      returnnull
    }
  }

  private async requestPermissions(): Promise<boolean> {
    if (!this.ability) {
      Log.i(TAG, "Could not launch BarcodeScanner because the plugin is not attached to any ability")
      returnfalse
    }
    try {
      const results = await requestPermissions(this.ability!.context)
      return results ? results : false
    } catch (e) {
    }
    returnfalse
  }
}


以下是 requestPermissions.ets 文件的代码示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import bundleManager from'@ohos.bundle.bundleManager';
import abilityAccessCtrl, { Permissions } from'@ohos.abilityAccessCtrl';
import { BusinessError } from'@kit.BasicServicesKit';

exportconst appTrackingConsentPermission: Array<Permissions> = ['ohos.permission.APP_TRACKING_CONSENT'];

asyncfunction checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;

// 获取应用程序的accessTokenID
let tokenId: number = 0;
try {
    let bundleInfo: bundleManager.BundleInfo =
      await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
    let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
    tokenId = appInfo.accessTokenId;
  } catch (error) {
    let err: BusinessError = error as BusinessError;
    console.error(`Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`);
  }

// 校验应用是否被授予权限
try {
    grantStatus = await atManager.checkAccessToken(tokenId, permission);
  } catch (error) {
    let err: BusinessError = error as BusinessError;
    console.error(`Failed to check access token. Code is ${err.code}, message is ${err.message}`);
  }

return grantStatus;
}

exportasyncfunction checkPermissions(permissions: Array<Permissions>): Promise<boolean> {
let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]);
return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

exportasyncfunction requestPermissions(
  context: Context
) {
const hasAppTrackingConsentPermission: boolean = await checkPermissions(appTrackingConsentPermission);

if (!hasAppTrackingConsentPermission) {
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();

    // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
    try {
      let data = await atManager.requestPermissionsFromUser(context, appTrackingConsentPermission)
      let grantStatus: Array<number> = data.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        if (grantStatus[i] !== 0) {
          // 用户拒绝授权
          returnfalse;
        }
      }
      // 用户授权,可以继续访问目标操作
      returntrue;
    } catch (error) {
      let err: BusinessError = error as BusinessError;
      console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
      returnfalse;
    }
  } else {
    // Permissions already exist. Call the callback with success.
    returntrue;
  }
}




4. 修改 index 文件

ohos 目录下创建 index.ets 文件,导出 FlutterToastPlugin

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

import FlutterUdidPlugin from './src/main/ets/de/gigadroid/flutter_udid/FlutterUdidPlugin'

export default FlutterUdidPlugin

(六)编写 Example

1. 创建 Example 应用

在最开始使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
flutter create . --template=plugin --platforms=ohos

创建模版的时候,也会配套创建 Example

2. 签名与运行

使用 Deveco Studio 打开 example > ohos 目录,单击 File > Project Structure > Project > Signing Configs,勾选 Automatically generate signature,等待自动签名完成。然后运行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
flutter pub get

 flutter build hap --debug

如果应用正常启动,说明插件适配成功。如果没有,欢迎大家联系坚果派一起支持。

五、总结

通过以上步骤,我们成功地将 Flutterudid 三方库适配到了鸿蒙平台。这个过程涉及到了解插件的基本信息、配置开发环境、创建鸿蒙模块、编写原生代码以及测试验证等多个环节。希望这篇博客能够帮助到需要进行 FlutterToast 鸿蒙适配的开发者们,让大家在鸿蒙生态的开发中更加得心应手。

六、参考

  • [如何使用 Flutter 与 OpenHarmony 通信 FlutterChannel](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/如何使用Flutter与OpenHarmony通信 FlutterChannel.md "如何使用 Flutter 与 OpenHarmony 通信 FlutterChannel")
  • [开发 module](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/如何使用混合开发 module.md "开发 module")
  • 开发 package[8]
  • 开发 plugin[9]
  • [开发 FFI plugin](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/开发FFI plugin.md "开发 FFI plugin")
  • https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/oaid-service-V14
  • https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/reference/apis-ads-kit/js-apis-oaid.md

七、坚果派

坚果派由坚果等人创建,团队拥有若干华为 HDE,以及若干其他领域的三十余位万粉博主运营。专注于分享的技术包括 HarmonyOS/OpenHarmony,ArkUI-X,元服务,服务卡片,华为自研语言,BlueOS 操作系统、团队成员聚集在北京、上海、广州、深圳、南京、杭州、苏州、宁夏等地。 聚焦“鸿蒙原生应用”、“智能物联”和“AI 赋能”、“人工智能”四大业务领域,依托华为开发者专家等强大的技术团队,以及涵盖需求、开发、测试、运维于一体的综合服务体系,赋能文旅、媒体、社交、家居、消费电子等行业客户,满足社区客户数字化升级转型的需求,帮助客户实现价值提升。 目前上架鸿蒙原生应用 18 款,三方库 72 个。

地址:

  • https://atomgit.com/nutpi
  • https://gitcode.com/nutpi
  • https://www.nutpi.net/

八、鸿蒙 Flutter 插件:获取 OAID 与应用跟踪权限处理

本文档旨在详细说明在一个 Flutter 插件中,鸿蒙(HarmonyOS)原生侧如何处理获取 OAID(开放匿名设备标识符)时所需的应用跟踪权限(ohos.permission.APP_TRACKING_CONSENT)。我们将基于 FlutterUdidPlugin.etsRequestPermissions.ets 这两个关键文件进行分析。

在许多场景下,应用需要一个设备标识符来进行数据分析、广告投放等。在鸿蒙系统中,OAID 是推荐使用的非永久性、可重置的设备标识符。然而,获取 OAID 需要用户明确授予“应用跟踪”权限。

我们的 Flutter 插件 flutter_udid 旨在提供一个跨平台的接口来获取设备标识符。在鸿蒙侧,这意味着我们需要:

  1. 检查应用是否已被授予 ohos.permission.APP_TRACKING_CONSENT 权限。
  2. 如果未授权,向用户请求该权限。
  3. 在获得权限后,调用鸿蒙提供的 API 获取 OAID。

权限处理核心:RequestPermissions.ets

RequestPermissions.ets 文件封装了检查和请求 ohos.permission.APP_TRACKING_CONSENT 权限的逻辑。其核心功能分为两部分:检查权限和请求权限。

1. 检查权限 (checkPermissionscheckAccessToken)

  • checkPermissions(permissions: Array<Permissions>): Promise<boolean>: 这是暴露给外部调用的函数,用于检查传入的权限列表(在此场景下主要是 appTrackingConsentPermission)是否已被授予。
  • checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus>: 这是实际执行权限检查的内部函数。它执行以下步骤:
    1. 使用 abilityAccessCtrl.createAtManager() 创建权限管理实例。
    2. 使用 bundleManager.getBundleInfoForSelf() 获取当前应用的 tokenId (accessTokenId)。这是检查特定应用权限所必需的。
    3. 调用 atManager.checkAccessToken(tokenId, permission) 来检查指定 tokenId 的应用是否已被授予 permission
    4. 返回权限的授予状态 (GrantStatus)。
  • checkPermissions 函数最终会比较 checkAccessToken 返回的状态是否为 PERMISSION_GRANTED,并返回一个布尔值。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RequestPermissions.ets (简化示例)
import bundleManager from'@ohos.bundle.bundleManager';
import abilityAccessCtrl, { Permissions } from'@ohos.abilityAccessCtrl';

exportconst appTrackingConsentPermission: Array<Permissions> = ['ohos.permission.APP_TRACKING_CONSENT'];

asyncfunction checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
// ... 获取 tokenId
// ... 调用 atManager.checkAccessToken(tokenId, permission)
// ... 返回 grantStatus
}

exportasyncfunction checkPermissions(permissions: Array<Permissions>): Promise<boolean> {
let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]);
return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

2. 请求权限 (requestPermissions)

  • requestPermissions(context: Context): Promise<boolean>: 这是主要的权限请求函数。
    • 创建 abilityAccessCtrl.AtManager 实例。
    • 调用 atManager.requestPermissionsFromUser(context, appTrackingConsentPermission)。这个方法会触发系统弹窗,请求用户授权。
    • requestPermissionsFromUser 返回一个包含授权结果(authResults)的对象。这是一个数字数组,0 代表授予,非 0 代表拒绝。
    • 遍历 authResults,如果所有请求的权限都被授予(即所有结果都是 0),则返回 true;否则返回 false
    • 包含错误处理逻辑,捕获请求过程中可能出现的 BusinessError
    1. 首先调用 checkPermissions 检查是否已获得 appTrackingConsentPermission
    2. 如果已授权:直接返回 true
    3. 如果未授权
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RequestPermissions.ets (简化示例)
exportasyncfunction requestPermissions(
  context: Context
): Promise<boolean> {
const hasPermission: boolean = await checkPermissions(appTrackingConsentPermission);

if (!hasPermission) {
    let atManager = abilityAccessCtrl.createAtManager();
    try {
      let data = await atManager.requestPermissionsFromUser(context, appTrackingConsentPermission);
      // ... 检查 data.authResults ...
      // ... 返回 true 或 false
    } catch (error) {
      // ... 处理错误,返回 false
    }
  } else {
    returntrue;
  }
}

插件集成:FlutterUdidPlugin.ets

FlutterUdidPlugin.ets 是 Flutter 与鸿蒙原生代码交互的桥梁。它通过 MethodChannel 接收来自 Flutter 端的调用。

当 Flutter 端调用 getUDID 方法时,onMethodCall 函数会被触发:

  1. 调用权限请求: 首先调用 this.requestPermissions()。注意,这个 requestPermissionsFlutterUdidPlugin 类内部的方法,它会进一步调用我们之前分析的 RequestPermissions.ets 中的 requestPermissions 函数。
    • FlutterUdidPlugin 内部的 requestPermissions 方法需要确保 this.ability (当前的 UIAbility 实例) 不为 null,因为请求权限需要一个 Context,通常从 Ability 获取。
    • 它调用 RequestPermissions.ets 中的 requestPermissions(this.ability!.context)
  2. 处理权限结果: this.requestPermissions() 返回一个 Promise,其结果是一个布尔值 data,表示权限是否被授予。
  3. 获取 OAID: 在权限请求的 Promise 完成后(.then((data: boolean) => { ... })),无论权限是否成功授予(虽然逻辑上应该只在授予后获取,但当前代码结构是在 then 回调中直接调用 getUDID),都会调用 this.getUDID()
    • getUDID() 方法使用 @kit.AdsKit 中的 identifier.getOAID() 来异步获取 OAID。
  4. 返回结果给 Flutter: 获取 OAID 的 Promise 完成后 (.then((udid: string | null) => { ... })):
    • 如果 udidnull 或空字符串,通过 result.error() 返回错误给 Flutter 端。
    • 如果成功获取 udid,通过 result.success(udid) 将 OAID 返回给 Flutter 端。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// FlutterUdidPlugin.ets (简化示例)
import { requestPermissions as requestAppPermissions } from'./RequestPermissions';
import { identifier } from'@kit.AdsKit';

exportdefaultclass FlutterUdidPlugin implements MethodCallHandler, FlutterPlugin {
// ... 其他成员和方法 ...
private ability: UIAbility | null = null;

  onMethodCall(call: MethodCall, result: MethodResult): void {
    if (call.method == "getUDID") {
      this.requestPermissions().then((granted: boolean) => {
        // 注意:原始代码在这里没有显式检查 granted 的值
        // 理想情况下,应该检查 granted 是否为 true
        // if (granted) { ... } else { result.error(...) }
        this.getUDID().then((udid: string | null) => {
          if (udid) {
            result.success(udid);
          } else {
            result.error("UNAVAILABLE", "UDID not available.", null);
          }
        });
      });
    } else {
      result.notImplemented();
    }
  }

privateasync getUDID(): Promise<string | null> {
    try {
      returnawait identifier.getOAID();
    } catch (err) {
      returnnull;
    }
  }

privateasync requestPermissions(): Promise<boolean> {
    if (!this.ability) {
      returnfalse;
    }
    try {
      // 调用 RequestPermissions.ets 中的函数
      returnawait requestAppPermissions(this.ability!.context);
    } catch (e) {
      returnfalse;
    }
  }
}

结论

通过 RequestPermissions.ets 封装鸿蒙的权限检查和请求逻辑,FlutterUdidPlugin.ets 可以在需要时调用这些功能,确保在获取 OAID 之前,应用已经获得了用户的应用跟踪许可。这种分层设计使得权限管理逻辑清晰、可复用,并简化了主插件逻辑。

注意: 示例代码中的 onMethodCall 在调用 getUDID 前并未严格检查 requestPermissions 的返回结果。在实际应用中,建议在确认权限被授予 (granted === true) 后才执行获取 OAID 的操作,并在权限被拒绝时向 Flutter 返回相应的错误信息。

命令

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
flutter pub get

 flutter build hap --debug



flutter config --ohos-sdk=/Users/jianguo/Library/OpenHarmony/Sdk

flutter config --ohos-sdk=""

参考资料

[1]

ohos.permission.APP_TRACKING_CONSENT: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/permissions-for-all-user-V14#ohospermissionapp_tracking_consent

[2]

requestPermissions 标签说明: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/declare-permissions-V14#在配置文件中声明权限

[3]

各类 Context 的获取方式: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V14/js-apis-inner-application-context-V14

[4]

Flutter 使用指导文档: https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/07_plugin/ohos%E5%B9%B3%E5%8F%B0%E9%80%82%E9%85%8Dflutter%E4%B8%89%E6%96%B9%E5%BA%93%E6%8C%87%E5%AF%BC.md

[5]

Flutter 配置指南: https://gitcode.com/openharmony-sig/flutter_flutter/blob/master/README.md

[6]

官方插件库: https://pub.dev/

[7]

fflutter_udid4.0.0: https://pub-web.flutter-io.cn/packages/flutter_udid/versions/4.0.0

[8]

开发 package: https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/开发package.md

[9]

开发 plugin: https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/开发plugin.md

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大前端之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ohos 平台适配 flutter 三方库指导 url_launcher
lib:是对接 dart 端代码的入口,由此文件接收到参数后,通过 channel 将数据发送到原生端;
徐建国
2025/06/30
1000
ohos 平台适配 flutter 三方库指导 url_launcher
鸿蒙Next应用权限管理
简介: 系统提供了一种允许应用访问系统资源(如:通讯录等)和系统能力(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被不当或恶意使用。 授权方式: system_grant(系统授权)指的是系统授权类型,如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。 user_grant(用户授权)指的是用户授权类型,该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。
用户4773577
2025/06/27
1050
现有 Flutter 项目支持鸿蒙
最近这关税战打的是不亦说乎,从另一方面来说,国产替代浪潮奔涌,鸿蒙适配已成为一个必答题,这里面跨端框架是破局多 OS 割裂的最优解。比如 Flutter,之前有很多 app 可能是用 Flutter 做的,那么如何支持鸿蒙呢?
徐建国
2025/04/15
2.7K0
现有 Flutter 项目支持鸿蒙
鸿蒙原生应用开发【分布式数据对象】
在可信组网环境下,多个相互组网认证的设备将各自创建的对象加入同一个 sessionId,使得加入的多个数据对象之间可以同步数据,也就是说,当某一数据对象属性发生变更时,其他数据对象会检测到这一变更,同时将自身属性更新。此时,该 sessionId 下的所有数据对象属性相同,这样的数据对象称之为分布式数据对象。此外,分布式数据对象可以被动退出 sessionId,当分布式数据对象退出 sessionId 后,该对象将检测不到其他对象的变更。
小帅聊鸿蒙
2024/06/28
1440
鸿蒙原生应用开发【分布式数据对象】
鸿蒙应用开发-录音保存并播放音频
录音并保存为m4a格式的音频,然后播放该音频,参考文档使用AVRecorder开发音频录制功能(ArkTS),更详细接口信息请查看接口文档:@ohos.multimedia.media (媒体服务)。
夜雨飘零
2024/05/26
5291
鸿蒙应用开发-录音保存并播放音频
Flutter 开发鸿蒙应用时三方库引入指南
近期有开发者反馈,在使用 Flutter 开发鸿蒙应用过程中,file_picker 和 file_selector 这两个三方库在鸿蒙系统上出现点击无响应的情况,而相同代码在安卓系统上却能正常拉起文件选择器。该项目使用的是 Flutter 3.22.0 ohos 版本,相关导入代码如下:
徐建国
2025/05/26
3260
Flutter 开发鸿蒙应用时三方库引入指南
解锁 Flutter_exit_app 库鸿蒙适配:离一键退出鸿蒙应用仅一步之遥
在数字化浪潮的推动下,跨平台开发框架如 Flutter 凭借其高效、便捷的特性,成为了开发者们的宠儿。而鸿蒙系统的崛起,更是为跨平台开发注入了新的活力。为了助力开发者在鸿蒙生态中快速实现 flutter_exit_app 退出应用程序功能,本文将深入浅出地为大家解析如何适配 flutter_exit_app 三方库至鸿蒙平台。
徐建国
2025/04/30
1470
解锁 Flutter_exit_app 库鸿蒙适配:离一键退出鸿蒙应用仅一步之遥
《仿盒马》app开发技术分享-- 原生地图展示(26)
上一节我们实现了获取当前用户的位置,并且成功的拿到了经纬度,这一节我们就要根据拿到的经纬度,结合我们其他的知识点来实现地图的展示。
用户10696402
2025/06/23
490
鸿蒙5开发宝藏案例分享---快捷触达的骑行体验
大家好!上次分享了鸿蒙那个超棒的共享单车体验案例,很多朋友留言说想看代码细节。没问题!这就带大家深入代码层,看看那些“丝滑”的体验(扫码直达、实时状态窗、路径规划)到底是怎么敲出来的。官方文档有时像藏宝图,代码才是真金白银!
陈杨
2025/06/17
1230
适配 HarmonyOS Next API16 的鸿蒙版 Flutter 3.22.0 版本正式发布(1.0Release)
本版本为基于 Flutter 3.22.0 适配的 OpenHarmony 版本。本版本支持和完善 OpenHarmony 平台侧能力,提升稳定性。
徐建国
2025/05/08
5810
适配 HarmonyOS Next API16 的鸿蒙版 Flutter 3.22.0 版本正式发布(1.0Release)
HarmonyOS NEXT 权限申请系统授权和用户授权权限
在鸿蒙原生开发中,我们normal级别的证书能够使用的权限分为系统授权权限和用户授权权限
水滴石轩
2025/03/17
3170
HarmonyOS NEXT 权限申请系统授权和用户授权权限
【HarmonyOS 5】鸿蒙应用隐私保护详解
在今天这个手机不离手的时代,我们每天用手机支付、聊天、记录生活,不知不觉中,大量个人信息都存储在了移动设备里。但你有没有想过,如果这些隐私数据泄露了会怎样?从接到诈骗电话,到遭遇身份盗用,后果可能不堪设想。好在,HarmonyOS早就为我们的隐私安全做好了全方位的防护。
GeorgeGcs
2025/05/06
3020
【HarmonyOS 5】鸿蒙应用隐私保护详解
HarmonyOS 开发实践——基于设置应用的应用权限、通知设置跳转
引导用户跳转到系统设置页进行权限,通知的相关设置,类似android和iOS应用中常见的应用内跳转到设置进行通知开启或权限设置的操作。
小帅聊鸿蒙
2024/11/03
3380
HarmonyOS 开发实践——基于设置应用的应用权限、通知设置跳转
三文带你轻松上手鸿蒙的AI语音01-实时语音识别
HarmonyOSNext中集成了强大的AI功能。Core Speech Kit(基础语音服务)是它提供的众多AI功能中的一种。
万少
2025/02/09
3100
三文带你轻松上手鸿蒙的AI语音01-实时语音识别
用 Flutter 开发鸿蒙 PC 应用
本文为开发者提供了使用 Flutter 开发鸿蒙 PC 应用的全面指南。涵盖开发环境搭建、项目创建与配置、界面设计、业务逻辑开发以及调试测试等环节,同时强调适配鸿蒙 PC 界面规范和调用系统能力的方法。还分享了实用的注意事项、相关资源链接,帮助开发者高效地使用Flutter构建鸿蒙 PC 应用。
徐建国
2025/05/19
4500
用 Flutter 开发鸿蒙 PC 应用
【HarmonyOS】应用权限原理和封装
在项目中,避免不了需要调用系统资源和系统能力,比如:日历读写、摄像头等。因此,需要了解对系统资源访问权限的申请方式方法。
钟子翔
2024/12/24
1250
鸿蒙开发学习:定位相关知识(Locationkit)
LocationKit提供了定位服务、地理围栏、地理编码、逆地理编码和国家码等功能。
钟子翔
2024/12/24
1300
HarmonyOS 开发实践 —— 基于@ohos.pasteboard实现剪贴板功能
本模块主要提供管理系统剪贴板的能力,为系统复制、粘贴功能提供支持。系统剪贴板支持对文本、HTML、URI、Want、PixelMap等内容的操作。
小帅聊鸿蒙
2024/12/01
2680
HarmonyOS 开发实践 —— 基于@ohos.pasteboard实现剪贴板功能
鸿蒙开发:权限授权封装
关于权限相关的知识点,陆陆续续分享了三篇了,也在前边的文章中关于权限的状态获取,以及权限的申请也做了原生代码的案例分享,本篇文章,我们把权限授权封装一下,便于在实际的开发中灵活的使用。
程序员一鸣
2025/03/18
1240
鸿蒙开发:权限授权封装
【HarmonyOS】鸿蒙应用蓝牙功能实现(一)
##鸿蒙开发能力 ##HarmonyOS SDK应用服务##鸿蒙金融类应用 (金融理财#
GeorgeGcs
2025/06/29
1090
推荐阅读
相关推荐
ohos 平台适配 flutter 三方库指导 url_launcher
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档