HarmonyOS 应用内部测试全面指南

2025-06-20 17:23:20
174次阅读
0个评论
最后修改时间:2025-07-21 23:23:39

一、内部测试概述

HarmonyOS 应用内部测试是面向企业开发者的功能,允许在不提交华为应用市场审核的情况下,将应用分发到最多 100 台授权设备进行测试。通过设备 UDID 授权机制,仅允许已注册设备安装使用,适用于开发团队内共享应用、提前测试功能及优化版本体验。当前仅支持 Stage 模型开发的 HarmonyOS 应用,暂不支持元服务。

二、准备工作

  • 开发者资质:需注册华为开发者账号并完成企业开发者实名认证。

三、内部测试核心流程

申请发布证书**
**

  • 作用:由 AGC 颁发的数字证书,保障代码完整性和发布者身份真实性,格式为.cer。
  • 限制:每个账号最多申请 3 个,有效期 3 年,到期后更新版本需更换证书。
  • 流程:在 AGC“证书、APP ID 和 Profile> 证书” 页面,上传 DevEco Studio 生成的 CSR 文件申请,下载后保存至本地。

注册测试设备**
**

  • 限制:每年最多注册 100 台设备,注册后一年内不可删除,删除后仍占用名额。
  • 操作:通过设备 UDID(64 位字符串)在 AGC “设备” 页面注册,支持单个添加或批量导入(模板下载后填写设备信息)。

申请内部测试 Profile

  • 作用:格式为.p7b,包含包名、证书、权限列表及授权设备信息,每个应用包必须包含。
  • 权限申请
  • HarmonyOS API9 及以上:申请受限 ACL 权限(如输入监听、剪贴板读取等),需描述使用场景,审批通过后添加到 Profile。
  • API9 以下:仅支持申请读取 / 写入联系人权限。
  • 设备关联:从已注册设备中选择最多 100 台,后续可通过 “编辑设备” 修改。

配置签名信息

  • 在 DevEco Studio 中,使用私钥(.p12)、发布证书(.cer)和 Profile(.p7b)配置工程签名,取消 “自动生成签名” 并填写密钥库密码、别名等信息。

编译打包应用

  • HAP 包:主模块编译后在 “build/default/outputs/default” 目录获取。
  • HSP 包:共享包模块通过 “Make Module” 生成,用于应用内共享资源。

上传应用包与生成描述文件

  • 服务器要求:支持 HTTPS 协议,配置分片下载(返回码 206)和正确响应头(如 Content-Type: application/hap)。
  • 描述文件:JSON 格式,包含 bundleName、versionCode、modules 等信息,需计算包的 SHA256 值并签名,上传后获取下载 URL。
  1. 构造 DeepLink 拉起安装
  • 格式:​​store://enterprise/manifest?url=https://xxx.xxx/xxx.json5​​,需使用华为浏览器点击触发,URL 需编码特殊字符。
  • 示例:通过 HTML 按钮调用​​window.open()​​方法触发 DeepLink。

四、错误码与解决方案

下载错误码**
**

  • 10000:DeepLink 格式错误,需确保 URL 以.json5 结尾且域名与 deployDomain 一致。
  • 10019:描述文件验签失败,检查签名密钥与安装包签名是否一致。
  • 10021:证书校验失败,确认设备 UDID 在 Profile 授权列表内。

安装错误码**
**

  • 参考 OpenHarmony 官方文档,常见问题如包完整性校验失败(10020)、证书不匹配等。

五、FAQ

应用已过期

  • 内部测试版本有效期 90 天,需更新版本号后重新编译打包。

无法打开应用

  • 安装设备超过 100 台限制,需删除未使用设备或创建新 Profile。

六、关键限制与最佳实践

  • 设备管理:定期清理无效设备,超过一年删除的设备自动释放名额。
  • 权限申请:优先使用系统控件(如 Picker)替代受限权限,避免上架审核驳回。
  • 版本管理:每次更新 Profile 后需重新下载并配置签名,确保设备列表及时更新。
import preferences from '@ohos.data.preferences';

@Entry
@Component
struct InternalTestDeviceRegister {
  // 设备UDID(64位字符串)
  @State deviceUDID: string = '';

  // 页面构建
  build() {
    Column() {
      // 标题
      Text('内部测试设备注册')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      // UDID显示区域
      Text(this.deviceUDID ? `设备UDID: ${this.deviceUDID}` : '正在获取设备信息...')
        .fontSize(16)
        .padding(15)
        .borderRadius(8)
        .backgroundColor(Color.White)
        .width('90%')

      // 操作按钮
      Button(this.deviceUDID ? '复制到剪贴板' : '获取UDID')
        .type(ButtonType.Capsule)
        .backgroundColor('#007DFF')
        .width('70%')
        .height(50)
        .margin({ top: 30 })
        .onClick(() => {
          if (this.deviceUDID) {
            this.copyToClipboard();
          } else {
            this.fetchDeviceUDID();
          }
        })
        
      // 注册状态显示
      if (this.isDeviceRegistered()) {
        Text('✅ 设备已注册到AGC')
          .fontColor(Color.Green)
          .margin({ top: 20 })
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#F5F5F5')
    .onPageShow(() => {
      this.loadSavedUDID();
    })
  }

  // 获取设备UDID
  private fetchDeviceUDID() {
    try {
      // 从系统服务获取设备唯一标识
      this.deviceUDID = deviceInfo.udid;
      
      // 保存到本地偏好设置
      preferences.getPreferences(getContext(), 'deviceInfo')
        .then(pref => {
          pref.put('udid', this.deviceUDID)
          pref.flush()
          console.info('UDID保存成功');
        })
    } catch (error) {
      console.error('获取UDID失败:', error);
      this.deviceUDID = 'ERROR: 权限不足或设备不支持';
    }
  }

  // 复制到剪贴板
  private copyToClipboard() {
    // 实际项目中需调用系统剪贴板API
    prompt.showToast({ message: 'UDID已复制到剪贴板', duration: 2000 });
    console.info('复制的UDID:', this.deviceUDID);
  }

  // 加载已保存的UDID
  private async loadSavedUDID() {
    try {
      const pref = await preferences.getPreferences(getContext(), 'deviceInfo');
      const savedUDID = await pref.get('udid', '');
      if (savedUDID) {
        this.deviceUDID = savedUDID.toString();
      }
    } catch (error) {
      console.error('读取UDID失败:', error);
    }
  }

  // 检查设备注册状态(模拟)
  private isDeviceRegistered(): boolean {
    // 实际项目需调用AGC接口验证
    return this.deviceUDID.length > 0 && this.deviceUDID !== 'ERROR: 权限不足或设备不支持';
  }
}

##HarmonyOS应用测试##商务##

收藏00

登录 后评论。没有帐号? 注册 一个。