內容預告:
- Windows Phone 任務管理
- 用後台代碼實現多任務
- 在Visual Studio中建立任務
- 檔案傳輸任務
- 後台提醒
- 後台音樂播放
前台任務:一般來說,一個Windows Phone應用程式運行在前台時,它可以與使用者直接互動,但同時只能有一個程式運行在前台,是為了保證效能和電量。
後台代理:Windows Phone應用程式可以開啟一個後台代理,類型可以是定期執行或資源密集型或兩者兼俱型,但每個程式只能有一個後台代理。後台代理和前景程式運行在後台不是一回事,後台代理只能做有限的事情。
後台代理的限制:在Windows Phone系統上同時可運行後台代理的數量有限的,且只有在條件允許的情況下作業系統才把CPU的控制權交給後台代理,省電模式下不能運行,使用者可以自己關閉。
代理和任務:一個任務是作業系統管理的在某個約定的時間執行的,有定期執行或資源密集型兩種。一個後台代理是真正要執行的代碼,代理代碼從BackgroundTask派生,是計劃任務代理項目的一部分。
定期任務:大約每30分鐘執行一次,每次大約25秒,記憶體使用量量小於6MB,兩次crash連續後會取消,同時活躍的任務數量有限制,適用於定位跟蹤,後台輪詢,磁貼更新。
耗用大量資源的工作:外接電源時,電量大於90%,WiFi,鎖屏狀態,可連續運行10分鐘,記憶體使用量量小於6MB,兩次crash連續後會取消,適合約步服務,解壓縮,壓縮資料庫。
兼俱型任務:可以用一個背景工作類運行兩種任務,系統會根據上下文判斷執行合適的任務。
後台代理功能:
定位跟蹤器:用後台代理以記錄檔的方式儲存有規律地儲存手機的座標,代理會在日誌程式沒有焦點的時候更新位置資料。
建立後台代理:
串連代理項目:船長記錄項目引用了一個定位任務項目的輸出,前景程式不直接引用任何代理類的對象或類。
後台代理代碼:必須實現OnInvode函數,它完成時會通知運行時系統。
namespace LocationLogTaskAgent{ public class ScheduledAgent : ScheduledTaskAgent { protected override void OnInvoke(ScheduledTask task) { //TODO: Add code to perform your task in background NotifyComplete(); } }}
與後台代理共用資料:通過隔離儲存區 (Isolated Storage)
protected override void OnInvoke(ScheduledTask task){ string message =""; string logString = ""; if (LoadLogFromIsolatedStorageFile() { message = "Loaded"; } else { message = "Initialised"; } ...}
並發資料存放區:用互斥量(Mutex)保護隱藏檔,保證釋放mutex。
public bool LoadLogFromIsolatedStorageFile(){ mut.WaitOne(); // Wait until it is safe to enter try { // read the file here return true; } catch { LogText = ""; return false; } finally { mut.ReleaseMutex(); // Release the Mutex. }}
鉤選定位能力:
擷取手機位置:通過GeoCoordinateWatcher類提供位置資訊,在後台代理中使用Position,其每15分鐘更新一次。
protected override void OnInvoke(ScheduledTask task){ ... GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(); watcher.Start(); string positionString = watcher.Position.Location.ToString() + System.Environment.NewLine; ...}
儲存手機位置:
protected override void OnInvoke(ScheduledTask task){ ... logString = logString + timeStampString + " " + positionString; SaveLogToIsolatedStorageFile (); ...}
顯示通知:背景工作可以彈出toast提醒,如果使用者點擊toast,可以啟動程式,Toast訊息會在程式啟用後消失。
protected override void OnInvoke(ScheduledTask task){ ... logString = logString + timeStampString + " " + positionString; SaveLogToIsolatedStorageFile (); ...}
安排一個後台代理:
PeriodicTask t;t = ScheduledActionService.Find(taskName) as PeriodicTask;bool found = (t != null);if (!found) { t = new PeriodicTask(taskName);}t.Description = description;t.ExpirationTime = DateTime.Now.AddDays(10);if (!found){ ScheduledActionService.Add(t);} else{ ScheduledActionService.Remove(taskName); ScheduledActionService.Add(t);}
調試背景工作:我們可以強制服務啟動代理,因為30分鐘才能執行一次太煩人了。
#if DEBUG_AGENT ScheduledActionService.LaunchForTest(taskName, TimeSpan.FromSeconds(60));#endif
Tips:
- 經常續訂,因為背景工作只能持續2周有效。
- 不實現後台代理的臨界功能,因為使用者可能禁用,系統也可能因為電量原理掛起程式。
- 如果需要穩定的更新磁貼或Toast訊息,考慮用推送。
檔案傳輸任務:程式不運行也可以傳輸,可以監視下載狀態,支援HTTP、HTTPS,但不支援FTP。
傳輸限制:上傳最大5MB,通過行動電話通訊下載最大20MB,通過WiFi最大100MB,這些數字可以通過修改TransferPreferences的值。每個程式最多可以請求25次。
後台傳輸命名空間:using Microsoft.Phone.BackgroundTransfer;
建立一個後台傳輸:POST用來傳送檔案到伺服器。
Uri transferUri = new Uri(Uri.EscapeUriString(transferFileName), UriKind.RelativeOrAbsolute);// Create the new transfer request, passing in the URI of the file to // be transferred.transferRequest = new BackgroundTransferRequest(transferUri);// Set the transfer method. GET and POST are supported.transferRequest.Method = "GET";
設定傳輸目標:
string downloadFile = transferFileName.Substring(transferFileName.LastIndexOf("/") + 1);// Build the URIdownloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.RelativeOrAbsolute);transferRequest.DownloadLocation = downloadUri;// Set transfer optionstransferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
開始傳輸:
try { BackgroundTransferService.Add(transferRequest);}catch (InvalidOperationException ex) { MessageBox.Show("Unable to add background transfer request. " + ex.Message);}catch (Exception) { MessageBox.Show("Unable to add background transfer request.");}
監視傳輸:TransferProcessChanged是為進度條準備的,TransferStatusChanged在完成或失敗時觸發。
// Bind event handlers to the progess and status changed eventstransferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>( request_TransferProgressChanged);transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>( request_TransferStatusChanged);
void request_TransferProgressChanged(object sender, BackgroundTransferEventArgs e){ statusTextBlock.Text = e.Request.BytesReceived + " received.";}
void request_TransferStatusChanged(object sender, BackgroundTransferEventArgs e) { switch (e.Request.TransferStatus) { case TransferStatus.Completed: // If the status code of a completed transfer is 200 or 206, the // transfer was successful if (transferRequest.StatusCode == 200 ||transferRequest.StatusCode == 206) { // File has arrived OK – use it in the program }
移除一個傳輸:
try { BackgroundTransferService.Remove(transferRequest);}catch {}
聲音播放代理:聲音流可以存在隔離儲存區 (Isolated Storage)內,機制與其他背景工作相同。