GetuiPush.ets 12 KB
import { common, Want } from '@kit.AbilityKit';
import PushManager, {
  BindAliasCmdMessage,
  GTCmdMessage, GTNotificationMessage, GTTransmitMessage, PushConst,
  SetTagCmdMessage,
  Tag,
  UnBindAliasCmdMessage } from 'library';
import { AppUtils, DeviceUtil, EmitterEventId, EmitterUtils, Logger, SPHelper } from 'wdKit/Index';
import { HostEnum, HostManager, HttpBizUtil, HttpUrlUtils, HttpUtils, ResponseDTO } from 'wdNetwork/Index';
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { SpConstants } from 'wdConstant/Index';
import { PushContentBean, PushContentParser } from './PushContentParser';

const TAG = "GetuiPush"

export class GetuiPush {

  private static GETUI_APPID_ONLINE = "sMkzgp09Ov82nU1MGk7Ae6"
  private static GETUI_APPID_TEST = "ZMi5AAXYHE84VN9p55YpW2"

  private readonly ALIAS_SN_USERID = "userID"
  private readonly TAG_SN_TAG = "tag1"
  private readonly TAG_PD_ZH = "peopledaily_zh"

  private cid: string = ""
  private deviceToken: string = ""
  private currentUserId = ""
  private lastPushContent?: PushContentBean

  private initialed = false

  private constructor() {
  }

  private static manager: GetuiPush
  static sharedInstance() : GetuiPush {
    if (!GetuiPush.manager) {
      GetuiPush.manager = new GetuiPush()
    }
    return GetuiPush.manager
  }

  init(context: common.UIAbilityContext) {

    const isOnlineEnv = HostManager.getHost() === HostEnum.HOST_PRODUCT

    PushManager.initialize({
      appId:isOnlineEnv ? GetuiPush.GETUI_APPID_TEST : GetuiPush.GETUI_APPID_TEST,
      context: context,
      onSuccess: (cid:string) => {
        Logger.debug(TAG, "个推SDK初始化成功,cid = " + cid)
        this.initialed = true
        this.cid = cid
        this.registerEvents()
        this.checkSetup()
      },
      onFailed: (error:string) => {
        Logger.error(TAG, "个推SDK初始化失败,error = " + error)
      }
    })
  }

  async requestEnableNotifications(context: common.UIAbilityContext) : Promise<boolean> {
    let enabled = await notificationManager.isNotificationEnabled()
    if (!enabled) {
      try {
        await notificationManager.requestEnableNotification(context)
        enabled = true
      } catch (err) {
        Logger.error(TAG, "请求通知权限报错: " + JSON.stringify(err))
        let error = err as BusinessError
        if (error.code == 1600004) {
          Logger.error(TAG, "请求通知权限 - 用户已拒绝")
        }
      }
    }
    Logger.info(TAG, "推送 enabled " + enabled)
    return enabled
  }

  checkSetup() {
    if (!this.initialed) { return }
    if (HttpUtils.isLogin()) {
      const userId = SPHelper.default.getSync(SpConstants.USER_ID, "") as string
      this.currentUserId = userId
      this.setAlias(true, userId)
    }
    let tags = [this.TAG_PD_ZH, AppUtils.getAppVersionCode()]
    this.setTags(tags)
  }

  // 默认是开启的
  switchPush(turnOn: boolean) {
    turnOn ? PushManager.turnOnPush() : PushManager.turnOffPush()
  }

  registerEvents() {

    // 登录和退出
    EmitterUtils.receiveEvent(EmitterEventId.LOGIN_SUCCESS, () => {
      const userId = SPHelper.default.getSync(SpConstants.USER_ID, "") as string
      this.currentUserId = userId
      this.setAlias(true, userId)
    })
    EmitterUtils.receiveEvent(EmitterEventId.FORCE_USER_LOGIN_OUT, () => {
      if (this.currentUserId.length) {
        this.setAlias(false, this.currentUserId)
      }
    })

    PushManager.setPushCallback({
      // cid
      onReceiveClientId: (clientId: string) => {
        Logger.debug(TAG, "推送 接收到 clientId = " + clientId)
        this.cid = PushManager.getClientId()
        SPHelper.default.save(SpConstants.GETUI_PUSH_CID, this.cid)
        this.uploadPushInfo(this.cid)
      },
      //接收⼚商token
      onReceiveDeviceToken: (deviceToken:string) => {
        Logger.debug(TAG, "推送 deviceToken = " + deviceToken)
        this.deviceToken = deviceToken;
        SPHelper.default.save(SpConstants.GETUI_PUSH_DEVICE_TOKEN, this.deviceToken)
      },
      // cid 离线上线通知
      onReceiveOnlineState: (onLine:boolean) => {
        Logger.debug(TAG, "推送 onLine State = " + onLine)
      },
      //命令相应回复
      onReceiveCommandResult: (result: GTCmdMessage) => {
        Logger.debug(TAG, "推送 Cmd Message = " + JSON.stringify(result))
        this.dealWithCmdMessage(result)
      },
      //sdk 收到透传消息
      onReceiveMessageData: (message: GTTransmitMessage) => {
        Logger.debug(TAG, "推送 透传 Message = " + JSON.stringify(message))
        this.dealWithTransmitMessage(message)
      },
      //通知到达回调
      onNotificationMessageArrived: (message: GTNotificationMessage) => {
        Logger.debug(TAG, "推送 通知到达回调 " + JSON.stringify(message))
      },
      //通知点击回调, 需要配合PushManager.setClickWant(want)使⽤
      onNotificationMessageClicked: (message: GTNotificationMessage) => {
        Logger.debug(TAG, "推送 通知 点击 回调 " + JSON.stringify(message))
      },
    })
  }

  setAlias(bind: boolean, alias: string, sn: string = this.ALIAS_SN_USERID) {
    if (typeof alias == "number") {
      alias = `${alias}`
    }
    if (!this.initialed) { return }
    if (bind) {
      Logger.debug(TAG, "推送 绑定别名 " + alias)
      PushManager.bindAlias(alias, sn)
    } else {
      Logger.debug(TAG, "推送 解绑别名 " + alias)
      PushManager.unBindAlias(alias, true, sn)
    }
  }

  setTags(tags: string[], sn: string = this.TAG_SN_TAG) {
    if (!this.initialed) { return }
    Logger.debug(TAG, "推送 设置标签 " + tags)
    PushManager.setTag(tags.map((tag) => {
      return new Tag().setName(tag)
    }), sn)
  }

  setBadgeNumber(number: number) {
    Logger.debug(TAG, "推送 设置角标 " + number)
    PushManager.setBadgeNum(number)
  }

  // 接收推送数据,包括启动和二次点击拉起
  // 参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/push-dev-0000001727885258
  onWant(want: Want) {
    this.onNewWant(want, true)
  }
  onNewWant(want: Want, startup: boolean = false) {
    Logger.debug(TAG, "want: " + JSON.stringify(want))

    this.lastPushContent = undefined
    let pushContent = PushContentParser.getPushLinkFromWant(want)
    if (pushContent && pushContent.isPush) {
      Logger.debug(TAG, "接收到推送: " + JSON.stringify(want.parameters))
      this.lastPushContent = pushContent
      if (this.initialed) {
        this.comsumeLastPushContent()
      }
    }
  }

  // 首次进入主页,即可解析跳转推送
  onReachMainPage() {
    if (this.initialed) {
      this.comsumeLastPushContent()
    } else {
      this.lastPushContent = undefined
    }
  }

  comsumeLastPushContent() {
    if (!this.lastPushContent) {
      return
    }
    if (this.lastPushContent.online) {
      if (this.lastPushContent.want) {
        Logger.debug(TAG, "推送 回执: " + this.lastPushContent.want)
        PushManager.setClickWant(this.lastPushContent.want)
      }
    }
    if (this.lastPushContent.pushLink) {
      Logger.debug(TAG, "跳转对应页面: " + this.lastPushContent.pushLink)
      PushContentParser.jumpWithPushLink(this.lastPushContent.pushLink)
    }
    this.lastPushContent = undefined
  }

  private dealWithCmdMessage(result: GTCmdMessage) {
    let action: Number = result.action;
    if (action === PushConst.BIND_ALIAS_RESULT) {
      let bindAliasCmdMessage = result as BindAliasCmdMessage;
      /* code 结果说明
       0:成功
       10099:SDK 未初始化成功
       30001:绑定别名失败,频率过快,两次调⽤的间隔需⼤于 1s
       30002:绑定别名失败,参数错误
       30003:当前 cid 绑定别名次数超限
       30004:绑定别名失败,未知异常
       30005:绑定别名时,cid 未获取到
       30006:绑定别名时,发⽣⽹络错误
       30007:别名⽆效
       30008:sn ⽆效 */
      let code = bindAliasCmdMessage.code
      if (code == 0) {
        Logger.debug(TAG, "推送 Cmd BindAlias 成功 " + bindAliasCmdMessage.sn)
      } else {
        Logger.debug(TAG, "推送 Cmd BindAlias 失败 "
          + ",sn = "+bindAliasCmdMessage.sn
          + ",clinetId = "+bindAliasCmdMessage.clientId
          + ",pkgname = "+bindAliasCmdMessage.pkgName
          + ",appId = "+bindAliasCmdMessage.appId
          + ",action = "+result.action
          + ",code ="+bindAliasCmdMessage.code)
      }
    } else if (action === PushConst.UNBIND_ALIAS_RESULT) {
      let unBindAliasCmdMessage = result as UnBindAliasCmdMessage
      /* code 结果说明
       0:成功
       10099:SDK 未初始化成功
       30001:解绑别名失败,频率过快,两次调⽤的间隔需⼤于 1s
       30002:解绑别名失败,参数错误
       30003:当前 cid 解绑别名次数超限
       30004:解绑别名失败,未知异常
       30005:解绑别名时,cid 未获取到
       30006:解绑别名时,发⽣⽹络错误
       30007:别名⽆效
       30008:sn ⽆效*/
      let code = unBindAliasCmdMessage.code
      if (code == 0) {
        Logger.debug(TAG, "推送 Cmd UnBindAlias 成功 " + unBindAliasCmdMessage.sn)
      } else {
        Logger.debug(TAG, "推送 Cmd UnBindAlias 失败 "
          + ",sn = "+unBindAliasCmdMessage.sn
          + ",clinetId = "+unBindAliasCmdMessage.clientId
          + ",pkgname = "+unBindAliasCmdMessage.pkgName
          + ",appId = "+unBindAliasCmdMessage.appId
          + ",action = "+result.action
          + ",code ="+unBindAliasCmdMessage.code)
      }
    } else if (action === PushConst.SET_TAG_RESULT) {
      let setTagCmdMessage = result as SetTagCmdMessage
      /* code 值说明
       0:成功
       10099:SDK 未初始化成功
       20001:tag 数量过⼤(单次设置的 tag 数量不超过 100)
       20002:调⽤次数超限(默认⼀天只能成功设置⼀次)
       20003:标签重复
       20004:服务初始化失败
       20005:setTag 异常
       20006:tag 为空
       20007:sn 为空
       20008:离线,还未登陆成功
       20009:该 appid 已经在⿊名单列表(请联系技术⽀持处理)
       20010:已存 tag 数⽬超限
       20011:tag 内容格式不正确 */
      let code = setTagCmdMessage.code
      if (code == 0) {
        Logger.debug(TAG, "推送 Cmd SetTag 成功 " + setTagCmdMessage.sn)
      } else {
        Logger.debug(TAG, "推送 Cmd SetTag 失败 "
          + ",sn = "+setTagCmdMessage.sn
          + ",clinetId = "+setTagCmdMessage.clientId
          + ",pkgname = "+setTagCmdMessage.pkgName
          + ",appId = "+setTagCmdMessage.appId
          + ",action = "+result.action
          + ",code ="+setTagCmdMessage.code)
      }
    }
  }

  private dealWithTransmitMessage(message: GTTransmitMessage) {
    // const taskid = message.taskId
    // const messageId = message.messageId
    // /* 上报个推透传消息的展示回执。如果透传消息本地创建通知栏消息“展示”了,则调⽤此⽅法上报。
    // */
    // int gtactionid = 60001;//gtactionid传⼊60001表示个推渠道消息展示了
    // boolean result = PushManager.sendFeedbackMessag(taskid, messageid, gtactionid);
    // /**
    //  * 上报个推透传消息的点击回执。如果透传消息本地创建通知栏消息“点击”了,则调⽤此⽅法上报。
    //  */
    // int gtactionid = 60002;//gtactionid传⼊60002表示个推渠道消息点击了
    // boolean result = PushManager.sendFeedbackMessage(taskid, messageid, gtactionid);
  }

  private uploadPushInfo(cid: string) {
    const url = HttpUrlUtils.getUploadPushInfoUrl()
    let bean: Record<string, string | number> = {}
    bean["deviceId"] = DeviceUtil.clientId()
    bean["cid"] = cid
    bean["userId"] = SPHelper.default.getSync(SpConstants.USER_ID, "") as string
    bean["appVersion"] = AppUtils.getAppVersionName()
    bean["platform"] = 3
    HttpBizUtil.post<ResponseDTO<string>>(url, bean).then((data) => {
      Logger.debug(TAG, "上传cid成功" + JSON.stringify(data))
    }).catch((e: BusinessError) => {
      Logger.debug(TAG, "上传cid失败" + JSON.stringify(e))
    })
  }
}