בדף הזה מפורטות כמה מהסיבות הנפוצות לכשלים בשירותים שפועלים בחזית, והוא עוזר לכם לזהות את הגורם לבעיה.
במסמך הזה נדון בבעיות הבאות:
לפני שמתחילים לפתור את הבעיה
בדיקת שינויים מהתקופה האחרונה בשירותים שפועלים בחזית
אם משתמשים בשירותים שפועלים בחזית בצורה לא נכונה, הם עלולים להשפיע לרעה על הביצועים של המכשיר ועל חיי הסוללה. לכן, בגרסאות של פלטפורמת Android מתבצעים לעיתים קרובות שינויים בהתנהגות של שירותים שפועלים בחזית כדי לצמצם את ההשפעות השליליות האלה.
אם נתקלתם בבעיות בשירותים שפועלים בחזית, כדאי לעיין במסמכי התיעוד בנושא שינויים בשירותים שפועלים בחזית ולבדוק אם יש שינויים מהזמן האחרון שיכולים להסביר את הבעיות. חשוב במיוחד לבדוק אם יש שינויים במקרים הבאים:
- קוד של שירות שפועל בחזית שפעל בעבר נכשל עכשיו
- התחלתם לבדוק גרסה חדשה של פלטפורמה, או ששיניתם את רמת ה-API שמטורגטת על ידי האפליקציה
בנוסף, אם אתם בודקים את המכשיר שלכם בגרסת טרום-השקה למפתחים של הפלטפורמה, הקפידו לבדוק את הגרסה העדכנית ביותר של מסמכי התיעוד של גרסת טרום-השקה למפתחים.
שגיאות מסוג 'האפליקציה לא מגיבה (ANR)'
בנסיבות מסוימות, אפליקציה צפויה לסגור את השירות שלה בחזית. אם האפליקציה לא מפסיקה את השירות, המערכת מפסיקה את השירות ומפעילה שגיאה מסוג האפליקציה לא מגיבה (ANR).
שירות קצר פועל יותר מדי זמן וגורם ל-ANR
שירותים שפועלים בחזית שמשתמשים בסוג short service צריכים להסתיים במהירות, תוך שלוש דקות בערך. כשהזמן נגמר, המערכת מפעילה את השיטה 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()
באופן מיידי.
חריגים לשירותים שפועלים בחזית
בקטע הזה מתוארות כמה בעיות בשירותים שפועלים בחזית שיכולות לגרום למערכת להחזיר חריגה. אם האפליקציה לא תופסת את החריגה, המשתמש יראה תיבת דו-שיח שמודיעה לו שהאפליקציה הפסיקה לפעול.
במקרים מסוימים, המערכת יוצרת חריגה פנימית. במקרים כאלה, אפשר לבדוק את מעקב המחסנית כדי לגלות מה הייתה החריגה, ואפשר לבדוק את Logcat כדי לקבל מידע מפורט יותר על השגיאה.
חריגה פנימית: חלף הזמן הקצוב
המערכת מטילה מגבלה על משך הזמן שבו שירותים קדמיים של סנכרון נתונים ועיבוד מדיה יכולים לפעול כשהאפליקציה ברקע. אם השירות חורג מהמגבלה הזו, המערכת קוראת לשיטת Service.onTimeout(int,int)
של השירות. לשירות יש כמה שניות להתקשר אל stopSelf()
. אם השירות לא מפסיק את עצמו, המערכת יוצרת RemoteServiceException
פנימי שגורם לקריסה של האפליקציה.
אבחון:
כדי לגלות מה הייתה החריגה, צריך לעיין במעקב אחר מחסנית הקריאות. אפשר גם לבדוק את 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
.
אבחון:
כדי לגלות מה הייתה החריגה, צריך לעיין במעקב אחר מחסנית הקריאות. אפשר גם לבדוק את Logcat כדי לקבל פרטים נוספים על השגיאה. במקרה כזה, הודעת השגיאה הבאה מופיעה ב-Logcat:
android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()
הוספה:
חשוב לוודא שכל השירותים החדשים שפועלים בחזית קוראים ל-ServiceCompat.startForeground()
תוך כמה שניות.
ForegroundServiceStartNotAllowedException
שגיאה:
המערכת מחזירה ForegroundServiceStartNotAllowedException
.
הסיבה:
בדרך כלל זה קורה כשהאפליקציה מפעילה שירות שפועל בחזית מהרקע, כשאין פטור תקף.
החל מ-Android 12 (רמת 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
אם ביקשתם את ההרשאות הנדרשות, אבל הפעלתם את השירות שפועל בחזית לפני שאישרתם שההרשאות הנדרשות ניתנו.
- יכול להיות שתקבלו
הוספה:
לפני שמפעילים את השירות שפועל בחזית, צריך לבקש את כל ההרשאות המתאימות לשירות שפועל בחזית ולוודא שמתקיימות כל הדרישות המוקדמות האחרות בזמן הריצה.