iOS灵动岛实时活动推送

iOS灵动岛实时活动推送

iOS16.1开始允许开发者和灵动岛交互。引入新概念Live Activity 实时活动,我们简称LA。
iOS17.2开始允许通过APNs启动 Live Activity。

应用场景:

1.重要通知(新闻类):

  • 通常需要在第一时间收到一手消息。
  • 可以在重大突发新闻事件发生时立即通知用户,即使他们的应用没有打开,也能第一时间收到信息。

2.沉默用户唤醒

(1)体育类比赛:向用户推送一个他可能感兴趣的并且正在直播的一场重大的体育比赛,用户可以不用打开 App 也能获得实时的比赛得分,并且只需要轻轻点击即可迅速打开应用内的直播比赛页面;

(2)交易类:当某个用户关注的股票或加密货币出现重大波动时,实时通知用户当前的市场动态和交易机会;

(3)游戏类:实时通知用户某个他们关注的游戏赛事即将开始,或当前有特别的游戏内活动和奖励。

一、开发者如何添加Live Activity

1 Info.plist 增加 Key NSSupportsLiveActivities, Value为YES
2 创建target widget
3 开发自定义交互的UI
4 在App中进行LA的启动、更新、终止

启动LiveActivity后,锁屏页 或者 通知栏页中 将展示实时活动视图

img

二、客户端通过App启动、更新、终止Live Activity

启动Live Activity

do {
      //启动LA
    let current = try Activity.request(attributes: attri, contentState: state, pushType: .token)
        //设置监听
    Task {
        //监听内容数据状态变化, contentState是视图对应的数据模型
        //1.远程通知更新内容(没有远程通知回调)  2.App代码更新内容
        for await state in current.contentStateUpdates {
            print("content state update: tip=\(state.prograssState)")
        }
    }
    Task {
        //监听视图的声明周期,状态变化:active,end,dismissed等
        //1.在锁屏页上手动删除LA通知  2.代码关闭LA 3.设置关闭LA权限   都将触发回调,state=dismissed
        for await state in current.activityStateUpdates {
            print("activity state update: tip=\(state) id:\(current.id)")
        }
    }
 } catch(let error) {
    //当灵动岛个数超过限制时, error=targetMaximumExceeded
    print("error=",error)
}

更新Live Activity

let state = MyWidgetAttributes.ContentState(prograssState: state)

let alertConfiguration = AlertConfiguration(title: "Delivery Update ", body: "Delivery Update State to \(state.prograssState.desc())", sound: .default)

//更新实时活动视图内容,同时发起一条本地通知
await current.update(using: state, alertConfiguration: alertConfiguration)

//仅更新实时活动视图内容
await current.update(using: state, alertConfiguration: nil)

终止Live Activity

await current.end(dismissalPolicy:.immediate)

三、通过APNs更新Live Activity

推送生命周期:
App进入前台,发起本地创建LA,获取当前LA的pushToken,上传个推服务器后进行推送。

获取pushToken

do {
        //创建LA
    let current = try Activity.request(attributes: attri, contentState: state, pushType: .token)

    //监听回调
    Task {
        //监听PushToken变化
        for await tokenData in current.pushTokenUpdates {
            let mytoken = tokenData.map { String(format: "%02x", $0) }.joined()
            print("activity push token", mytoken)
        }
    }
 } catch(let error) {
    //当灵动岛个数超过限制时, error= targetMaximumExceeded
    print("error=",error)
}
服务端更新/结束LA接口说明

开发者可通过 设置ios厂商通道消息 来更新/结束灵动岛,示例如下:

"ios": {
  "type": "liveactivity",
  "laId": "myLA",
  "payload": "ios透传@timestamp",
  "aps": {
    "timestamp": 1730702910,
    "dismissal-date": 1630702910,
    "event": "update",
    "content-state": {
      "prograssState": 2,
      "name": "myLA"
    },
    "alert": {
      "title": "ios标题@timestamp",
      "body": "ios内容@timestamp"
    },
    "content-available": 0
  },
  "auto_badge": "+1"
}

参数设置注意事项:

  • type:推送灵动岛消息时,传入的类型必须为liveactivity
  • laId:更新/结束灵动岛时必传,laId需要与创建灵动岛时的liveActivityId值保持一致
  • timestamp:必传,需要传入当前时间,秒级10位时间戳
  • dismissal-date:非必传,event 为end,且需要按时关闭实时活动时才填写
  • event:必传,更新灵动岛时,需要传入update;结束灵动岛时,需要传入end
  • content-state:必传,灵动岛推送透传参数,Json内的kv由业务方自定义


四、通过APNs启动Live Activity

iOS>=17.2开始允许通过APNs启动Live Activity。注意当前功能仅仅是启动LA,若要通过APNs更新LA还需要根据上述获取当前LA的pushToken来更新。

开发者需要在App启动后第一时间获取pushToStartToken,用于推送启动Live Activity。

if #available(iOS 17.2, *) {
    let startTokenData = Activity<MyWidgetAttributes>.pushToStartToken

    if let token = startTokenData {
        let startToken = String(data: token, encoding: .utf8)
        NSLog("Activity startToken=\(String(describing: startToken))")
         //TODO: 开发者上传现有的pushToStartToken
    }

    //pushToStartToken为空。App创建LA时,会触发下面的回调。可以拿到pushToStartToken
    Task {
        for await tokenData in Activity<MyWidgetAttributes>.pushToStartTokenUpdates {
            //监听token更新 注意线程
            let mytoken = tokenData.map { String(format: "%02x", $0) }.joined()
            NSLog("Activity startToken=\(mytoken) ")
            //TODO: 开发者上传变更后的startToken
        }
    }
} else {
    // Fallback on earlier versions
} 

注:如果一直无法获取pushToStartToken,可以尝试App本地创建灵动岛后再试

pushToStartToken是和ActivityAttributes绑定的,即FirstActivityAttributes可获取pushToStartToken1,SecondActivityAttributes可获取pushToStartToken2, pushToStartToken1可能和pushToStartToken2是不同的。

服务端创建LA接口说明

开发者可通过 设置ios厂商通道消息 来创建灵动岛,示例如下:

    "ios": {
      "type": "liveactivity",
      "aps": {
        "timestamp": 1730701651,
        "event": "start",
        "attributes-type": "MyWidgetAttributes",
        "attributes": {
          "prograssState": 0,
          "name": "myLA"
        },
        "content-state": {
          "prograssState": 0,
          "name": "myLA"
        },
        "alert": {
          "title": "ios标题@timestamp",
          "body": "ios内容@timestamp"
        },
        "content-available": 0
      },
      "auto_badge": "+1"
    }

参数设置注意事项:

  • type:推送灵动岛消息时,传入的类型必须为liveactivity
  • timestamp:必传,需要传入当前时间,秒级10位时间戳
  • event:必传,创建灵动岛时,需要传入start
  • attributes-type:创建灵动岛时必传,对应客户端调用
    + (BOOL)registerLiveActivity:(NSString *)activityAttributes pushToStartToken:(NSString*)pushToStartToken sequenceNum:(NSString*)sn; 方法的activityAttributes值
  • attributes:创建灵动岛时必传,灵动岛推送透传参数,Json内的kv由业务方自定义
  • content-state:必传,灵动岛推送透传参数,Json内的kv由业务方自定义

五、使用场景

1.App打开时,APNs启动LA,会触发系统回调, 可以获取对应的pushToken。

2.App杀死时,会拉活App,可以获取当前LA列表。可以获取对应的pushToken。大概可以存活一定时长。

因此App启动后,开发者需要第一时间接收LA的pushToken,并上报给个推,以便后续对LA进行更新。

该视频演示了使用pushToStartToken启动LA后,使用pushToken更新状态

六、灵动岛常见问题FAQ

Q1:服务推送灵动岛消息时,提示“strategy is invalid”是什么原因

  • 个推后台看下一下vip权限是否开启,没有vip权限无法配置 strategy 参数
  • 检查一下传入的cid是否正确,以及服务端创建(start)灵动岛时对应cid客户端是否有注册LiveActivity PushToStartToken 上报
  • 检查一下传入的cid是否正确,以及服务端更新(update)灵动岛时对应cid客户端是否有activityToken(灵动岛token)上报

Q2:服务端更新(update)灵动岛,为什么灵动岛ui界面没有变化

  • 检查ios客户端有没有activityToken(灵动岛token)上报,只有上报了才能更新灵动岛
  • 检查服务端参数timestamp是否是传入的当前最新时间,间隔过久不会触发灵动岛更新
  • 检查服务端传的content-state参数是否和客户端完全一样,只有完全一样一一对应才能更新灵动岛,建议前期调试的时候只传1-2个参数去验证功能。

Q3:服务端更新(update)灵动岛的时候,移动端页面没有弹窗提醒,仅仅数据刷新

  • 如果服务端接口不设置alert或者alert中的body未设置,会无提醒弹出仅仅静默更新灵动岛内容
开发者中心 SDK 下载

文档中心搜索

技术
咨询

微信扫一扫

随时联系技术支持

在线
咨询