הגבלות מערכת על עבודה ברקע

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

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

הגבלות ביוזמת המשתמש

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

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

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

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

הגבלות על קבלת שידורי פעילות ברשת

אפליקציות לא מקבלות שידורים של CONNECTIVITY_ACTION אם הן נרשמות אל לקבל אותן במניפסט ובתהליכים שתלויים בשידור הזה לא יתחיל. הפעולה הזו עלולה ליצור בעיה באפליקציות שרוצות להאזין לרשת משתנה או לבצע פעילויות בכמות גדולה ברשת כאשר המכשיר מתחבר רשת מוגדרת ללא שימוש בנתונים. יש כבר כמה פתרונות לעקוף את ההגבלה הזו קיימות ב-framework של 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)
}

כשהתנאים לעבודה מתקיימים, האפליקציה תקבל קריאה חוזרת (callback) כדי להפעיל אותה ה-method 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 שהשתנו.

הקוד לדוגמה הבא מבטל את ה-method 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 לתזמון משימות התיעוד.