作为一名长期从事移动端开发的工程师,最近在uni-app项目中集成JPush(极光推送)时遇到了一个棘手问题:华为设备在应用离线状态下无法接收推送通知。经过反复排查和测试,最终发现这与华为厂商通道的特殊机制有关,特别是"自分类权益"的配置问题。
典型现象表现为:
提示:华为设备对离线推送有严格的分类管理机制,未正确配置"自分类权益"的应用将被系统限制离线推送能力。
华为设备使用自家的HMS Push服务作为系统级推送通道,与标准安卓的FCM机制不同。其核心特点包括:
华为定义的11种消息分类中,每种都有不同的系统限制:
| 分类ID | 分类名称 | 每日限额 | 展示限制 | 适用场景 |
|---|---|---|---|---|
| IM | 即时通讯 | 无限制 | 无 | 聊天消息 |
| VOIP | 网络电话 | 无限制 | 无 | 语音/视频通话 |
| WORK | 工作事项 | 500条/日 | 无 | 任务提醒、审批通知 |
| MARKETING | 营销活动 | 1条/日 | 折叠展示 | 促销广告 |
关键发现:未申请"自分类权益"的应用,系统默认将其归类为"MARKETING"类型,导致严格限制。
申请自分类权益:
配置推送参数:
javascript复制// 华为通道专属配置
const HUAWEI_CATEGORY_MAP = {
WORK: 'WORK', // 工作事项分类
SYSTEM_REMINDER: 'SYSTEM_REMINDER' // 系统提醒
};
androidNotification.android.category = HUAWEI_CATEGORY_MAP.WORK;
在原有极光推送代码基础上,需要增加华为通道的特殊处理:
javascript复制// controllers/jpush/vendorConfig.js
const VENDOR_CONFIG_MAP = {
huawei: (payload, category, androidNotification) => {
const huaweiCategory = HUAWEI_CATEGORY_MAP[category] || 'SYSTEM_REMINDER';
// 必须设置的华为专属参数
androidNotification.android.badge_add_num = 1;
androidNotification.android.badge_class = 'io.dcloud.PandoraEntry';
androidNotification.android.category = huaweiCategory;
return {
category: huaweiCategory,
importance: huaweiCategory === 'MARKETING' ? 'LOW' : 'NORMAL',
target_user_type: 0 // 0表示测试/生产环境都可用
};
}
};
在manifest.json中确保已正确配置华为渠道:
json复制{
"app-plus": {
"distribute": {
"android": {
"permissions": [
"<uses-permission android:name=\"com.huawei.android.launcher.permission.CHANGE_BADGE\"/>"
],
"huawei": {
"appid": "你的华为应用ID"
}
}
}
}
}
未申请自分类权益
分类不匹配
category参数与申请的分类一致每日限额超限
华为推送调试命令:
bash复制adb shell setprop log.tag.hwpush VERBOSE
adb logcat -v time -s HwPush
极光推送状态查询:
javascript复制// 在推送回调中检查华为通道返回
client.push().send().then(res => {
console.log(res.huawei_status); // 应返回"success"
});
多分类混合策略:
javascript复制// 根据消息类型动态选择分类
function getHuaweiCategory(messageType) {
switch(messageType) {
case 'urgent': return 'IM';
case 'work': return 'WORK';
default: return 'SYSTEM_REMINDER';
}
}
离线消息缓存:
javascript复制plus.push.addEventListener('receive', function(msg) {
localStorage.setItem('last_push', msg.content);
});
厂商通道降级方案:
javascript复制// 当华为通道失败时尝试极光自有通道
const sendWithFallback = async (payload) => {
try {
await client.push(payload).send();
} catch (huaweiError) {
payload.options.third_party_channel = null;
await client.push(payload).send();
}
};
在实际项目中,我们通过这套方案成功将华为设备的离线推送到达率从0%提升至98%以上。特别需要注意华为分类的日限额问题,对于高频推送场景建议申请多个分类组合使用。