Background Agents
נניח שאתם מעונינים לכתוב אפליקציה שרצה ברקע, ומבצעת סינכרון נתונים מול השרת, או שולחת נתונים שנאספו בעת ריצת האפליקציה. כידוע בגרסת תרום מנגו לא ניתן להריץ אפליקציה ברקע. כלומר אם יצאתם מהאפליקציה ע”י לחיצה על כפתור Start, האפליקציה יורדת מזכרון המכשיר וה- Process לא רץ (Tombstoning). בגרסת מנגו האפליקציה לא יורדת מזכרון המכשיר, אבל ה- Process נעצר והמשאבים משוחררים (Dormancy).
השאלה היא איך בכל זאת ניתן לבצע את מה שתארתי?
התשובה לשאלה זו היא Scheduled Tasks. במנגו מבדילים בין שני סוגי תהליכי רקע שניתן להריץ בעזרת Agents: האחד Periodic Agent והשני Resource Intensive Agent. כל אפליקציה יכולה להכיל מקס’ Agent אחד שיכול לתפקד כ- Periodic, Resource Intensive או שניהם יחד.
Periodic Agent
מאפשר לבצע פעולות קצרות שלא עולות על 15 שניות במחזוריות של 30 דקות, כגון שליחת מיקומו האחרון של המכשיר, עדכון או סנכרון נתונים קצר. צריך לקחת בחשבון ש- Agent זה יכול לרוץ במקביל עם Agents נוספים מאפליקציות אחרות ואם המשתמש הפעיל Battery Saver לא ירוץ אף Periodic Agent.
Resource Intensive Agent
מאפשר לבצע פעולות ארוכות של עד 10 דקות וישנם תנאים מחמירים לתחילת פעולתו של Agent זה:
- המכשיר חייב להיות מחובר למקור מתח קבוע, או שהסוללה מעל 90%.
- יש צורך בחיבור רשת WiFi או דרך המחשב.
- יש צורך שהמכשיר יהיה נעול (screen lock) ושאין שיחה פעילה.
הפרת אחד מהתנאים הללו יגרום לסגירת התהליך אם רץ, ולאי הפעלתו אם לא רץ.
לתיאור מלא של המגבלות השונות, ולרשימת ה- API’s שלא ניתן להפעיל מתוך Agent:
דוגמאת קוד
להלן קטעי קוד שמדגימים כיצד ניתן ליצור Background Agents משני הסוגים.
Code Snippet
- public class TaskScheduler : ScheduledTaskAgent
- {
- /// <summary>
- /// Agent that runs a scheduled task
- /// </summary>
- /// <param name="task">
- /// The invoked task
- /// </param>
- /// <remarks>
- /// This method is called when a periodic or resource intensive task is invoked
- /// </remarks>
- protected override void OnInvoke(ScheduledTask task)
- {
- if (task is PeriodicTask)
- {
- // Run periodic task.
- RunTask("Periodic Task");
- }
- else
- {
- // Run resource intensive task.
- RunTask("Resource Intensive Task");
- }
- NotifyComplete();
- }
- private static void RunTask(string taskType)
- {
- int start = Environment.TickCount;
- for (int ellapsed = 0; ellapsed < 20000; ellapsed = Environment.TickCount - start)
- {
- Debug.WriteLine(string.Format("{0} running for {1:N1} seconds", taskType, ellapsed / (double)1000));
- Thread.Sleep(500);
- }
- }
- }
כפי שניתן לראות בדוגמה, ה- Agent שלנו הינו TaskScheduler שיורש מ- ScheduledTaskAgent.
המטודה OnInvoke פועלת בכל פעם שה- Agent מופעל. כאן ניתן בעזרת הפרמטר task לדעת אם נוצר PeriodicTask או ResourceIntensiveTask ולפעול בהתאם. בדוגמה פשוטה זו, מודפסת הודעה ל- Debug Output כל 500ms למשך 20 שניות (זכרו, במקרה של Periodic זמן פעולת ה- Agent אינו עולה על 15 שניות).
Visual Studio Template for Creating Agents
כדי ליצור Background Agent מ- Visual Studio, יש ליצור פרוייקט חדש מסוג: Windows Phone Scheduled Task.
הפרוייקט שנוצר הינו מסוג DLL ואינו רץ בזכות עצמו, אלא יש ליצור את האפליקציה שאחראית על- Agent זה. האפליקציה צריכה לרשום ולקבוע את סוג ה- Agent.
כעת, אחרי שיצרתם Agent ואפליקצית Phone רגילה, יש להוסיף Reference לפרוייקט שמכיל את ה- Agent, ולהכניס את הקוד הבא:
Code Snippet
- private void StartPeriodicAgent()
- {
- var periodicTask = ScheduledActionService.Find(PeriodicTaskName) as PeriodicTask;
- if (periodicTask == null)
- {
- periodicTask = new PeriodicTask(PeriodicTaskName)
- {
- Description = "Periodic Task Test"
- };
- ScheduledActionService.Add(periodicTask);
- #if(DEBUG_AGENT)
- ScheduledActionService.LaunchForTest(PeriodicTaskName, TimeSpan.FromSeconds(0));
- #endif
- }
- else
- {
- if (periodicTask.IsEnabled)
- {
- StopPeriodicAgent();
- StartPeriodicAgent();
- }
- else
- {
- MessageBox.Show("Background agents for this application have been disabled by the user.");
- }
- }
- }
- private void StopPeriodicAgent()
- {
- try
- {
- ScheduledActionService.Remove(PeriodicTaskName);
- }
- catch
- {
- }
- }
הקוד מדגים כיצד ליצור Periodic Task ולרשום אותו. תחילה יש לבדוק אם כבר קיים Task כזה במערכת. לכל Task יש שם ייחודי, וניתן לבדוק אם קיים בעזרת: ScheduledActionService.Find(taskName). אם קיים וזמין, מסירים את הנוכחי ויוצרים חדש במקומו. אם לא קיים, יוצרים חדש, נותנים לו שם ייחודי ותיאור למשתמש, כדי שנוכל לאתר אותו בהמשך.
ניתן לראות את ה- Agents השונים דרך מסך Settings, Applications של הטלפון או האמולטור.
במקרה שלנו, ה- Agent מופיע כשייך לאפליקציה הראשית. אם לוחצים על ה- Agent, ניתן לראות את התיאור שקיבל כשנוצר.
כדי לבדוק את ה- Agent באמולטור או על הטלפון בזמן Debugging, יש לקרוא למטודה ScheduleAgentService.LaunchForTest עם שם ה- Agent וזמן התחלת פעולה. מטודה זו פועלת רק אם ה- Debugger מקושר.
מה בפוסט הבא?
Reminders and Alarms