华为应用市场审核要求 manifest.json 中 distribute.android.permissions 必须准确填写定位、相机、录音等必要权限,禁止使用已废弃权限(如 READ_EXTERNAL_STORAGE),targetSdkVersion 必须为数字33且与 build.gradle 一致,permissionPhoneState.prompt 等字段不能为空,隐私政策需 HTTPS 可访问并严格对应权限用途。

manifest.json 里哪些权限字段必须填,填错会直接驳回
华为应用市场会静态扫描 AndroidManifest.xml,而 uni-app 的安卓权限最终都来自 manifest.json 的 distribute.android.permissions 数组。漏写、错写、多写都会触发自动化检测失败。
常见错误包括:"<uses-permission android:name='\"android.permission.READ_PHONE_STATE\"/'>"</uses-permission> 写成 "READ_PHONE_NUMBERS"(后者是 Android 8+ 新权限,华为不认);或把 WRITE_EXTERNAL_STORAGE 和 READ_EXTERNAL_STORAGE 混用在 Android 11+ 上——其实从 targetSdkVersion ≥ 30 起,这两个权限已废弃,应改用 MANAGE_EXTERNAL_STORAGE(但华为对这个权限审核极严,除非真需要访问全部媒体文件,否则别申)。
- 必须声明但常被遗漏的:
"<uses-permission android:name='\"android.permission.ACCESS_FINE_LOCATION\"/'>"</uses-permission>(定位)、"<uses-permission android:name='\"android.permission.CAMERA\"/'>"</uses-permission>(相机)、"<uses-permission android:name='\"android.permission.RECORD_AUDIO\"/'>"</uses-permission>(录音) - 声明了但代码里没调用?也会被标记“权限冗余”,人工复审时可能质疑用途
- 第三方 SDK 自动引入的权限(如个推、友盟)需在
distribute.android.permissionPhoneState.request等字段中显式配置,否则算“隐式申请”
uni.authorize 调用前必须加自定义弹窗,且不能自动关闭
华为审核员会手动点开你的 App,看你在调用 uni.authorize({ scope: 'scope.userLocation' }) 前,是否弹出了一个用户可操作的说明弹窗。系统原生弹窗不算,uni.showModal 弹窗也不能设 showCancel: false 或 duration: 2000 自动消失——这会被判定为“诱导授权”。
正确做法是封装一个通用权限提示函数,比如 showPermissionTip('location'),内部用 uni.showModal 显示标题和内容,并只保留“去设置”和“取消”按钮。点击“去设置”再调用 uni.authorize;点击“取消”则记录拒绝状态,后续不再重复弹。
- 弹窗文案必须含三要素:权限名称(如“位置信息”)、具体功能(如“查找附近门店”)、使用场景(如“仅在您点击‘找店’按钮时使用”)
- 不能出现“用于提升用户体验”“优化服务”等模糊表述
- 如果用户之前拒绝过,再次进入同一页面时,要跳过弹窗直接引导至系统设置页(用
uni.openSetting)
targetSdkVersion 必须 ≥ 33,且 manifest.json 和 build.gradle 要一致
华为当前(2026年10月)强制要求 targetSdkVersion ≥ 33。这个值不是只改 manifest.json 就行——它最终要落到生成的 build.gradle 里。uni-app 在 HBuilderX 中打包时,会读取 manifest.json 的 app-plus.distribute.android.targetSdkVersion 字段,但如果你手动修改过 build.gradle 或用了自定义基座,这里就容易不一致。
检查方法:解压生成的 APK,打开 AndroidManifest.xml,搜索 targetSdkVersion;再对比 build.gradle 里的 targetSdk。两者必须完全相等,否则审核直接卡在“目标版本不合规”。
- uni-app 官方推荐写法:
"targetSdkVersion": 33(数字,非字符串) - 不要写成
"33"(字符串类型),HBuilderX 可能无法识别 - 升级到 33 后,
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE默认失效,需改用分区存储逻辑或申请MANAGE_EXTERNAL_STORAGE(慎用)
隐私政策链接必须可访问,且内容与权限声明严格对应
华为审核员会点开你提交的隐私政策 URL,逐条比对:网页里写的“我们收集设备标识符用于反作弊”,就必须在 manifest.json 里配置 permissionPhoneState.prompt,且文案高度一致;如果网页写了“收集位置用于导航”,但代码里只在首页调用了 uni.getLocation 却没配位置权限说明字段,就会被认定为“声明与实际不符”。
最稳妥的做法是把所有权限用途说明统一收口到一个 JS 配置对象里,再同时用于弹窗文案、manifest 声明、隐私政策网页文本——避免一处改、多处漏。
-
permissionPhoneState.prompt字段必须存在,且不能为空字符串或占位符(如“xxx”) - 隐私政策网页必须是 HTTPS,且响应时间
- 网页中不得出现“可能收集”“将用于”等不确定性措辞,要用肯定语气:“用于提供设备识别和安全性校验”
真正卡住人的从来不是某个配置项写不对,而是多个环节之间存在隐性依赖:比如 targetSdkVersion 升级后,READ_EXTERNAL_STORAGE 不再生效,但你的弹窗文案还写着“读取相册”,这就导致文案与行为脱节。这种链路级问题,往往要连着看 manifest、JS 权限调用、隐私政策网页、APK 实际声明四者才能定位。



















