Dynamic Island灵动岛调研

1.背景

对于IoT行业,iPhone14 Pro及Max的灵动岛可以用于展示设备的各种动作和计时,在iPhone锁定屏幕和动态岛上显示App的最新数据,这让人们可以一目了然地看到实时信息。

2.名词解释

词汇 含义
1 Widget 组件,iOS 14 重磅推出的新功能,使得用户可以在主屏幕添加小组件,快速浏览 app 提供的重要信息
2 Dynamic Island 灵动岛,iOS16.1推出的针对iphone14 pro系列机型的联动功能,快速浏览 app 提供的重要信息
3 Live Activity 实时活动,展示在灵动岛和锁屏界面的信息活动

Dynamic Island是ActivitiesKit的一部分,而它是Widget Extension的一部分。

3.配置条件

  • 需要至少Xcode 14.1 Beta版及iOS16.1才能使用ActivityKit 框架,iOS16.1是第一个开放ActivityKit的正式版本。
  • 在主工程的info.plist中加入键值NSSupportsLiveActivities ,并将其布尔值设置为YES
  • 因为灵动岛是属于小组件的一部分,所以项目中如果没有小组件的话要先创建小组件。有小组件的话可以添加些代码即可适配。


    16645173953743.png

4.详细介绍

4.1 布局
16645173873665.png
16645182762547.png
Simulator Screen Shot - iPhone 14 Pro Max - 2022-09-30 at 14.15.21.png

上图依次是

  • 紧凑视图:分为leading和traling视图,只有一个live activity事件时
  • 最小视图:两个及以上live activity事件时,左右显示的都是minmal视图
  • 扩展视图:分为leading、traling、center、bottom
  • 锁屏视图:锁屏的时候会展示在锁屏下方
var body: some WidgetConfiguration {
        ActivityConfiguration(for: GroceryDeliveryAppAttributes.self) { context in
            LockScreenView(context: context) //锁屏视图
        } dynamicIsland: { context in
            DynamicIsland {
                 //扩展视图
                 DynamicIslandExpandedRegion(.leading) {
                    dynamicIslandExpandedLeadingView(context: context)
                 }
                 
                 DynamicIslandExpandedRegion(.trailing) {
                     dynamicIslandExpandedTrailingView(context: context)
                 }
                 
                 DynamicIslandExpandedRegion(.center) {
                     dynamicIslandExpandedCenterView(context: context)
                 }
                 
                 DynamicIslandExpandedRegion(.bottom) {
                    dynamicIslandExpandedBottomView(context: context)
                 }
                
              } compactLeading: {//单个前视图
                  compactLeadingView(context: context)
              } compactTrailing: {//单个后视图
                  compactTrailingView(context: context)
              } minimal: { //最小化视图
                  minimalView(context: context)
              }
              .keylineTint(.cyan) //灵动岛边缘颜色
        }
    }

当只有一个live activity事件时


16645183250579.png
16645183283279.png

因为这个灵动岛左右是对称的,左边布局的拉宽会带动右边也拉宽,进而占据时间、信号、电量等图标。而用户肯定会对这种占据过多空间的live activity深恶痛绝,可能会立马干掉。

灵动岛:只能在App处于前台时从其启动实时活动。目前最多只能展示两个live activity,后来的不会显示,除非用户上下滑动移除了当前显示的live activity或者在锁屏界面移除或者代码调用移除,后来的才会依次展示在上面,因为用的模拟器调研,不知道系统的打电话功能是否优先级最高。注意这里的上下滑动只是隐藏了当前的live activity,他其实还在,锁屏的时候依然会显示。

锁屏: 没有灵动岛的设备同样会展示锁屏视图,高度最多显示160,其余会被系统裁剪掉。移除锁屏状态的视图,就相当于停止了live activity。

4.2 更新策略

每个“Live Activity”都在自己的沙盒中运行,虽然它是依托于小组件但是与小组件的时间线timeline更新不同,它无法访问网络或接收位置更新。要更新活动现场活动的动态数据,请使用应用程序中的ActivityKit框架,或允许您的现场活动接收远程推送通知。 ActivityKit 更新后和远程推送通知更新的动态数据大小不得超过 4KB

4.2.1 live activity更新
  1. 手动代码更新:
    16645187695082.png
  2. 推送通知更新:需要和服务端配置推送类型pushType,详情可见相关链接。如果通知被用户关闭了权限,应该只能采用手动更新来保证吧。

4.2.2 对比widget更新

Widget 的刷新方式是很特别的,相当的克制。以下摘自官方文档:
Updating every minute is far too aggressive. Widgets have a limited number of updates and if you were to try to update every minute, you'll quickly run out of updates. While debugging with Xcode these limits are not imposed, but if you're running your app outside of Xcode you'd see the behavior you're describing where your widget would stop updating.
意思是一个组件一天会有一定限制的刷新频次数,超过这个次数,系统将不保证刷新是否成功。
WidgetKit通过以下两种方式之一要求时间线条目:

  • 单个即时快照,表示小部件的当前状态。
  • 条目数组,包括当前时刻,以及(如果已知)小部件状态将更改的任何未来日期。

其实就是Widget引入了timeline时间线的概念,如果已知这个小组件现在及未来一段时间的状态,就可以在getTimeline提供内容展示的entry组。并且更新策略选.atEnd就是提供的entry都展示完再去请求新的。
WidgetKit 在一个单独的进程中呈现视图。因此,即使小部件在屏幕上,小部件扩展也不会一直处于活动状态。尽管小部件并不总是处于活动状态,但可以通过多种方式使其内容保持最新。

被动:

  • WidgetKit 有时会重新加载小部件以帮助保持其内容最新。一些常见的场景包括:
  • 如果小部件位于用户很少访问的主屏幕页面上,则 WidgetKit 可能会降低该小部件的重新加载频率。稍后,当用户查看页面时,WidgetKit 可能会在小部件可见时重新加载它。
  • 对于使用位置服务的小部件,WidgetKit 会在位置发生重大变化后重新加载它们。

主动:
主程序调用的主动刷新:

WidgetCenter.shared.reloadTimelines(ofKind: "com.mygame.character-detail")

官方示例:

如果已知一个人健康状态当前为25%,且每小时固定增长25%,则可以安排一个如下计划生成timeline

//@escaping修饰则可以进行异步网络请求,下面的例子是静态的时候的

func getTimeline(in context: Context, completion: @escaping (Timeline<CharacterDetailEntry>) -> Void) {

        var date = Date()

        var healthLevel = 0.25

        var entries: [CharacterDetailEntry] = []       

        while healthLevel <= 1 {

            entries.append(CharacterDetailEntry(date: date, healthLevel: healthLevel))  //添加当前状态的entry 是要立马展示出来的

            healthLevel = min(1, healthLevel + 0.25)                                                        // 每次把健康状态升高0.25,最高为1

            date = Calendar.current.date(byAdding: .hour, value: 1, to: date)!                 // TiimeLine提供一段Entry,而entry的最小间隔是1分钟,及时设置成秒也没用。

        }

        let timeline = Timeline(entries: entries, policy: .atEnd) // .after   .never

        completion(timeline)

    }
4.3 移除策略

在灵动岛leading视图部位上下滑动可以隐藏当前的live activity , 也可以在应用的设置里面禁止live activity。

  • default:“实时活动”会在锁定屏幕上显示一段时间,以便用户一目了然地查看手机以查看最新信息。用户可以选择随时删除“实时活动”,或者系统会在“实时活动”结束后四小时自动移除它。

  • immediate:立即移除从锁定屏幕结束的“实时活动”

  • after: 系统会在给定日期后或自“实时活动”结束起四小时后删除已结束的现场活动——以先到者为准

除非App主动结束或用户手动结束,否则展现在灵动岛的“live activity”活动在不操作的情况下最多可以活跃8小时。如果在第8小时的时候用户主动关闭了default或after策略的live activity,锁定屏幕上的可以再多显示4个小时。所以即实时活动会灵动上岛最多保留八小时,在锁定屏幕上最多保留十二小时。 杀死App不会停止live activity.

欢迎大家交流并指出错误,谢谢

5. 参考文档

参考 链接
ActivityKit https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities
Live Activity Push Notification https://developer.apple.com/documentation/activitykit/update-and-end-your-live-activity-with-remote-push-notifications
Dynamic Island https://developer.apple.com/documentation/widgetkit/dynamicisland
Code https://github.com/jordibruin/Dynamic-Islands https://github.com/batikansosun/iOSLiveActivitiesLockScreen https://github.com/1998code/iOS16-Live-Activities
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容