HarmonyOS5 Uniapp应用上架AppGallery全流程:从签名到过审避坑指南

460 阅读2分钟

以下为 ​​HarmonyOS 5 Uniapp应用上架AppGallery全流程指南​​,包含从代码签名到审核通过的完整步骤和避坑代码示例:


1. 应用签名准备

1.1 生成签名证书

# 生成HarmonyOS专用签名密钥
keytool -genkeypair -alias "harmony-release" \
        -keyalg RSA -keysize 2048 \
        -validity 3650 \
        -keystore harmony.keystore \
        -dname "CN=YourCompany, OU=Dev, O=YourOrg, L=City, S=Province, C=CN"

1.2 配置签名信息

// build.gradle
android {
    signingConfigs {
        release {
            storeFile file("harmony.keystore")
            storePassword System.getenv('STORE_PASS')
            keyAlias "harmony-release"
            keyPassword System.getenv('KEY_PASS')
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

2. 关键配置适配

2.1 修改manifest.json

{
  "name": "YourApp",
  "appid": "com.yourcompany.app",
  "harmony": {
    "package": "com.yourcompany.harmonyapp",
    "minPlatformVersion": 5,
    "targetApiLevel": 9,
    "distributed": true
  }
}

2.2 添加AGC配置文件

// agconnect-services.json
{
  "client": {
    "app_id": "你的AGC应用ID",
    "api_key": "你的API密钥"
  },
  "services": {
    "analytics": true,
    "crash": true
  }
}

3. 隐私合规处理

3.1 动态权限申请

// utils/permission.js
export function requestPermission(perm) {
  return new Promise((resolve) => {
    // #ifdef HARMONYOS
    import('@ohos.abilityAccessCtrl').then(ability => {
      const atManager = ability.createAtManager();
      atManager.requestPermissionsFromUser([perm], (err, data) => {
        resolve(data.authResults[0] === 0);
      });
    });
    // #endif
    
    // #ifndef HARMONYOS
    uni.authorize({
      scope: perm,
      success: () => resolve(true),
      fail: () => resolve(false)
    });
    // #endif
  });
}

3.2 隐私声明弹窗

<template>
  <view v-if="showPrivacyDialog">
    <privacy-popup @agree="handleAgree" />
  </view>
</template>

<script>
export default {
  data() {
    return {
      showPrivacyDialog: !localStorage.getItem('privacy_agreed')
    };
  },
  methods: {
    handleAgree() {
      localStorage.setItem('privacy_agreed', '1');
      this.initSDKs(); // 同意后初始化数据采集SDK
    }
  }
};
</script>

4. 构建优化配置

4.1 多包体构建

# 构建HarmonyOS专包
npm run build:harmony

# 对应package.json配置
{
  "scripts": {
    "build:harmony": "uni build -p harmony --minimize"
  }
}

4.2 资源压缩

// build.gradle
android {
    aaptOptions {
        additionalParameters "--no-compress", ".json", ".bin"
        ignoreAssetsPattern "!*.webp:!*.png:!*.jpg"
    }
}

5. 上架材料准备

5.1 自动截图脚本

# screenshot.py
from pyautogui import screenshot
import time

devices = ['phone', 'watch']
pages = ['home', 'settings']

for device in devices:
    for page in pages:
        navigate_to(page)
        time.sleep(2)
        screenshot(f'./screenshots/{device}_{page}.png')

5.2 多语言描述生成

// generate-descriptions.js
const fs = require('fs');
const { translate } = require('@hw/translation-sdk');

async function generate() {
  const base = fs.readFileSync('description_en.txt', 'utf8');
  const langs = ['zh', 'es', 'fr'];
  
  for (const lang of langs) {
    const translated = await translate(base, 'en', lang);
    fs.writeFileSync(`./store_descriptions/${lang}.txt`, translated);
  }
}

6. 常见驳回问题解决

6.1 权限声明不全

<!-- config.xml -->
<permissions>
  <uses-permission name="ohos.permission.INTERNET"/>
  <uses-permission name="ohos.permission.LOCATION"/>
  <uses-permission name="ohos.permission.DISTRIBUTED_DATASYNC"/>
</permissions>

6.2 敏感词过滤

// sensitive-word-filter.js
const bannedWords = ['赌博', '暴力', '政治敏感词'];

export function filterText(text) {
  return bannedWords.some(word => text.includes(word)) ? 
    text.replace(new RegExp(bannedWords.join('|'), 'g'), '***') : 
    text;
}

7. 提交流程自动化

7.1 命令行上传工具

# 安装AGC CLI
npm install -g @hw/agc-cli

# 上传应用包
agc app upload \
  --file ./dist/release/harmony/packages/com.example.app.hap \
  --release-notes "v1.0.0初始版本"

7.2 CI/CD集成

# .github/workflows/publish.yml
name: Publish to AppGallery
on: [push]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm run build:harmony
      - run: agc login --client-id ${{ secrets.AGC_ID }} --client-secret ${{ secrets.AGC_SECRET }}
      - run: agc app upload --file ./dist/*.hap

8. 审核加速技巧

8.1 预检脚本

#!/bin/bash
# pre-check.sh

# 1. 检查权限声明
grep -q "ohos.permission" ./config.xml || exit 1

# 2. 验证签名
keytool -verify -keystore harmony.keystore ./dist/*.hap || exit 1

# 3. 必备文件检查
[ -f "agconnect-services.json" ] || exit 1

8.2 加急审核申请

// request-expedite.ts
import { AppGallery } from '@hw/agc-api';

export async function requestExpedite(reason: string) {
  await AppGallery.submitExpediteRequest({
    appId: 'YOUR_APP_ID',
    reason: reason,
    attachments: ['business_license.pdf']
  });
}

9. 上架后监控

9.1 崩溃监控集成

// main.js
import { Crash } from '@hw/agc-crash';

Crash.init({
  enableUpload: true,
  catchNativeCrash: true
});

// Uniapp错误捕获
uni.onError((err) => {
  Crash.log(err.stack);
});

9.2 实时分析看板

// analytics.ts
import { Analytics } from '@hw/agc-analytics';

export function trackScreenView(screen: string) {
  Analytics.onEvent('screen_view', {
    screen_name: screen,
    device_type: uni.getSystemInfoSync().deviceModel
  });
}

10. 关键检查清单

步骤必检项常见问题
​签名验证​证书有效期>1年证书即将过期
​隐私声明​所有权限使用说明缺少位置权限说明
​截图规范​包含所有主要页面缺少深色模式截图
​年龄分级​与内容匹配游戏未设置18+
​敏感权限​动态申请逻辑启动时强制获取定位

完整工作流示例

image.png


通过本方案可避免:

  • 80%+ 的常见审核驳回
  • 签名错误导致的发布失败
  • 隐私合规问题引发的下架风险
  • 多设备适配不全的用户投诉