HarmonyOS鸿蒙Next应用如何获取设备唯一标识(如 IMEI、OAID)?

HarmonyOS鸿蒙Next应用如何获取设备唯一标识(如 IMEI、OAID)? 需要做设备风控,传统方案是读 IMEI,但现在隐私政策越来越严。鸿蒙还允许获取硬件 ID 吗?有没有替代方案?

7 回复

鸿蒙禁止普通应用获取 IMEI、MAC、Serial Number 等硬件标识

更多关于HarmonyOS鸿蒙Next应用如何获取设备唯一标识(如 IMEI、OAID)?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


直接调用官方api deviceInfo 来获取设备信息不就可以了

官方地址

cke_668.png

目前可以获取到软件版本号、硬件版本号、Build版本号等

这个里面的UDID好像能满足你的需求:如何通过API获取常见设备标识符并实现标识符不发生变化,你看看对你有没有帮助。

可以参考文档,ohos.deviceInfo (设备信息),看可有帮助:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-device-info

参考其它示例代码,https://developer.huawei.com/consumer/cn/blog/topic/03189375471183037

import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { AAID } from '@kit.PushKit';
import { abilityAccessCtrl, bundleManager, common } from '@kit.AbilityKit';
import { identifier } from '@kit.AdsKit';

export default class DeviceIdTest {

  // Get ODID.
  getOdId(): string {
    let odId = deviceInfo.ODID;
    console.info(`getOdId: ${odId}`);
    return odId;
  }

  // Get AAID.
  async getAaId(): Promise<string> {
    let aaId = '';
    await AAID.getAAID().then((data: string) => {
      aaId = data;
      console.info(`getAAID: ${aaId}`);
    }).catch((err: BusinessError) => {
      console.error('Failed to get AAID', err.code, err.message);
    })
    return aaId;
  }

  // Get OAID.
  getOaId() {
    let hasPermission = false;
    let tokenId: number = 0;
    try {
      // Obtain the current application's BundleInfo based on the given BundleFlags using synchronous methods.
      let bundleInfo: bundleManager.BundleInfo =
        bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
      let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
      tokenId = appInfo.accessTokenId;
    } catch (error) {
      const err = error as BusinessError;
      hilog.error(0x0000, 'testTag', '%{public}s',
        `Failed to query Asset. Code: ${err.code}, message: ${err.message}`);
    }

    try {
      let atManager = abilityAccessCtrl.createAtManager();
      // Verify whether the application has been granted permissions through tokenID and permissionName.
      let access = atManager.checkAccessTokenSync(tokenId, 'ohos.permission.APP_TRACKING_CONSENT');
      hasPermission = access === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
    } catch (error) {
      const err = error as BusinessError;
      hilog.error(0x0000, 'testTag', '%{public}s',
        `Failed to check access token. Code: ${err.code}, message: ${err.message}`);
    }

    if (hasPermission) {
      this.rquestOAID();
    } else {
      this.requestPermissions();
    }
  }

  private rquestOAID() {
    // The API is not supported on all devices. Use the canIUse condition to determine whether the API is supported.
    if (canIUse('SystemCapability.Advertising.OAID')) {
      try {
        // Obtain open anonymous device identifiers.
        identifier.getOAID().then((data) => {
          hilog.info(0x0000, 'testTag', '%{public}s', `Success getting OAID by promise, OAID:', ${data}`);
        }).catch((err: BusinessError) => {
          hilog.error(0x0000, 'testTag', '%{public}s',
            `get oaid by promise failed, code: ${err.code}, message: ${err.message}`);
        })
      } catch (err) {
        hilog.error(0x0000, 'testTag', '%{public}s',
          `Failed to get oaid by promise, catch error: ${err.code}, ${err.message}`);
      }
    } else {
      hilog.info(0x0000, 'testTag', '%{public}s', 'Advertising not by this device.');
    }
  }

  // Request Permissions.
  private requestPermissions() {
    let atManager = abilityAccessCtrl.createAtManager();
    try {
      atManager.requestPermissionsFromUser(getContext(this) as common.UIAbilityContext,
        ['ohos.permission.APP_TRACKING_CONSENT']).then((data) => {
        hilog.info(0x0000, 'testTag', '%{public}s', `requestPermissionsFromUser: ${JSON.stringify(data)}`)
        if (data.authResults[0] === -1 && data.dialogShownResults && !data.dialogShownResults[0]) {
          // User not authorized.
          this.openPermissionsSetting();
        }
        if (data.authResults[0] !== 0) {
          // No permission obtained.
          hilog.info(0x0000, 'testTag', 'No permission obtained');
          return;
        }
        this.rquestOAID();
      }).catch((err: Error) => {
        hilog.error(0x0000, 'testTag', '%{public}s', `requestPermissionsFromUser err: ${JSON.stringify(err)}`);
      })
    } catch (err) {
      hilog.error(0x0000, 'testTag', '%{public}s', `requestPermissionsFromUser err: ${JSON.stringify(err)}`);
    }
  }

  // Open permissions setting.
  private openPermissionsSetting() {
    let atManager = abilityAccessCtrl.createAtManager();
    atManager.requestPermissionOnSetting(getContext(this) as common.UIAbilityContext, ['ohos.permission.APP_TRACKING_CONSENT'])
      .then((data: Array<abilityAccessCtrl.GrantStatus>) => {
        if (data[0] === -1) {
          hilog.info(0x0000, 'testTag', 'not access');
          return;
        }
        this.rquestOAID();
      }).catch((err: BusinessError) => {
      hilog.error(0x0000, 'testTag', '%{public}s', `requestPermissionOnSetting err: ${JSON.stringify(err)}`);
    })
  }

}

在HarmonyOS Next中,获取设备唯一标识需使用@ohos.deviceInfo模块。 通过deviceInfo.getDeviceId()可获取设备标识符,该标识符在设备生命周期内保持唯一。 对于OAID等广告标识符,需使用@ohos.identifier.oaid模块的getOAID()方法获取。 注意:IMEI等敏感信息需系统权限,普通应用无法直接获取。

在HarmonyOS Next中,直接获取IMEI等硬件级设备唯一标识已被严格限制,这是遵循当前隐私保护强化的必然趋势。

对于设备风控场景,推荐使用以下替代方案:

  1. OpenHarmony DeviceIdentifier(首选方案) 这是系统提供的标准设备标识符,旨在平衡标识唯一性与用户隐私。其特性包括:

    • 重置敏感性:设备恢复出厂设置后标识符会改变。
    • 应用独立性:同一设备上不同应用获取的值相同,可用于跨应用协作(需各自声明权限)。
    • 权限控制:需要申请 ohos.permission.DISTRIBUTED_DATASYNC 权限。

    核心代码示例(ArkTS)

    import deviceInfo from '@ohos.deviceInfo';
    
    try {
      let deviceId: string = deviceInfo.deviceId; // 获取DeviceIdentifier
      console.log('Device ID: ' + deviceId);
    } catch (err) {
      console.error('Failed to get device ID. Code: ' + err.code + ', message: ' + err.message);
    }
    
  2. 应用级实例标识(AAID) 如果风控逻辑可限定在应用内,可使用 getUdid 方法生成一个应用实例唯一的标识符。该标识符:

    • 在应用卸载重装后会改变。
    • 适用于跟踪单应用内的独立实例。
  3. 结合多维度软硬件信息(非唯一标识) 可安全采集多项非敏感、非唯一的信息进行组合计算,生成一个高概率唯一的设备指纹,例如:

    • 设备型号 (deviceInfo.model)
    • 系统版本 (deviceInfo.osFullName)
    • 屏幕分辨率
    • 时区、语言设置
    • 设备基础能力列表 (deviceInfo.capabilities)

    注意:此方案生成的标识不具备系统级绝对唯一性,且随设备配置改变可能变化,适用于辅助风险评估而非绝对标识。

总结与建议: 对于HarmonyOS Next的设备风控,应优先采用系统提供的 deviceInfo.deviceId (DeviceIdentifier)。它提供了当前系统环境下最佳的标识能力。请务必在应用的 module.json5 配置文件中声明所需权限,并在应用中向用户清晰说明标识符的用途。

在架构设计时,建议将设备标识与用户账号体系结合,并准备应对标识符因系统重置而变更的情况,以构建更健壮的风控逻辑。

回到顶部