盒馬 iOS Live Activity &“靈動島”配送場景實踐

語言: CN / TW / HK

作者:陳振港、李凱

蘋果在 WWDC22 中,提出了實時活動(Live Activity)的概念,以便於使用者在鎖屏檢視一些應用實時活動的更新,這與盒馬的配送場景十分貼合。因此,我們將 Live Activity & “靈動島” 特性第一時間落地到盒馬 30 分鐘配送場景,並作為第一批適配實時活動的 iOS 應用,獲得 App Store Today 推薦。

目前,盒馬 App 適配“靈動島”的最新 5.51.1 版本已正式上線,歡迎大家升級體驗。在適配過程中,盒馬 App 也在端側踩過很多“坑”,特此彙總為實戰經驗分享給大家,歡迎交流。

快速落地時間線

  • 6月16日,根據WWDC相關內容提前調研;
  • 8月16日,開始基於官方文件和beta版做demo;
  • 9月8日,登上Apple中國區官網;
  • 9月15日,iOS 16.1 beta開放,開始正式的需求流程;
  • 10月19日,iOS 16.1 RC上線,開始打包以及迴歸測驗;
  • 10月20日,提交稽核;
  • 10月22日,稽核通過上架;
  • 10月25日,App Store Today推薦。

蘋果官網截圖

App Store Today截圖

客戶端技術方案

Live Activity&靈動島簡介

在介紹盒馬最終落地技術方案之前,先給大家簡單介紹一下Live Activity&靈動島技術調研得出的一些關鍵資訊及其比較適用的場景。

場景限制及建議

  1. 最多持續8小時,使用場景需要考慮,8小時之後無法再重新整理(目前實際還可以,但是以官方文件為準,自行限制),12小時後強制消失(因此跨天場景不考慮)
  2. 建立時,需要app在前臺主動建立,沒啟動應用的時候不能自己出現(與特定業務繫結,比如下單後顯示)
  3. 卡片本身禁止定位以及網路請求,少量(4KB)資料可通過通知傳送,或通過後臺活動重新整理資料
  4. 同場景多卡片由於樣式趨同且摺疊,不建議同時建立多卡片

靈動島適配必要性

  • 與鎖屏Live Activity共享資料,在支援靈動島的機型下,使用者在非鎖屏頁面時,資訊的更新會以靈動島的形式展示更新
  • Live Activity建立後,靈動島就可以進行點選響應了,如果不適配的話,點選靈動島會自動進入主程式,並且長按會變成一個沒有任何資訊的黑塊
  • 盒馬iPhone14 Pro以及 Pro Max使用者佔比逐漸升高

整體方案流程圖

注意事項: - Live Activity有一個獨立的許可權,並且是不需要請求同意的,預設開啟 - 使用者必須保持開始通知許可權,才能通過通知重新整理,後臺活動不需要 - 必須在應用處於前臺時啟動,相當於要主動觸發 - 資料更新時,系統自動適配動畫,不需要自己額外新增動畫(添加了也會被忽略) - 不支援在其中顯示gif圖片和網路圖片 - 可以設定響應頁面,比如點選不同控制元件跳到不同頁面,和widget類似

技術難點及策略

基於上述流程方案,我們在實際落地過程中也遇到一些問題,下面是核心問題和應對策略。

實時更新 - 通知重新整理資料

更新方式有2種:

  1. 通過本地update方式在後臺重新整理資料,比如藍芽、後臺活動等。此方式要求主App程序必須存在,程序一旦殺掉就無法更新;
  2. 通過通知重新整理的實時活動,需要通知為Token-Based,並且對請求的引數做新的擴充套件。此方式比較靈活,無需主App程序存在,更新及時,因此我們採用此方式。

監聽並上報token

使用通知重新整理的方式需要獲取實時活動獨立的pushToken,對比在Swift中通過Http請求的方式上報,這裡考慮用block的方式,將Swift中的token丟回給主工程,由主工程負責上傳token。

圖片傳入 - 非本地化圖片

技術限制

因為Live Activity內部禁用網路圖片,傳統的服務端傳圖片URL的方式無法滿足實際使用,但是希望傳入訂單圖片來個性化地表達並且區分不同訂單。

解決方案

iOS 16 beta版時可以通過建立時將圖片轉為Data格式傳入卡片,但是iOS16.1該方案僅限傳入4KB左右的圖片(API限制),因此暫時不考慮非本地圖片方案,採用內建圖片方式實現。

機型適配 - 獲取螢幕寬度問題

技術限制

iOS 16 beta版時,嘗試使用UIScreen.main.bounds.width獲取螢幕寬度,該方法在模擬器上可以正確獲取,但是在真機上,得到值為0,導致無法進行適配。

解決方案

考慮在建立Live Activity時,直接從主工程將螢幕寬度作為起始屬性傳入其中,驗證發現可行。

過渡動畫 - 系統限制

Live Activity限制了自定義動畫,在資料重新整理時,系統自行進行過渡,這也導致了過渡時會出現一些問題。

卡片大小變化過渡問題及解決方案

如果通過設定整個View的.background,在變更整體Live Activity大小的時候,一開始會先把之後的區域框定,但是超出的部分顏色與自定義的背景是不一致的。

改之前(漸變背景為.background設定),有明顯不同色的情況。

改之後(漸變背景為單獨圖層),變化時不再有顏色區別。

視訊效果展示,請點選此處

進度條長度變化過渡問題及解決方案

實際應用發現,通過mask實現的進度條,如果進度條變長,並沒有過渡效果,而是直接跳到最終位置,因此考慮相反的進度條,就可以實現過渡效果。

視訊效果展示,請點選此處

埋點分析 - 點選跳轉

由於預設情況點選是回主程式,而並不是固定頁面,因此有必要自定義widgetUrl(如用於回到訂單頁面),也可以通過Link實現分割槽域的跳轉,Link和widgetUrl共存時,點選Link區域會響應Link,因此兩者同時使用即可。

技術限制

無法在widget內部直接新增埋點,並且靈動島收起時,僅支援新增同一個widgetUrl,對於收起狀態新增Link並沒有響應。

解決方案

因為點選直接跳轉到主App,因此考慮將埋點引數加入URL引數即可,主App解析時埋點。但是無法記錄包括使用者檢視、使用者關閉(關閉卡片 繼續傳送推送也沒有報錯 因此無法判斷)等行為的埋點。

對於靈動島的區分,實際測試發現,在展開模式下,可以加入Link並且可以正常響應,這與官方文件中的描述一致。

版本適配 - 與小鎮widget共存

盒馬App本來上線有小鎮Widget,iOS 14即可支援,而Live Activity需要iOS 16.1,因此需要對兩者做版本適配。

技術限制

  • Xcode 14beta不支援在Bundle內部區分版本,只能重新建立一個擴充套件;
  • Xcode 14.1支援在同一個widget Extension內部區分版本。但beta版發現使用了該方法,會導致兩個widget都不出現,不使用則都可以正常使用,確認是當前版本bug。

解決方案

後置系統版本判斷,在LiveActivityWidget內部去限制版本,成功使二者同時展現。

觸發場景 - 前置判斷

許可權限制

系統版本: - 不支援iOS 16.1以下

沒有許可權: - 通知許可權 - 實時活動許可權

前置許可權限制判斷,不滿足以上條件時,不嘗試建立Live Activity。

時間限制

送達時間超過8小時的場景不建立,因為建立後8小時就無法再重新整理

異常場景

  • 已經存在了很多卡片,達到上限,建立時失敗(返回建立結果,失敗不進行後續推送)
  • 使用者關閉卡片,應用無法感知(繼續推送,也不會再顯示)

觸發提醒 - 疲勞度控制

鎖屏提醒

實時活動的重新整理支援靜默重新整理和提醒重新整理,這就需要考慮使用者疲勞度,並且靈動島的展開提醒會比普通的通知屏佔比更大,更容易影響到使用者。

帶有alert欄位的通知會觸發鎖屏的亮起以及聲音,在主螢幕時會展示靈動島,不帶有alert欄位的通知,會靜默更新,鎖屏時不會亮起,息屏顯示時也不會有動畫過渡,直接顯示後續進度。

特殊情況

事件型別為END的通知,即使帶了alert,也不會觸發提醒。如果需要的話,可以在此時發一條update。

對於不支援靈動島的機型,新增alert欄位,會在主螢幕中觸發鎖屏Live Activity樣式的橫幅通知,目前該橫屏會常駐顯示,但螢幕有新的任何使用者點選都會直接被收起。

擴充套件能力 - 欄位解析

技術限制

為了保證通知能正常解析,通知payload欄位必須保證包含客戶端定義的欄位,若新版本加了新欄位,服務端下發了新欄位,老版本不會受到影響也可以正常解析。

原因:原生的解析方式,將通知中的JSON解析為物件,但是對於欄位缺少的JSON,解析會失敗,這時候無法成功重新整理。

解決方案

考慮外部傳入JSONString,內部進行單獨解析,注意不要解析為物件,不然還是沒法處理欄位缺少的情況,直接解析為字典,字典內部再對各個屬性判斷,並將空的屬性置為空值,widget內部再對應進行調整顯示。

這樣方式可以使各業務端只要傳自己需要用到的欄位即可,不必再傳入空值。

後續技術規劃

第一階段我們在盒馬即時配送場景進行初步探索,後續會持續關注使用者使用反饋,不斷優化迭代,把更好的購物體驗帶給大家。同時,持續關注蘋果官方技術動態,嘗試在更多與盒馬緊密結合的業務場景落地,也歡迎熱愛iOS新技術的同學與我們交流。