סקירה כללית על משימות ברקע

אפליקציות צריכות לעיתים קרובות לבצע יותר מפעולה אחת בו-זמנית. ממשקי ה-API של Android מספקים הרבה דרכים שונות לעשות את זה. חשוב מאוד לבחור את האפשרות הנכונה. אפשרות מסוימת יכולה להתאים למצב אחד, אבל לא להתאים בכלל למצב אחר. בחירה בממשקי API לא מתאימים עלולה לפגוע בביצועים של האפליקציה או ביעילות השימוש במשאבים, מה שעלול לרוקן את הסוללה ולפגוע בביצועים של המכשיר של המשתמש באופן כללי. במקרים מסוימים, בחירה בגישה הלא נכונה עלולה למנוע את הופעת האפליקציה בחנות Play.

במאמר הזה נסביר על האפשרויות השונות שעומדות לרשותכם, ונעזור לכם לבחור את האפשרות שמתאימה למצב שלכם.

הסברים על המונחים

יכול להיות שמונחים חשובים שקשורים למשימות ברקע ישמשו בכמה דרכים סותרות. לכן חשוב להגדיר את המונחים שלנו.

אם אפליקציה פועלת ברקע, המערכת מטילה עליה מספר מגבלות. (לדוגמה, ברוב המקרים, אפליקציה שפועלת ברקע לא יכולה להפעיל שירותים בחזית).

במסמך הזה, המונח "משימה" מתייחס לפעולה שהאפליקציה מבצעת מחוץ לתהליך העבודה הראשי שלה. כדי לוודא שכולם מבינים את הנושא, חילקנו את סוגי המשימות לשלוש קטגוריות עיקריות: עבודה אסינכרונית, ממשקי API לתזמון משימות ושירותים שפועלים בחזית.

בחרו את האפשרות המתאימה

ברוב המקרים, כדי להבין באילו ממשקי API כדאי להשתמש, צריך להבין לאיזו קטגוריה המשימה שייכת (עבודה אסינכרונית, ממשקי API לתזמון משימות או שירותים שפועלים בחזית).

אם אתם עדיין לא בטוחים, אתם יכולים להשתמש בתרשימי הזרימה שאנחנו מספקים, שמוסיפים עוד ניואנסים להחלטה. בהמשך המאמר נפרט על כל אחת מהאפשרויות האלה.

יש שני תרחישים עיקריים שצריך להביא בחשבון לגבי משימות ברקע:

לשני התרחישים האלה יש עצי החלטות משלהם.

עבודה אסינכרונית

במקרים רבים, האפליקציה צריכה לבצע פעולות בו-זמנית רק כשהיא פועלת בחזית. לדוגמה, יכול להיות שהאפליקציה צריכה לבצע חישוב שלוקח הרבה זמן. אם החישוב היה מתבצע בשרשור ה-UI, המשתמש לא היה יכול לבצע פעולות באפליקציה עד שהחישוב היה מסתיים, וזה היה עלול לגרום לשגיאת ANR. במקרה כזה, האפליקציה צריכה להשתמש באפשרות של עבודה אסינכרונית.

אפשרויות נפוצות לעבודה אסינכרונית כוללות קורוטינות של Kotlin ושרשורים של Java. מידע נוסף זמין במסמכי התיעוד של עבודה אסינכרונית. חשוב לציין שבניגוד לממשקי ה-API של משימות ברקע, אין הבטחה שהעבודה האסינכרונית תסתיים אם האפליקציה תפסיק להיות בשלב תקין במחזור החיים (לדוגמה, אם האפליקציה תצא מהחזית).

ממשקי API לתזמון משימות

ממשקי ה-API לתזמון משימות הם אפשרות גמישה יותר כשצריך לבצע משימות שצריכות להימשך גם אם המשתמש יוצא מהאפליקציה. ברוב המקרים, האפשרות הטובה ביותר להפעלת משימות ברקע היא להשתמש ב-WorkManager, אבל במקרים מסוימים יכול להיות שיהיה מתאים להשתמש ב-API של הפלטפורמה JobScheduler.

‫WorkManager היא ספרייה מתקדמת שמאפשרת להגדיר משימות פשוטות או מורכבות לפי הצורך. אתם יכולים להשתמש ב-WorkManager כדי לתזמן משימות שיפעלו בזמנים ספציפיים, או לציין את התנאים שבהם המשימה צריכה לפעול. אתם יכולים אפילו להגדיר שרשראות של משימות, כך שכל משימה תפעל בתורה ותעביר את התוצאות שלה למשימה הבאה. כדי להבין את כל האפשרויות הזמינות, כדאי לקרוא את רשימת התכונות של WorkManager.

דוגמאות לתרחישים נפוצים שבהם משימות פועלות ברקע:

  • אחזור נתונים מהשרת מדי פעם
  • אחזור נתוני חיישנים (לדוגמה, נתונים של מונה צעדים)
  • קבלת נתוני מיקום תקופתיים (צריך לקבל את ההרשאה ACCESS_BACKGROUND_LOCATION ב-Android מגרסה 10 ואילך)
  • העלאת תוכן על סמך טריגר תוכן, כמו תמונות שנוצרו על ידי המצלמה

שירותים שפועלים בחזית

שירותים שפועלים בחזית הם דרך יעילה להפעיל באופן מיידי משימות שאסור להפריע להן. עם זאת, שירותים שפועלים בחזית עלולים להעמיס על המכשיר, ולפעמים יש להם השלכות על הפרטיות והאבטחה. לכן, המערכת מגבילה מאוד את האופן שבו אפליקציות יכולות להשתמש בשירותים שפועלים בחזית ואת המועדים שבהם הן יכולות לעשות זאת. לדוגמה, שירות שפועל בחזית צריך להיות גלוי למשתמש, וברוב המקרים אפליקציות לא יכולות להפעיל שירותים בחזית כשהן פועלות ברקע. מידע נוסף זמין במסמכי התיעוד של שירותים שפועלים בחזית.

יש שתי שיטות ליצירת שירות שפועל בחזית. אתם יכולים להצהיר על Service משלכם ולציין שהשירות פועל בחזית באמצעות קריאה ל-Service.startForeground(). אפשר גם להשתמש ב-WorkManager כדי ליצור שירות שפועל בחזית, כמו שמתואר במאמר תמיכה ב-workers שפועלים לאורך זמן. עם זאת, חשוב לדעת ששירות שפועל בחזית שנוצר על ידי WorkManager צריך לציית לאותן הגבלות כמו כל שירות אחר שפועל בחזית. ‫WorkManager פשוט מספק כמה ממשקי API נוחים כדי לפשט את היצירה של שירות שפועל בחזית.

ממשקי API חלופיים

המערכת מציעה ממשקי API חלופיים שנועדו לשפר את הביצועים בתרחישים ספציפיים יותר. אם יש API חלופי לתרחיש לדוגמה שלכם, מומלץ להשתמש בו במקום בשירות שפועל בחזית, כי הוא אמור לשפר את ביצועי האפליקציה. במסמכי התיעוד של סוגי השירותים שפועלים בחזית מצוין מתי יש API חלופי טוב שאפשר להשתמש בו במקום סוג מסוים של שירות שפועל בחזית.

אלה כמה מהתרחישים הנפוצים ביותר לשימוש בממשקי API חלופיים:

משימות שהמשתמש התחיל

תרשים זרימה שמראה איך לבחור את ה-API המתאים. התרשים הזה מסכם את החומר בקטע "משימות שהמשתמש התחיל".
איור 1: איך לבחור את ה-API המתאים להרצת משימה ברקע שהמשתמש הפעיל.

אם האפליקציה צריכה לבצע משימות ברקע, והפעולה מתחילה על ידי המשתמש כשהאפליקציה גלויה, ענו על השאלות הבאות כדי למצוא את הגישה הנכונה.

האם המשימה צריכה להמשיך לפעול כשהאפליקציה ברקע?

אם המשימה לא צריכה להמשיך לפעול כשהאפליקציה ברקע, כדאי להשתמש בעבודה אסינכרונית. יש כמה אפשרויות לביצוע עבודה אסינכרונית. חשוב להבין שכל האפשרויות האלה מפסיקות לפעול אם האפליקציה עוברת לרקע. (הם גם מפסיקים אם האפליקציה נסגרת). לדוגמה, אפליקציה של רשת חברתית יכולה לרענן את פיד התוכן שלה, אבל היא לא צריכה לסיים את הפעולה אם המשתמש יצא מהמסך.

האם חוויית המשתמש תיפגע אם המשימה תופסק או תתעכב?

חשוב לשקול אם חוויית המשתמש תיפגע אם משימה תידחה או תבוטל. לדוגמה, אם אפליקציה צריכה לעדכן את הנכסים שלה, יכול להיות שהמשתמש לא ישים לב אם הפעולה מתרחשת מיד או באמצע הלילה כשהמכשיר בטעינה. במקרים כאלה, כדאי להשתמש באפשרויות של עבודה ברקע.

האם זו משימה קצרה וקריטית?

אם אי אפשר לדחות את המשימה והיא תסתיים במהירות, אתם יכולים להשתמש בשירות שפועל בחזית מסוג shortService. קל יותר ליצור את השירותים האלה מאשר שירותים אחרים שפועלים בחזית, והם לא דורשים הרבה הרשאות. עם זאת, שירותים קצרים חייבים להסתיים תוך שלוש דקות.

האם יש API חלופי רק למטרה הזו?

אם המשימה לא מוסתרת מהמשתמש, יכול להיות שהפתרון הנכון הוא להשתמש בשירות שפועל בחזית. השירותים האלה פועלים ברציפות מרגע שהם מתחילים, ולכן הם בחירה טובה כשהפרעה למשימה תגרום לחוויית משתמש גרועה. לדוגמה, אפליקציה למעקב אחרי אימונים יכולה להשתמש בחיישני מיקום כדי לאפשר למשתמשים לתעד את מסלול הריצה שלהם במפה. לא כדאי לעשות את זה עם אפשרות של עבודה ברקע, כי אם המשימה תושהה, המעקב ייפסק מיד. במצב כזה, הכי הגיוני להשתמש בשירות שפועל בחזית.

עם זאת, מכיוון ששירותים שפועלים בחזית יכולים להשתמש בהרבה משאבים של המכשיר, המערכת מגבילה מאוד את המקרים שבהם אפשר להשתמש בהם ואת אופן השימוש בהם. במקרים רבים, במקום להשתמש בשירות שפועל בחזית, אתם יכולים להשתמש בממשק API חלופי שמטפל במשימה בשבילכם עם פחות בעיות. לדוגמה, אם האפליקציה צריכה לבצע פעולה כשהמשתמש מגיע למיקום מסוים, האפשרות הטובה ביותר היא להשתמש ב-geofence API במקום לעקוב אחרי מיקום המשתמש באמצעות שירות שפועל בחזית.

משימות שקשורות לאירוע

תרשים זרימה שמראה איך לבחור את ה-API המתאים. התרשים הזה מסכם את החומר בקטע "משימות בתגובה לאירוע".
איור 2: איך לבחור את ה-API המתאים להפעלת משימה ברקע שמופעלת על ידי אירוע.

לפעמים אפליקציה צריכה לבצע פעולה ברקע בתגובה לטריגר, למשל:

זה יכול להיות טריגר חיצוני (כמו הודעת FCM) או תגובה להתראה שהוגדרה על ידי האפליקציה עצמה. לדוגמה, משחק יכול לקבל הודעת FCM שמורה לו לעדכן נכסים מסוימים.

אם אתם בטוחים שהמשימה תסתיים תוך כמה שניות, השתמשו בעבודה אסינכרונית כדי לבצע את המשימה. המערכת תאפשר לאפליקציה כמה שניות לבצע משימות כאלה, גם אם האפליקציה הייתה ברקע.

אם המשימה תימשך יותר מכמה שניות, יכול להיות שכדאי להפעיל שירות בחזית כדי לטפל במשימה. למעשה, גם אם האפליקציה פועלת כרגע ברקע, יכול להיות שהיא תוכל להפעיל שירות שפועל בחזית, אם המשימה הופעלה על ידי המשתמש והיא נכללת באחד מהפטורים המאושרים מההגבלות על הפעלה ברקע. לדוגמה, אם האפליקציה מקבלת הודעת FCM בעדיפות גבוהה, היא יכולה להפעיל שירות שפועל בחזית גם אם היא פועלת ברקע.

אם המשימה תימשך יותר מכמה שניות, צריך להשתמש ב-Task Scheduling API.