Xamarin 中的 watchOS 背景工作
使用 watchOS 3 時,監看應用程式有三種主要方式可讓其資訊保持在最新狀態:
- 使用數個新的背景工作之一。
- 在手錶臉上有一個併發症(給予它額外的時間更新)。
- 讓使用者釘選到應用程式到新的 Dock(其保留在記憶體中且經常更新)。
讓應用程式保持最新狀態
在討論開發人員可以保留 watchOS 應用程式數據和使用者介面目前和更新的所有方式之前,本節將探討一組典型的使用模式,以及使用者如何根據一天中的時間及其 Apple Watch 電話 之間移動(例如開車)。
以下列範例為例:
- 早上,在排隊等候咖啡時,用戶流覽 i 電話 目前的新聞幾分鐘。
- 離開咖啡店之前,他們迅速檢查天氣與手錶臉上的併發症。
- 午餐前,他們使用 i 上的 地圖 應用程式 電話 尋找附近的餐廳,並預訂預訂,以會見客戶。
- 在前往餐廳時,他們收到關於蘋果手錶的通知,並快速看一眼,他們知道他們的午餐預約正在遲到。
- 晚上,他們在i 電話 上使用 地圖 應用程式,在開車回家之前檢查交通情況。
- 在回家的路上,他們收到iMessage通知,他們的蘋果手錶要求他們拿起一些牛奶,他們使用快速回復功能來傳送回應“確定”。
由於使用者想要使用Apple Watch 應用程式的「快速概覽」(少於三秒)本質,因此應用程式在向用戶顯示之前,通常沒有足夠的時間擷取所需的資訊並更新其 UI。
藉由使用Apple隨附於 watchOS 3 的新 API,應用程式可以排程 背景重新 整理,並在使用者要求之前準備好所需的資訊。 以上述天氣併發症為例:
- 應用程式排程在特定時間由系統喚醒。
- 應用程式會擷取產生更新所需的資訊。
- 應用程式會重新產生其使用者介面,以反映新的數據。
- 當使用者一目了然地查看應用程式的 [複雜度] 時,其具有最新的資訊,而不需要使用者等待更新。
如上所述,watchOS 系統會使用一或多個工作喚醒應用程式,其中具有非常有限的集區:
Apple 建議在應用程式完成自行更新程式之前,將它保持在其中,以充分利用這項工作(因為它對應用程式來說如此有限)。
系統會藉由呼叫委派的新 HandleBackgroundTasks
方法 WKExtensionDelegate
來傳遞這些工作。 例如:
using System;
using Foundation;
using WatchKit;
namespace MonkeyWatch.MonkeySeeExtension
{
public class ExtensionDelegate : WKExtensionDelegate
{
#region Constructors
public ExtensionDelegate ()
{
}
#endregion
#region Override Methods
public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
{
// Handle background request here
...
}
#endregion
}
}
當應用程式完成指定的工作時,它會將它標示為已完成,將它傳回給系統:
新增背景工作
watchOS 3 引進了數個背景工作,應用程式可用來更新其資訊,確保其具有使用者開啟應用程式之前所需的內容,例如:
- 背景應用程式重新 整理 - WKApplicationRefreshBackgroundTask 工作可讓應用程式在背景中更新其狀態。 這通常包含另一項工作,例如使用 NSUrlSession 從因特網下載新內容。
- 背景快照集重新 整理 - WKSnapshotRefreshBackgroundTask 工作可讓應用程式在系統擷取將用來填入 Dock 的快照集之前更新其內容和 UI。
- 背景監看 連線 ivity - WKWatch 連線 ivityRefreshBackgroundTask 工作會在應用程式收到配對 i 電話 的背景數據時啟動。
- 背景 URL 工作階段 - 當背景傳輸需要授權或完成時,會針對應用程式啟動 WKURLSessionRefreshBackgroundTask 工作(成功或發生錯誤)。
下列各節將詳細說明這些工作。
WKApplicationRefreshBackgroundTask
WKApplicationRefreshBackgroundTask
是一般工作,可排程在未來日期喚醒應用程式:
在工作運行時間內,應用程式可以執行任何類型的本機處理,例如更新複雜時間軸,或使用 擷取一些必要的數據 NSUrlSession
。
WKURLSessionRefreshBackgroundTask
當資料完成下載並準備好由應用程式處理時,系統會傳送 WKURLSessionRefreshBackgroundTask
:
在背景下載數據時,應用程式不會繼續執行。 相反地,應用程式會排程數據的要求,然後會暫停,而系統會處理數據的下載,而只會在下載完成時重新喚醒應用程式。
WKSnapshotRefreshBackgroundTask
在 watchOS 3 中,Apple 已新增 Dock,讓使用者可以釘選他們慣用的應用程式並快速存取它們。 當使用者按下 Apple Watch 上的側邊按鈕時,將會顯示釘選的應用程式快照集資源庫。 使用者可以向左或向右撥動以尋找所需的應用程式,然後點選應用程式以將快照集取代為執行中應用程式的介面。
系統會定期擷取應用程式 UI 的快照集(藉由傳送 WKSnapshotRefreshBackgroundTask
),並使用這些快照集填入 Dock。 watchOS 可讓應用程式有機會在取得此快照集之前更新其內容和UI。
快照集在 watchOS 3 中非常重要,因為它們會同時作為應用程式的預覽和啟動影像運作。 如果使用者在 Dock 中的應用程式上定居,它會展開至全螢幕,輸入前景並開始執行,因此快照集必須處於最新狀態:
同樣地,系統會發出 WKSnapshotRefreshBackgroundTask
,讓應用程式可以在擷取快照集之前準備 (藉由更新數據和 UI:
當應用程式標示 WKSnapshotRefreshBackgroundTask
完成時,系統會自動擷取應用程式的 UI 快照集。
重要
請務必在應用程式收到新數據並更新其使用者介面之後排程 WKSnapshotRefreshBackgroundTask
,否則使用者不會看到修改的資訊。
此外,當使用者收到來自應用程式的通知,並點選它以將應用程式帶到前景時,快照集也必須是最新的,因為它也會作為啟動畫面:
如果使用者已與 watchOS 應用程式互動超過一小時,它將能夠返回其默認狀態。 默認狀態可能代表不同應用程式的不同專案,而且根據應用程式的設計,它可能完全沒有默認狀態。
WKWatch 連線 ivityRefreshBackgroundTask
在 watchOS 3 中,Apple 已透過新的 WKWatchConnectivityRefreshBackgroundTask
整合式監看式連線與背景重新整理 API。 使用這項新功能,i 電話 應用程式可以在背景中執行 watchOS 應用程式時,將全新的數據傳遞給其監看應用程式對應專案:
起始複雜推送、應用程式內容、傳送檔案或從 i 電話 應用程式更新使用者資訊,將會在背景喚醒 Apple Watch 應用程式。
當監看應用程式透過 WKWatchConnectivityRefreshBackgroundTask
喚醒時,它必須使用標準 API 方法從 i 電話 應用程式接收數據。
- 確定會話已啟用。
- 只要值為
true
,應用程式仍要處理數據,就會監視新的HasContentPending
屬性。 和之前一樣,應用程式應該會保留工作,直到它完成處理所有數據為止。 - 當沒有其他數據要處理時(
HasContentPending = false
),請標示已完成的工作以將它傳回系統。 若無法這麼做,將會耗盡應用程式配置的背景運行時間,導致當機報告。
背景 API 生命週期
將所有新的背景工作 API 片段放在一起,一組典型的互動看起來如下:
- 首先,watchOS 應用程式會排程背景工作,以在未來某個時間點喚醒。
- 應用程式會由系統喚醒,並傳送工作。
- 應用程式會處理工作以完成任何必要工作。
- 由於處理工作,應用程式可能需要排程更多背景工作,以在未來完成更多工作,例如使用
NSUrlSession
下載更多內容。 - 應用程式會將工作標示為已完成,並將它傳回給系統。
負責任地使用資源
監看式OS 應用程式必須藉由限制其對系統共用資源的流失,在生態系統內負責任地運作。
請檢視下列案例:
- 使用者於下午 1:00 啟動 watchOS 應用程式。
- 應用程式會在下午 2:00 排程一小時內喚醒並下載新內容的工作。
- 下午 1:50 時,用戶會重新開啟應用程式,以便目前更新其數據和 UI。
- 應用程式應該在下午 2:50 重新排程工作一小時後執行,而不是讓工作在 10 分鐘內再次喚醒應用程式。
雖然每個應用程式都不同,但Apple建議尋找使用模式,例如上面所示的模式,以協助節省系統資源。
實作背景工作
為了方便起見,本檔會使用假的 MonkeySoccer 運動應用程式,向用戶報告足球分數。
請檢視下列一般使用案例:
用戶最喜歡的足球隊正在下午 7:00 到下午 9:00 進行一場大型比賽,因此應用程式應該預期使用者會定期檢查分數,並決定 30 分鐘的更新間隔。
- 用戶會開啟應用程式,並在 30 分鐘後排程背景更新的工作。 背景 API 只允許在指定時間執行一種背景工作。
- 應用程式會收到工作並更新其數據和UI,然後排程30分鐘後的另一個背景工作。 請務必讓開發人員記得排程另一個背景工作,否則應用程式永遠不會重新叫用以取得更多更新。
- 同樣地,應用程式會收到工作並更新其數據、更新其 UI,並在 30 分鐘後排程另一個背景工作。
- 相同的程式會再次重複。
- 收到最後一個背景工作,應用程式會再次更新其數據和UI。 因為這是最終分數,因此不會排程新的背景重新整理。
背景更新的排程
假設上述案例,MonkeySoccer 應用程式可以使用下列程式代碼來排程背景更新:
private void ScheduleNextBackgroundUpdate ()
{
// Create a fire date 30 minutes into the future
var fireDate = NSDate.FromTimeIntervalSinceNow (30 * 60);
// Create
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("LastActiveDate"), NSDate.FromTimeIntervalSinceNow(0));
userInfo.Add (new NSString ("Reason"), new NSString ("UpdateScore"));
// Schedule for update
WKExtension.SharedExtension.ScheduleBackgroundRefresh (fireDate, userInfo, (error) => {
// Was the Task successfully scheduled?
if (error == null) {
// Yes, handle if needed
} else {
// No, report error
}
});
}
當應用程式想要喚醒並建立 ,以保存所要求工作的詳細數據時,它會在未來建立NSMutableDictionary
新的 NSDate
30 分鐘。 的 ScheduleBackgroundRefresh
方法是 SharedExtension
用來要求排程的工作。
如果系統無法排程所要求的工作,系統將會傳回 NSError
。
處理更新
接下來,請仔細查看 5 分鐘視窗,其中顯示更新分數所需的步驟:
- 在下午 7:30:02 時,應用程式會由系統喚醒,並指定更新背景工作。 其第一個優先順序是從伺服器取得最新的分數。 請參閱 下面的排程 NSUrlSession 。
- 在 7:30:05 應用程式完成原始工作時,系統會讓應用程式進入睡眠狀態,並繼續在背景下載要求的數據。
- 當系統完成下載時,它會建立新的工作來喚醒應用程式,以便處理下載的資訊。 請參閱 處理背景工作 和 處理下列下載完成 。
- 應用程式會儲存更新的資訊,並將工作標示為已完成。 開發人員目前可能會想要更新應用程式的使用者介面,不過 Apple 建議排程快照集工作來處理該程式。 請參閱 下方的排程快照集更新 。
- 應用程式會收到快照集工作、更新其使用者介面,並將工作標示為已完成。 請參閱 下方處理快照集更新 。
排程 NSUrlSession
下列程式代碼可用來排程下載最新的分數:
private void ScheduleURLUpdateSession ()
{
// Create new configuration
var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.example.urlsession");
// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration);
// Create and start download task
var downloadTask = backgroundSession.CreateDownloadTask (new NSUrl ("https://example.com/gamexxx/currentScores.json"));
downloadTask.Resume ();
}
它會設定並建立新的 NSUrlSession
,然後使用該工作階段,使用 CreateDownloadTask
方法建立新的下載工作。 它會呼叫 Resume
下載工作的 方法來啟動會話。
處理背景工作
藉由覆寫 HandleBackgroundTasks
的 WKExtensionDelegate
方法,應用程式可以處理傳入的背景工作:
using System;
using System.Collections.Generic;
using Foundation;
using WatchKit;
namespace MonkeySoccer.MonkeySoccerExtension
{
public class ExtensionDelegate : WKExtensionDelegate
{
#region Computed Properties
public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
#endregion
...
#region Public Methods
public void CompleteTask (WKRefreshBackgroundTask task)
{
// Mark the task completed and remove from the collection
task.SetTaskCompleted ();
PendingTasks.Remove (task);
}
#endregion
#region Override Methods
public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
{
// Handle background request
foreach (WKRefreshBackgroundTask task in backgroundTasks) {
// Is this a background session task?
var urlTask = task as WKUrlSessionRefreshBackgroundTask;
if (urlTask != null) {
// Create new configuration
var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);
// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);
// Keep track of all pending tasks
PendingTasks.Add (task);
} else {
// Ensure that all tasks are completed
task.SetTaskCompleted ();
}
}
}
#endregion
...
}
}
方法 HandleBackgroundTasks
會循環執行系統已傳送應用程式的所有 [工作] 來 backgroundTasks
搜尋 WKUrlSessionRefreshBackgroundTask
。 如果找到其中一個,它會重新加入會話,並附加 NSUrlSessionDownloadDelegate
以處理正在完成的下載 (請參閱 處理下方的下載完成 ):
// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);
它會在工作上保留句柄,直到它完成,方法是將它新增至集合:
public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
...
// Keep track of all pending tasks
PendingTasks.Add (task);
所有傳送至應用程式的工作都必須完成,對於目前未處理的任何工作,請將其標示為完成:
if (urlTask != null) {
...
} else {
// Ensure that all tasks are completed
task.SetTaskCompleted ();
}
處理下載完成
MonkeySoccer 應用程式會使用下列 NSUrlSessionDownloadDelegate
委派來處理下載完成並處理要求的數據:
using System;
using Foundation;
using WatchKit;
namespace MonkeySoccer.MonkeySoccerExtension
{
public class BackgroundSessionDelegate : NSUrlSessionDownloadDelegate
{
#region Computed Properties
public ExtensionDelegate WatchExtensionDelegate { get; set; }
public WKRefreshBackgroundTask Task { get; set; }
#endregion
#region Constructors
public BackgroundSessionDelegate (ExtensionDelegate extensionDelegate, WKRefreshBackgroundTask task)
{
// Initialize
this.WatchExtensionDelegate = extensionDelegate;
this.Task = task;
}
#endregion
#region Override Methods
public override void DidFinishDownloading (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
{
// Handle the downloaded data
...
// Mark the task completed
WatchExtensionDelegate.CompleteTask (Task);
}
#endregion
}
}
初始化時,它會保留 和 WKRefreshBackgroundTask
繁衍它的 句柄ExtensionDelegate
。 它會覆寫 DidFinishDownloading
方法來處理下載完成。 CompleteTask
然後使用的 ExtensionDelegate
方法,通知工作已完成,並將它從暫止工作集合中移除。 請參閱 上述處理背景工作 。
排程快照集更新
下列程式代碼可用來排程快照集工作,以最新的分數更新UI:
private void ScheduleSnapshotUpdate ()
{
// Create a fire date of now
var fireDate = NSDate.FromTimeIntervalSinceNow (0);
// Create user info dictionary
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));
// Schedule for update
WKExtension.SharedExtension.ScheduleSnapshotRefresh (fireDate, userInfo, (error) => {
// Was the Task successfully scheduled?
if (error == null) {
// Yes, handle if needed
} else {
// No, report error
}
});
}
就像上述方法一樣 ScheduleURLUpdateSession
,它會在應用程式想要被叫醒時建立新的 NSDate
,並建立 NSMutableDictionary
來保存所要求工作的詳細數據。 的 ScheduleSnapshotRefresh
方法是 SharedExtension
用來要求排程的工作。
如果系統無法排程所要求的工作,系統將會傳回 NSError
。
處理快照集更新
若要處理快照集工作, HandleBackgroundTasks
方法(請參閱 上述處理背景工作 )已修改為如下所示:
public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
{
// Handle background request
foreach (WKRefreshBackgroundTask task in backgroundTasks) {
// Take action based on task type
if (task is WKUrlSessionRefreshBackgroundTask) {
var urlTask = task as WKUrlSessionRefreshBackgroundTask;
// Create new configuration
var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);
// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);
// Keep track of all pending tasks
PendingTasks.Add (task);
} else if (task is WKSnapshotRefreshBackgroundTask) {
var snapshotTask = task as WKSnapshotRefreshBackgroundTask;
// Update UI
...
// Create a expiration date 30 minutes into the future
var expirationDate = NSDate.FromTimeIntervalSinceNow (30 * 60);
// Create user info dictionary
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));
// Mark task complete
snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);
} else {
// Ensure that all tasks are completed
task.SetTaskCompleted ();
}
}
}
方法會測試正在處理的工作類型。 WKSnapshotRefreshBackgroundTask
如果是 ,它就會取得工作的存取權:
var snapshotTask = task as WKSnapshotRefreshBackgroundTask;
方法會更新使用者介面,然後建立 NSDate
,以告訴系統快照集何時過期。 它會使用使用者資訊建立 NSMutableDictionary
,以描述新的快照集,並以這項資訊標記完成的快照集工作:
// Mark task complete
snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);
此外,它也會告訴快照集工作,應用程式不會返回默認狀態(在第一個參數中)。 沒有預設狀態概念的應用程式應該一律將此屬性設定為 true
。
有效率地工作
如上述五分鐘視窗範例所示,MonkeySoccer 應用程式透過有效率地運作及使用新的 watchOS 3 背景工作來更新分數,應用程式僅作用中 15 秒:
這樣可降低應用程式對可用 Apple Watch 資源和電池使用時間的影響,也讓應用程式能夠與在手錶上執行的其他應用程式搭配運作得更好。
排程的運作方式
當 watchOS 3 應用程式處於前景時,它一律會排程執行,而且可以執行任何類型的處理,例如更新數據或重新繪製其 UI。 當應用程式進入背景時,系統通常會暫停它,且所有運行時間作業都會停止。
當應用程式位於背景時,系統可能會以快速執行特定工作為目標。 因此,在 watchOS 2 中,系統可能會暫時喚醒背景應用程式,以執行處理長外觀通知或更新應用程式併發症等動作。 在 watchOS 3 中,有數種可在背景中執行應用程式的新方式。
當應用程式處於背景時,系統會對其施加數個限制:
- 只需要幾秒鐘的時間才能完成任何指定的工作。 系統不僅會考慮經過的時間量,還會考慮應用程式耗用多少 CPU 能力來衍生此限制。
- 任何超過其限制的應用程式都會以下列錯誤碼終止:
- CPU - 0xc51bad01
- 時間 - 0xc51bad02
- 系統會根據要求應用程式執行的背景工作類型來施加不同的限制。 例如,
WKApplicationRefreshBackgroundTask
和WKURLSessionRefreshBackgroundTask
[工作] 會針對其他類型的背景工作提供略長一點的運行時間。
複雜功能和應用程式 更新
除了 Apple 新增至 watchOS 3 的新背景工作之外,watchOS 應用程式的複雜功能可能會影響應用程式接收背景更新的方式和時機。
複雜功能是小型視覺元素,可一目了然地提供有用的資訊。 根據選取的手錶臉部,用戶能夠使用 watchOS 3 中手錶應用程式提供的一或多個複雜功能來自定義手錶臉部。
如果使用者在其手錶臉上包含其中一個應用程式的複雜功能,則會為應用程式提供下列更新的優點:
- 它會導致系統讓應用程式處於可啟動狀態,並嘗試在背景啟動應用程式、將應用程式保留在記憶體中,並額外提供更新時間。
- 併發症保證每天至少 50 個推送更新。
開發人員應一律努力為其應用程式建立令人信服的複雜功能,以吸引使用者將他們新增至手錶臉部,原因如下。
在 watchOS 2 中,複雜度是應用程式在背景中接收運行時間的主要方式。 在 watchOS 3 中,仍會確保複雜應用程式每小時收到多個更新,不過,它可以用來 WKExtensions
要求更多運行時間來更新其複雜狀況。
看看下列程式代碼,用來從連線的 i 電話 應用程式更新複雜狀況:
using System;
using WatchConnectivity;
using UIKit;
using Foundation;
using System.Collections.Generic;
using System.Linq;
...
private void UpdateComplication ()
{
// Get session and the number of remaining transfers
var session = WCSession.DefaultSession;
var transfers = session.RemainingComplicationUserInfoTransfers;
// Create user info dictionary
var iconattrs = new Dictionary<NSString, NSObject>
{
{new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0)},
{new NSString ("reason"), new NSString ("UpdateScore")}
};
var userInfo = NSDictionary<NSString, NSObject>.FromObjectsAndKeys (iconattrs.Values.ToArray (), iconattrs.Keys.ToArray ());
// Take action based on the number of transfers left
if (transfers < 1) {
// No transfers left, either attempt to send or inform
// user of situation.
...
} else if (transfers < 11) {
// Running low on transfers, only send on important updates
// else conserve for a significant change.
...
} else {
// Send data
session.TransferCurrentComplicationUserInfo (userInfo);
}
}
它會使用 RemainingComplicationUserInfoTransfers
的 WCSession
屬性來查看應用程式在當天剩餘多少次優先順序傳輸,然後根據該數位採取動作。 如果應用程式開始在傳輸時執行低,它可能會阻礙傳送次要更新,而且只有在有重大變更時才會傳送資訊。
排程和停駐
在 watchOS 3 中,Apple 已新增 Dock,讓使用者可以釘選他們慣用的應用程式並快速存取它們。 當使用者按下 Apple Watch 上的側邊按鈕時,將會顯示釘選的應用程式快照集庫。 使用者可以向左或向右撥動以尋找所需的應用程式,然後點選應用程式,將快照集取代為執行中應用程式的介面。
系統會定期擷取應用程式的UI快照集,並使用這些快照集填入 Docs。watchOS 可讓應用程式有機會在擷取此快照集之前更新其內容和UI。
已釘選到擴充座的應用程式可以預期下列各項:
- 他們至少會收到每小時一次更新。 這包括應用程式重新整理工作和快照集工作。
- 更新預算會在 Dock 中的所有應用程式之間散發。 因此,使用者釘選的應用程式越少,每個應用程式將會收到更多的潛在更新。
- 應用程式會保留在記憶體中,讓應用程式在從 Dock 中選取時快速繼續。
使用者執行的最後一個應用程式會被視為 最近使用 的應用程式,並將佔用 Dock 中的最後一個位置。 用戶可以從該處選擇永久釘選到 Dock。 [最近使用] 會像使用者已釘選到 Dock 的任何其他最愛應用程式一樣處理。
重要
只新增至主畫面的應用程式將不會得到任何定期排程。 若要接收定期排程和背景更新,必須將應用程式新增至 Dock。
如本檔稍早所述,快照集在 watchOS 3 中非常重要,因為它們會同時作為應用程式的預覽和啟動影像運作。 如果使用者在 Dock 中的應用程式上定居,它會展開為全螢幕,輸入前景並開始執行,因此快照集必須處於最新狀態。
有時候系統決定它需要應用程式UI的全新快照集。 在此情況下,快照集要求不會計入應用程式的運行時間預算。 下列會觸發系統快照集要求:
- 複雜時間軸更新。
- 使用者與應用程式的通知互動。
- 從前景切換至背景狀態。
- 進入背景狀態一小時之後,應用程式就可以返回默認狀態。
- 當 watchOS 第一次開機時。
最佳做法
使用背景工作時,Apple 會建議下列最佳做法:
- 視需要更新應用程式的頻率排程。 每次應用程式執行時,都應該重新評估其未來需求,並視需要調整此排程。
- 如果系統傳送背景重新整理工作,且應用程式不需要更新,請延遲工作,直到實際需要更新為止。
- 請考慮應用程式可用的所有執行時間機會:
- Dock 和 Foreground 啟用。
- 通知。
- 複雜更新。
- 背景重新整理。
- 用於
ScheduleBackgroundRefresh
一般用途的背景執行時間,例如:- 輪詢系統以取得資訊。
- 排程未來
NSURLSessions
以要求背景數據。 - 已知時間轉換。
- 觸發複雜更新。
快照集最佳做法
使用快照集更新時,Apple 會提出下列建議:
- 只有在需要時才使快照集失效,例如,當內容發生重大變更時。
- 避免高頻率快照集失效。 例如,定時器應用程式不應該每秒更新快照集,它應該只在定時器結束時完成。
應用程式數據流
Apple 建議使用數據流的下列專案:
外部事件 (例如 Watch 連線 ivity) 喚醒應用程式。 這會強制應用程式更新其數據模型(代表應用程式目前狀態)。 由於數據模型變更,應用程式需要更新其複雜狀況、要求新的快照集、可能啟動背景 NSURLSession
以提取更多數據,並排程進一步的背景重新整理。
應用程式生命週期
由於 Dock 和將最愛的應用程式釘選到它的能力,Apple 認為使用者將在更多應用程式之間移動,更頻繁地移動,然後他們確實使用 watchOS 2。 因此,應用程式應該準備好處理這項變更,並在前景和背景狀態之間快速移動。
Apple 有下列建議:
- 在進入前景啟用時,請確定應用程式會儘快完成任何背景工作。
- 請務必先完成所有前景工作,再呼叫
NSProcessInfo.PerformExpiringActivity
進入背景。 - 在 watchOS 模擬器中測試應用程式時,不會強制執行任何工作預算,讓應用程式可以視需要重新整理,以正確測試功能。
- 請務必在實際的Apple Watch硬體上進行測試,以確保應用程式在發佈至iTunes 連線 之前,不會執行超過其預算。
- 蘋果建議在測試和偵錯時將蘋果手錶放在充電器上。
- 請確定已徹底測試冷啟動和繼續應用程式。
- 確認所有應用程式工作都已完成。
- 變更固定在 Dock 中的應用程式數目,以測試最佳和最差的案例。
摘要
本文涵蓋 Apple 對 watchOS 所做的增強功能,以及如何用來讓手錶應用程式保持最新狀態。 首先,它涵蓋了 Apple 已在 watchOS 3 中新增的所有新背景工作。 然後,它涵蓋背景 API 生命週期,以及如何在 Xamarin watchOS 應用程式中實作背景工作。 最後,它涵蓋排程的運作方式,並提供一些最佳做法。