תהליכים שפועלים ברקע יכולים לצרוך הרבה זיכרון וסוללה. לדוגמה, הודעה מרומזת עשויה להפעיל הרבה תהליכי רקע שנדרשים להאזין לה, גם אם התהליכים האלה לא מבצעים הרבה עבודה. המצב הזה משפיע באופן משמעותי על הביצועים של המכשיר ועל חוויית המשתמש.
כדי למנוע הגבלות של המערכת, חשוב להשתמש ב-API המתאים למשימת הרקע. במאמר העזרה סקירה כללית על משימות ברקע מוסבר איך לבחור את ה-API המתאים לצרכים שלכם.
הגבלות שהמשתמשים יוזמים
אם אפליקציה מסוימת מציגה חלק מההתנהגויות הבעייתיות שמתוארות בתפקוד האפליקציה, המערכת מבקשת מהמשתמש להגביל את הגישה של האפליקציה למשאבי המערכת.
אם המערכת מזהה שאפליקציה צורכת יותר מדי משאבים, היא שולחת למשתמש הודעה ומציעה לו להגביל את הפעולות של האפליקציה. התנהגויות שיכולות להפעיל את ההודעה כוללות:
- שימוש מוגזם בחסימות מצב שינה: חסימת מצב שינה חלקית אחת למשך שעה כשהמסך כבוי
- שירותי רקע מוגזמים: אם האפליקציה מטרגטת רמות API נמוכות מ-26 ויש לה שירותי רקע מוגזמים
ההגבלות המדויקות שמוטלות נקבעות על ידי יצרן המכשיר. לדוגמה, בגרסאות של AOSP, אפליקציות מוגבלות לא יכולות להריץ משימות, להפעיל התראות או להשתמש ברשת, אלא אם האפליקציה פועלת בחזית.
הגבלות על קבלת שידורים של פעילות ברשת
אפליקציות לא מקבלות שידורים של CONNECTIVITY_ACTION אם הן נרשמות לקבל אותם במניפסט שלהן, ותהליכים שתלויים בשידור הזה לא יתחילו. זה יכול להוות בעיה לאפליקציות שרוצות להאזין לשינויים ברשת או לבצע פעילויות רשת בכמות גדולה כשהמכשיר מתחבר לרשת ללא הגבלת נפח. יש כבר כמה פתרונות לעקיפת ההגבלה הזו במסגרת Android, אבל הבחירה בפתרון הנכון תלויה במטרה של האפליקציה.
קביעת זמנים לעבודה בחיבורים ללא הגבלת נפח
כשיוצרים WorkRequest, מוסיפים NetworkType.UNMETERED Constraint.
fun scheduleWork(context: Context) {
val workManager = WorkManager.getInstance(context)
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
)
.build()
workManager.enqueue(workRequest)
}
כשהתנאים לעבודה מתקיימים, האפליקציה מקבלת קריאה חוזרת להפעלת השיטה doWork() במחלקה Worker שצוינה.
מעקב אחרי החיבור לרשת בזמן שהאפליקציה פועלת
אפליקציות שפועלות עדיין יכולות להאזין לCONNECTIVITY_CHANGE עם BroadcastReceiver רשום. עם זאת, ה-API ConnectivityManager מספק שיטה חזקה יותר לבקשת קריאה חוזרת רק כשמתקיימים תנאים ספציפיים ברשת.
אובייקטים של NetworkRequest מגדירים את הפרמטרים של הקריאה החוזרת (callback) של הרשת במונחים של NetworkCapabilities. אתם יוצרים אובייקטים של NetworkRequest באמצעות המחלקה NetworkRequest.Builder. registerNetworkCallback
ואז מעבירה את האובייקט NetworkRequest למערכת. כשמתקיימים התנאים של הרשת, האפליקציה מקבלת קריאה חוזרת להפעלת ה-method onAvailable() שמוגדר במחלקה ConnectivityManager.NetworkCallback.
האפליקציה ממשיכה לקבל קריאות חוזרות (callback) עד שהיא יוצאת או עד שהיא קוראת ל-unregisterNetworkCallback().
הגבלות על קבלת שידורים של תמונות וסרטונים
אפליקציות לא יכולות לשלוח או לקבל שידורים מסוג ACTION_NEW_PICTURE או ACTION_NEW_VIDEO. ההגבלה הזו עוזרת לצמצם את ההשפעות על הביצועים ועל חוויית המשתמש במקרים שבהם כמה אפליקציות צריכות להתעורר כדי לעבד תמונה או סרטון חדשים.
קביעה של רשויות התוכן שהפעילו את העבודה
ההרשאה WorkerParameters מאפשרת לאפליקציה לקבל מידע שימושי על ספקי התוכן ומזהי ה-URI שהפעילו את העבודה:
List<Uri> getTriggeredContentUris()
מחזירה רשימה של כתובות URI שהפעילו את העבודה. הערך יהיה ריק אם אף URI לא הפעיל את העבודה (לדוגמה, העבודה הופעלה בגלל מועד אחרון או סיבה אחרת), או אם מספר ה-URI שהשתנו גדול מ-50.
List<String> getTriggeredContentAuthorities()
מחזירה רשימת מחרוזות של רשויות תוכן שהפעילו את העבודה. אם הרשימה שמוחזרת לא ריקה, משתמשים ב-getTriggeredContentUris() כדי לאחזר את הפרטים של כתובות ה-URI שהשתנו.
קוד לדוגמה הבא מבצע החלפה של השיטה CoroutineWorker.doWork() ומתבצעת הקלטה של רשויות התוכן ושל כתובות ה-URI שהפעילו את העבודה:
class MyWorker(
appContext: Context,
params: WorkerParameters
): CoroutineWorker(appContext, params)
override suspend fun doWork(): Result {
StringBuilder().apply {
append("Media content has changed:\n")
params.triggeredContentAuthorities
.takeIf { it.isNotEmpty() }
?.let { authorities ->
append("Authorities: ${authorities.joinToString(", ")}\n")
append(params.triggeredContentUris.joinToString("\n"))
} ?: append("(No content)")
Log.i(TAG, toString())
}
return Result.success()
}
}
בדיקת אפליקציה בהתאם להגבלות המערכת
אופטימיזציה של האפליקציות כדי להפעיל אותן במכשירים עם זיכרון נמוך או בתנאים של זיכרון נמוך, יכולה לשפר את הביצועים ואת חוויית המשתמש. הסרת תלות בשירותי רקע ובמקלט הודעה מרומזת שרשום במניפסט יכולה לעזור לאפליקציה לפעול טוב יותר במכשירים כאלה. מומלץ לבצע אופטימיזציה של האפליקציה כך שהיא תפעל ללא שימוש בתהליכי הרקע האלה בכלל.
יש עוד כמה פקודות של Android Debug Bridge (ADB) שיכולות לעזור לכם לבדוק את התנהגות האפליקציה כשמבטלים את תהליכי הרקע האלה:
כדי לדמות תנאים שבהם שידורים מרומזים ושירותי רקע לא זמינים, מזינים את הפקודה הבאה:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreכדי להפעיל מחדש שידורים מרומזים ושירותים ברקע, מזינים את הפקודה הבאה:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
אופטימיזציה נוספת של האפליקציה
במסמכי התיעוד בנושא אופטימיזציה של השימוש בסוללה עבור ממשקי API לתזמון משימות מוסבר על דרכים טובות נוספות לאופטימיזציה של התנהגות משימות ברקע.