阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 推送与通知(uni.push)

推送与通知(uni.push)

作者:陈川 阅读数:16959人阅读 分类: uni-app

uni.push 简介

uni.push 是 uni-app 提供的跨平台推送服务,支持 iOS、Android 和 Web 平台。它封装了各平台的原生推送能力,开发者只需调用统一 API 即可实现推送功能。uni.push 支持离线推送、本地通知、消息透传等多种场景,适用于消息提醒、营销推送、系统通知等需求。

推送服务配置

申请推送服务权限

使用 uni.push 前需要先在各个平台申请推送权限:

  1. iOS:在苹果开发者中心配置推送证书(开发和生产环境)
  2. Android:在各大厂商推送平台(华为、小米、OPPO、vivo等)申请应用密钥
  3. Web:使用浏览器通知 API(需用户授权)
// manifest.json 配置示例
{
  "app-plus": {
    "distribute": {
      "ios": {
        "push": {
          "production": true,
          "devCert": "dev.p12",
          "prodCert": "prod.p12"
        }
      },
      "android": {
        "push": {
          "HW": {
            "appid": "你的华为应用ID"
          },
          "XM": {
            "appid": "你的小米应用ID",
            "appkey": "你的小米应用密钥"
          }
        }
      }
    }
  }
}

客户端初始化

在应用启动时初始化推送服务:

// App.vue
export default {
  onLaunch() {
    uni.getPushClientId({
      success: (res) => {
        console.log('客户端推送标识:', res.cid)
        // 将 cid 发送到服务器保存
      },
      fail: (err) => {
        console.error('获取推送标识失败:', err)
      }
    })
    
    // 监听推送消息
    uni.onPushMessage((res) => {
      console.log('收到推送消息:', res)
      if (res.type === 'click') {
        // 用户点击通知栏消息
        this.handlePushClick(res)
      } else if (res.type === 'receive') {
        // 收到透传消息
        this.handlePushReceive(res)
      }
    })
  }
}

推送消息类型

通知栏消息

通知栏消息会显示在系统通知中心,用户点击后可以打开应用:

// 服务端推送示例(Node.js)
const push = require('uni-push')

push.send({
  platform: ['ios', 'android'],
  notification: {
    title: '新消息提醒',
    body: '您有3条未读消息',
    sound: 'default',
    badge: 3,
    extras: {
      path: '/pages/message/list',
      type: 'message'
    }
  },
  cid: ['客户端推送标识1', '客户端推送标识2']
})

透传消息

透传消息不会显示通知,直接传递给应用处理:

push.send({
  platform: ['ios', 'android'],
  message: {
    title: '静默消息',
    content: '{"action":"update","data":{"version":"1.2.0"}}',
    extras: {
      silent: true
    }
  },
  cid: ['客户端推送标识']
})

本地通知

应用内触发本地通知,无需服务器参与:

uni.createPushMessage({
  title: '本地通知',
  content: '这是一条本地生成的通知',
  delay: 5, // 5秒后显示
  sound: 'default',
  extras: {
    path: '/pages/home/index'
  },
  success: () => {
    console.log('本地通知创建成功')
  }
})

消息处理与跳转

处理推送点击

methods: {
  handlePushClick(res) {
    const extras = res.data.extras || {}
    if (extras.path) {
      // 跳转到指定页面
      uni.navigateTo({
        url: extras.path
      })
    }
    
    // 根据消息类型处理业务逻辑
    switch(extras.type) {
      case 'message':
        this.updateUnreadCount()
        break
      case 'order':
        this.fetchLatestOrder()
        break
    }
  }
}

消息到达统计

// 统计消息到达率
uni.reportPushMsgArrival({
  msgid: res.data.msgid,
  success: () => {
    console.log('消息到达上报成功')
  }
})

高级功能

标签与别名管理

// 设置用户别名(替代CID)
uni.setPushAlias({
  alias: 'user123',
  success: () => {
    console.log('别名设置成功')
  }
})

// 添加标签
uni.addPushTag({
  tags: ['vip', 'shanghai'],
  success: () => {
    console.log('标签添加成功')
  }
})

定时推送

// 服务端设置定时推送
push.send({
  notification: {
    title: '每日提醒',
    body: '记得完成今日任务'
  },
  cid: ['客户端推送标识'],
  time: '2023-12-31 20:00:00' // 指定发送时间
})

富媒体通知

// Android 大图通知
push.send({
  platform: ['android'],
  notification: {
    title: '新品上市',
    body: '点击查看详情',
    style: {
      type: 1, // 大图样式
      bigText: '...',
      bigPicPath: 'https://example.com/banner.jpg'
    }
  }
})

常见问题处理

推送权限检查

uni.checkPushPermission({
  success: (res) => {
    if (!res.result) {
      // 引导用户开启通知权限
      this.showPermissionDialog()
    }
  }
})

厂商通道适配

// 处理不同厂商的兼容性问题
if (uni.getSystemInfoSync().platform === 'android') {
  // 华为设备特殊处理
  if (uni.getSystemInfoSync().brand === 'HUAWEI') {
    this.adjustForHuawei()
  }
  // 小米设备特殊处理
  else if (uni.getSystemInfoSync().brand === 'Xiaomi') {
    this.adjustForXiaomi()
  }
}

推送性能优化

// 合并同类消息
let lastMessageTime = 0
uni.onPushMessage((res) => {
  const now = Date.now()
  if (now - lastMessageTime < 1000) {
    // 1秒内收到多条消息,合并处理
    this.batchUpdate()
    return
  }
  lastMessageTime = now
  // 正常处理
})

推送策略设计

用户分群推送

// 根据用户行为推送不同内容
function getUserGroup(user) {
  if (user.lastLogin < Date.now() - 30*24*60*60*1000) {
    return 'inactive'
  } else if (user.orderCount > 5) {
    return 'vip'
  } else {
    return 'normal'
  }
}

const group = getUserGroup(currentUser)
push.send({
  notification: {
    title: group === 'inactive' ? '好久不见' : '专属优惠',
    body: group === 'vip' ? '会员专属折扣' : '新用户福利'
  },
  cid: [currentUser.cid]
})

A/B 测试实现

// 随机分组推送
const variant = Math.random() > 0.5 ? 'A' : 'B'
const message = {
  A: {
    title: '限时折扣',
    body: '全场5折起'
  },
  B: {
    title: '新品上市',
    body: '立即抢购'
  }
}

push.send({
  notification: message[variant],
  extras: {
    variant: variant
  },
  cid: [user.cid]
})

数据统计与分析

推送效果追踪

// 跟踪用户行为
uni.onPushMessage((res) => {
  if (res.type === 'click') {
    const extras = res.data.extras || {}
    reportAnalytics('push_click', {
      msgid: res.data.msgid,
      type: extras.type,
      variant: extras.variant
    })
  }
})

推送报表生成

// 服务端统计代码示例
async function generatePushReport(startDate, endDate) {
  const stats = await PushLog.aggregate([
    {
      $match: {
        createdAt: { $gte: startDate, $lte: endDate }
      }
    },
    {
      $group: {
        _id: '$campaign',
        sent: { $sum: 1 },
        arrived: { $sum: { $cond: [{ $eq: ['$arrived', true] }, 1, 0] } },
        clicked: { $sum: { $cond: [{ $eq: ['$clicked', true] }, 1, 0] } }
      }
    }
  ])
  
  return stats.map(item => ({
    campaign: item._id,
    arrivalRate: (item.arrived / item.sent * 100).toFixed(2) + '%',
    clickThroughRate: (item.clicked / item.arrived * 100).toFixed(2) + '%'
  }))
}

安全与权限控制

推送内容审核

// 服务端内容过滤
function filterPushContent(content) {
  const bannedWords = ['敏感词1', '敏感词2']
  for (const word of bannedWords) {
    if (content.includes(word)) {
      throw new Error('推送内容包含敏感词')
    }
  }
  return content
}

用户退订处理

// 退订管理
uni.getPushSetting({
  success: (res) => {
    if (!res.notificationEnabled) {
      // 用户关闭了通知
      this.showReEnableDialog()
    }
  }
})

// 退订特定类型消息
uni.subscribePush({
  topic: 'promotion',
  subscribe: false, // 取消订阅
  success: () => {
    console.log('已取消订阅营销消息')
  }
})

多平台差异处理

iOS 特殊配置

// 处理 iOS 推送限制
if (uni.getSystemInfoSync().platform === 'ios') {
  // 请求通知权限
  uni.requestPushPermission({
    success: (res) => {
      if (res.result) {
        console.log('已获得推送权限')
      }
    }
  })
  
  // 处理角标清零
  uni.setPushBadge({
    badge: 0
  })
}

Web 平台适配

// Web 平台通知处理
if (process.env.VUE_APP_PLATFORM === 'h5') {
  // 检查浏览器通知支持
  if (!('Notification' in window)) {
    console.log('该浏览器不支持通知')
  } else if (Notification.permission === 'granted') {
    // 已授权
  } else if (Notification.permission !== 'denied') {
    // 请求权限
    Notification.requestPermission().then(permission => {
      if (permission === 'granted') {
        new Notification('欢迎回来')
      }
    })
  }
}

调试与问题排查

推送日志记录

// 客户端日志记录
uni.onPushMessage((res) => {
  console.log('推送消息详情:', JSON.stringify(res))
  this.savePushLog(res)
})

// 保存推送记录
savePushLog(pushData) {
  const logs = uni.getStorageSync('push_logs') || []
  logs.unshift({
    time: new Date().toISOString(),
    data: pushData
  })
  uni.setStorageSync('push_logs', logs.slice(0, 100)) // 保留最近100条
}

常见错误处理

// 错误处理示例
uni.getPushClientId({
  fail: (err) => {
    switch(err.code) {
      case 10001:
        console.error('推送服务未初始化')
        break
      case 10002:
        console.error('设备不支持推送')
        break
      default:
        console.error('未知错误', err)
    }
  }
})

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌