iOS16 灵动岛 Dynamic Island(实时活动 Live Activity)

什么是LiveActivity

LiveActivity中文翻译就是实时活动,是一种可以脱离App展示实时信息的能力,样式类似于传统的通知,但是相比于通知可以展示的信息更为丰富,对于含有”灵动岛“的机型,如iPhone14 Pro、iPhone14 Pro Max,实时活动可以常驻于”灵动岛“上(Apple给灵动岛赋予的英文名称是“Dynamic Island”)。点击后可以跳转至App内指定链接,长按会变为扩展状态。

灵动岛机型展示

灵动岛的三种状态多个实时活动

从左至右分别为含灵动岛机型实时活动的四种状态:
锁屏状态灵动岛缩小状态灵动岛展开态灵动岛缩小状态时展示两个活动

不含灵动岛机型展示

非灵动岛

从左至右分别为不含灵动岛机型实时活动的两种状态:

锁屏非锁屏(Banner)

系统限制

运行条件

系统

iOS 16.1+

设备:

  • 实时活动:iPhone+iPad

  • 灵动岛:含有灵动岛的机型

 

展示时间

灵动岛上

  1. 时长:至多8h

  2. 消失条件:

  • < 8h,用户手动终止

  • >=8h,系统将其从灵动岛移除

锁屏页面

  1. 时长:至多12h

  2. 消失条件:

  • < 12h,用户手动终止

  • >=12h,系统将其从锁屏页面移除

实时活动的能力

  1. 不支持网络请求

  2. 不支持感知定位变化

  3. 数据更新

  • App内使用Activity.framework更新

  • 通过接收push更新数据

  1. 接收数据大小限制:一次4KB

与Widget(小组件)异同点

相同点

  1. 都使用Widget Extension承载

不同点

  1. 更新方式
  • Widget:使用Timeline更新

  • LiveActivity:使用ActivityKit + remote push

开发

开发注意事项

  1. 可以新建一个WidgetExtension,也可以在已有的WidgetExtension中新增一个LiveActivity

  2. 在主工程的Info.plist中增加”Supports Live Activities”

  3. ActivityKit只支持Swift调用,WidgetExtension只能使用SwiftUI编写,如果主工程是OC需要在主工程建一个swift文件使用ActivityKit相关API来调用实时活动相关能力

  4. 在系统设置中,每个App都含有一个独立实时活动开关,用户开启/关闭,App不会收到回调,所以需要在调用ActivityKit API时,检测一下areActivitiesEnabled这个字段的值是否为true

  5. 做好错误处理

UI区域大小

灵动岛上

  1. compact
    灵动岛缩小状态,单个实时活动,分别支持leading、trailing各显示一段内容

缩小

  1. minimal
    灵动岛缩小状态,多个实时活动,支持两个实时活动在leading、trailing分别展示,中间分割

缩小

  1. expanded
    灵动岛展开态,展示单个实时活动,支持展示内容区域为leading、center、bottom、right,每个区域展示内容的大小并不是固定的,可以通过priority属性调节各个区域之间挤压的状态

展开

  1. 展开状态的高度限制
    160PT,超出后被系统截断

非灵动岛上

锁屏状态与顶部展示(Banner)样式是一致的,可以理解为一个SwiftUI编写的自定义的大小固定的View

点击跳转

  1. 整个实时活动
    使用WidgetURL跳转

  2. 实时活动中的独立区域
    使用Link跳转

启动&更新&隐藏

  1. 通过ActivityKit调用
    由每个LiveActivity实例调用
  • 启动:

    static func request(
    attributes: Attributes,
    contentState: Activity<Attributes>.ContentState,
    pushType: PushType? = nil
    ) throws -> Activity<Attributes>
  • 更新:

    func update(using contentState: Activity<Attributes>.ContentState) async
  • 结束

    func end(
    using contentState: Activity<Attributes>.ContentState? = nil,
    dismissalPolicy: ActivityUIDismissalPolicy = .default
    ) async
  1. 通过remote push notification更新
    这个暂时没尝试,在LiveActivity生成后,获取该activity的pushToken,将该pushToken上传至服务端,由服务端发送push来更新、结束这个LiveActivity