בדף הזה מפורטות כמה מהסיבות הנפוצות לכשלים בשירותי חזית, ואנחנו עוזרים לכם לזהות את הגורם לבעיה.
במסמך הזה מפורטות הבעיות הבאות:
לפני פתרון הבעיות
בדיקת שינויים אחרונים בשירותים שפועלים בחזית
שימוש שגוי בשירותים שפועלים בחזית עלול להשפיע לרעה על הביצועים של המכשיר ועל חיי הסוללה. לכן, לעיתים קרובות אנחנו מבצעים שינויים בהתנהגות של שירותים שפועלים בחזית במהדורות של פלטפורמת Android, כדי להגביל את ההשפעות השליליות האלה.
אם נתקלת בבעיות בשירותים בחזית, כדאי לעיין במסמכים בנושא שינויים בשירותים בחזית ולבדוק אם יש שינויים מהזמן האחרון שיכולים להסביר את הבעיות. חשוב במיוחד לבדוק אם יש שינויים במקרים הבאים:
- קוד של שירות שפועל בחזית שפעל בעבר נכשל עכשיו
- התחלתם לבדוק גרסה חדשה של פלטפורמה או שיניתם את רמת ה-API שאליה האפליקציה שלכם מטרגטת
בנוסף, אם אתם בודקים את המכשיר בגרסה טרום-השקה למפתחים של הפלטפורמה, חשוב לבדוק את הגרסה העדכנית ביותר של מסמכי התיעוד לגרסה טרום-השקה למפתחים.
שגיאות מסוג 'האפליקציה לא מגיבה (ANR)'
בנסיבות מסוימות, אפליקציה אמורה להשבית את השירות שלה בחזית. אם האפליקציה לא תפסיק את השירות, המערכת תפסיק אותו ותגרום לשגיאה מסוג האפליקציה לא מגיבה (ANR).
שירות קצר פועל יותר מדי זמן וגורם ל-ANR
שירותים שפועלים בחזית ומשתמשים בשירות קצר חייבים להשלים את הפעולה במהירות, תוך כשלוש דקות. כשהזמן פג, המערכת מפעילה את השיטה Service.onTimeout(int,int)
של השירות. לשירות יש כמה שניות להתקשר אל stopSelf()
. אם השירות לא יעצור את עצמו, המערכת תפעיל שגיאה מסוג 'האפליקציה לא מגיבה'.
אבחון:
אם אירוע ה-ANR נגרם בגלל ששירות בחזית לא הצליח להפסיק את עצמו, המערכת תשליך חריגה פנימית. כדי לוודא שזו הבעיה, אפשר לבדוק את דוחות ה-ANR. אם זו הבעיה, הדוח יכלול את ההודעה הבאה:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"
הפתרון:
חשוב לוודא שכל השירותים בחזית עם מגבלת זמן מסיימים את העבודה ומפעילים את stopForeground(int)
במסגרת מגבלת הזמן של המערכת.
להטמיע את Service.onTimeout(int,int)
בשירותים שפועלים בחזית.
חשוב לוודא שההטמעה של השיטה הזו מפעילה את stopSelf()
באופן מיידי.
חריגים לשירותים שפועלים בחזית
בקטע הזה מתוארות כמה בעיות בשירותים בחזית שיכולות לגרום למערכת להוציא חריגה. אם האפליקציה לא תתעד את החריגה, תופיע תיבת דו-שיח עם הודעה על כך שהאפליקציה הופסקה.
במקרים מסוימים, המערכת תיצור חריגה פנימית. במקרים כאלה, תוכלו לבדוק מה הייתה החריגה על ידי הצגת מעקב ה-stack, ולבדוק ב-Logcat מידע מפורט יותר על השגיאה.
חריגה פנימית: זמן הקצוב פג
המערכת מטילה מגבלה על משך הזמן שבו שירותי חזית של סנכרון נתונים ועיבוד מדיה יכולים לפעול בזמן שהאפליקציה ברקע. אם השירות חורג מהמגבלה הזו, המערכת קוראת לשיטה Service.onTimeout(int,int)
של השירות. לשירות יש כמה שניות להתקשר ל-stopSelf()
. אם השירות לא יעצור את עצמו, המערכת תיצור RemoteServiceException
פנימי שגורם לקריסה של האפליקציה.
אבחון:
כדי לבדוק מה הייתה החריגה, אפשר לעיין ב-stack trace, ואפשר לבדוק ב-Logcat כדי לקבל פרטי שגיאה מפורטים יותר. במקרה כזה, הודעת השגיאה הבאה תופיע ב-Logcat:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"
הפתרון:
חשוב לוודא שכל השירותים בחזית עם מגבלת זמן מסיימים את העבודה ומפעילים את stopForeground(int)
במסגרת מגבלת הזמן של המערכת.
השירותים שפועלים בחזית צריכים ליישם את Service.onTimeout(int,int)
.
חשוב לוודא שההטמעה של השיטה הזו מפעילה את stopSelf()
באופן מיידי.
חריג פנימי: ForegroundServiceDidNotStartInTimeException
כשמפעילים שירות באמצעות קריאה ל-context.startForegroundService()
, יש לשירות כמה שניות כדי להפוך לשירות שפועל בחזית באמצעות קריאה ל-ServiceCompat.startForeground()
.
אם השירות לא עושה זאת, הוא יוצר אירוע פנימי מסוג ForegroundServiceDidNotStartInTimeException
.
אבחון:
כדי לבדוק מה הייתה החריגה, אפשר לעיין ב-stack trace, ואפשר לבדוק ב-Logcat כדי לקבל פרטי שגיאה מפורטים יותר. במקרה כזה, הודעת השגיאה הבאה תופיע ב-Logcat:
android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()
הפתרון:
חשוב לוודא שכל השירותים החדשים שנוצרו שפועלים בחזית קוראים ל-ServiceCompat.startForeground()
תוך כמה שניות.
ForegroundServiceStartNotAllowedException
שגיאה:
המערכת גורמת להשלכה של ForegroundServiceStartNotAllowedException
.
הסיבה:
בדרך כלל, הסיבה לכך היא שהאפליקציה מפעילה שירות שפועל בחזית מהרקע כשאין פטור תקף.
החל מגרסה 12 של Android (רמת API 31), לא מורשים לאפליקציות להפעיל שירותים שפועלים בחזית בזמן שהאפליקציה פועלת ברקע, מלבד כמה חריגים ספציפיים.
אם תנסו להפעיל שירות שפועל בחזית מהרקע ולא תתעמדו בדרישות של אחת מההחרגות, המערכת תשליך את השגיאה ForegroundServiceStartNotAllowedException
. המערכת עושה זאת גם אם אתם לא עומדים בדרישות לפטור.
לדוגמה, יכול להיות שבאפליקציה יש לחצן שהמשתמש יכול ללחוץ עליו, וכתוצאה מכך האפליקציה מבצעת עיבוד מסוים ואז מפעילה שירות שפועל בחזית. במקרה כזה, יש סכנה שהמשתמש ילחץ על הלחצן ולאחר מכן מיד יעביר את האפליקציה לרקע. לאחר מכן, האפליקציה תנסה להפעיל את השירות מהרקע. אם האפליקציה לא עומדת באחד מהפטורים שצוינו, המערכת תשליך הודעת שגיאה מסוג ForegroundServiceStartNotAllowedException
.
בנוסף, לחלק מהפטורים יש מגבלה זמנית קצרה. לדוגמה, יש פטור קצר אם האפליקציה מפעילה שירות בחזית בתגובה להודעת FCM בעדיפות גבוהה. אם לא תפעילו את השירות במהירות מספקת, יוצג לכם ForegroundServiceStartNotAllowedException
.
לפעמים, כשאנחנו משיקים גרסאות חדשות של Android, ההחרגות הספציפיות הופכות למחמירות יותר. אם שיניתם את גרסת Android שאליה האפליקציה שלכם מטרגטת, כדאי לעיין במסמכים בנושא שינויים בשירותי חזית ולוודא שהאפליקציה עדיין עומדת בקריטריונים של אחת מהפטרונות המותרים.
הפתרון:
לשנות את תהליך העבודה של האפליקציה כך שלא יהיה צורך להפעיל שירותים בחזית בזמן שהאפליקציה פועלת ברקע, או לוודא שהאפליקציה עומדת באחד מהפטורים.
אתם יכולים להשתמש ברכיבים מודעים למחזור חיים כדי לנהל את מחזור החיים של האפליקציה, וכך למנוע ניסיון לא מכוון להפעיל שירות שפועל בחזית מהרקע.
SecurityException
שגיאה:
המערכת תיצור את ההודעהSecurityException
.
הסיבה:
האפליקציה ניסתה להפעיל שירות שפועל בחזית בלי ההרשאות הנדרשות.
- אם אפליקציה מטרגטת ל-Android 9 (רמת API 28) ואילך, היא צריכה את ההרשאה
FOREGROUND_SERVICE
כדי להפעיל שירות שפועל בחזית. - אם אפליקציה מטרגטת ל-Android 14 (רמת API 34) ואילך, היא צריכה לעמוד בכל הדרישות המוקדמות לסוג השירות שפועל בחזית שלה. הדרישות המקדימות האלה מפורטות במאמר העזרה בנושא סוגים של שירותים שפועלים בחזית. חשוב לשים לב במיוחד לדרישות הבאות:
- יש כמה סוגים של שירותים שפועלים בחזית שדורשים הרשאות ספציפיות בסביבת זמן הריצה. לדוגמה, לשירות שפועל בחזית להעברת הודעות מרחוק צריכה להיות ההרשאה
FOREGROUND_SERVICE_REMOTE_MESSAGING
.
- יש כמה סוגים של שירותים שפועלים בחזית שדורשים הרשאות ספציפיות בסביבת זמן הריצה. לדוגמה, לשירות שפועל בחזית להעברת הודעות מרחוק צריכה להיות ההרשאה
- במקרים מסוימים, יש הגבלות נוספות על ההרשאות שנדרשות לסוגים מסוימים של שירותים שפועלים בחזית בזמן השימוש בהם. ההרשאות האלה מוענקות לאפליקציה רק כשהיא בחזית (למעט כמה יוצאים מן הכלל). כלומר, גם אם האפליקציה ביקשה אחת מההרשאות האלה וקיבלתם אותה, אם האפליקציה תנסה להפעיל את השירות שפועל בחזית בזמן שהיא ברקע, המערכת תשליך הודעת
SecurityException
גם אם לאפליקציה יש פטור להפעלת שירות שפועל בחזית מהרקע. מידע נוסף זמין במאמר הגבלות על הפעלת שירותים שפועלים בחזית שצריכים הרשאות לשימוש.- יכול להיות שתקבלו את הערך
SecurityException
אם ביקשת את ההרשאות הנדרשות אבל הפעלת את השירות בחזית לפני שמוודאים שההרשאות הנדרשות אושרו.
- יכול להיות שתקבלו את הערך
הפתרון:
לפני שמפעילים את השירות שפועל בחזית, צריך לבקש את כל ההרשאות המתאימות לשירות שפועל בחזית, ולוודא שעמדתם בכל הדרישות המוקדמות האחרות בסביבת זמן הריצה.