מדריכים

האכיפה של איכות טכנית של סוללה כבר כאן: איך לבצע אופטימיזציה לתרחישי שימוש נפוצים של נעילת השכמה

משך הקריאה: 8 דקות
הצגת הפרופיל של Alice Yuan
Alice Yuan מהנדס/ת קשרי מפתחים, Android

מכיוון שצריכת סוללה מוגזמת היא אחד הנושאים שהכי חשובים למשתמשי Android, ‏ Google נוקטת צעדים משמעותיים כדי לעזור למפתחים ליצור אפליקציות חסכוניות יותר בצריכת החשמל. ב-1 במרץ 2026, התחלנו להשיק בחנות Google Play את הטיפולים הטכניים באיכות של חסימת מצב שינה כדי לשפר את התרוקנות הסוללה. הטיפול הזה יושק בהדרגה באפליקציות המושפעות במהלך השבועות הקרובים. לאפליקציות שחורגות באופן עקבי מהסף של "שימוש מופרז בחסימה חלקית של מצב השינה" במדד תפקוד האפליקציה ב-Android, עשויות להיות השפעות מוחשיות על הנוכחות שלהן בחנות, כולל אזהרות בדף האפליקציה בחנות והחרגה מפלטפורמות לגילוי אפליקציות, כמו המלצות.

appDetails.png

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

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

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

שימוש בשירות שפועל בחזית לעומת נעילת השכמה חלקית

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

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

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

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

ספריות של צד שלישי שמקבלות הרשאות לביטול מצב השינה

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

  • בודקים את מדדי 'תפקוד האפליקציה': מוצאים את השם המדויק של חסימת מצב השינה הבעייתית במרכז הבקרה 'חסימות מצב שינה חלקיות מוגזמות'. כדאי להשוות את השם הזה להנחיות שבמאמר זיהוי חסימות של מצב השינה שנוצרו על ידי ממשקי API אחרים כדי לבדוק אם הוא נוצר על ידי API מוכר של המערכת או על ידי ספריית Jetpack. אם כן, יכול להיות שתצטרכו לבצע אופטימיזציה של השימוש ב-API, ותוכלו להיעזר בהנחיות המומלצות.
  • תיעוד עקבות המערכת: אם קשה לזהות את חסימת מצב שינה, אפשר לשחזר את הבעיה של חסימת מצב שינה באופן מקומי באמצעות תיעוד עקבות המערכת ולבדוק אותה באמצעות ממשק המשתמש של Perfetto. מידע נוסף על אופן הפעולה מופיע בקטע ניפוי באגים בסוגים אחרים של נעילות השכמה מוגזמות בפוסט הזה בבלוג.
  • הערכת חלופות: אם ספרייה לא יעילה של צד שלישי אחראית לבעיה ואי אפשר להגדיר אותה כך שתתחשב בחיי הסוללה, כדאי להודיע על הבעיה לבעלי ה-SDK, למצוא SDK חלופי או לבנות את הפונקציונליות באופן עצמאי.

תרחישים נפוצים של חסימת מצב השינה

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

העלאה או הורדה ביוזמת המשתמש

תרחישים לדוגמה: 

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

איך מצמצמים את חסימות מצב השינה: 

  • לא להפעיל חסימת מצב שינה ידנית. במקום זאת, אפשר להשתמש ב-User-Initiated Data Transfer (UIDT) API. זהו הנתיב המיועד למשימות ארוכות של העברת נתונים שהמשתמש יזם, והוא מוחרג מחישובים של חסימת מצב שינה מוגזמת.

סנכרונים חד-פעמיים או תקופתיים ברקע

תרחישים לדוגמה: 

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

איך מצמצמים את השימוש בחסימות של מצב שינה: 

  • לא להפעיל חסימת מצב שינה ידנית. משתמשים ב-WorkManager שהוגדר לעבודה חד-פעמית או תקופתית. WorkManager מכבד את תקינות המערכת על ידי איגוד משימות, ויש לו מרווח מחזורי מינימלי (15 דקות), שבדרך כלל מספיק לעדכונים ברקע. 
  • אם אתם מזהים חסימות מצב שינה שנוצרו על ידי WorkManager או JobScheduler עם שימוש גבוה בחסימות מצב שינה, יכול להיות שהגדרתם את ה-worker בצורה לא נכונה כך שהוא לא יושלם בתרחישים מסוימים. כדאי לנתח את הסיבות להפסקת העובד, במיוחד אם אתם רואים מקרים רבים של STOP_REASON_TIMEOUT
workManager.getWorkInfoByIdFlow(syncWorker.id)
  .collect { workInfo ->
      if (workInfo != null) {
        val stopReason = workInfo.stopReason
        logStopReason(syncWorker.id, stopReason)
      }
  }
  • בנוסף לרישום הסיבות להפסקת העבודה של העובדים, כדאי לעיין במסמכי התיעוד שלנו בנושא ניפוי באגים בעובדים. כדאי גם לאסוף ולנתח עקבות מערכת כדי להבין מתי מתבצעת נעילת השכמה ומתי היא מסתיימת.
  • לבסוף, כדאי לעיין במקרה לדוגמה של WHOOP, שבו החברה הצליחה לגלות בעיה בהגדרות של ה-workers שלה ולהפחית באופן משמעותי את ההשפעה של חסימת מצב שינה.

תקשורת Bluetooth

תרחישים לדוגמה: 

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

איך מצמצמים את השימוש בחסימות של מצב שינה: 

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

מעקב אחר מיקום

תרחישים לדוגמה: 

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

איך מצמצמים את השימוש בחסימות של מצב שינה: 

  • כדאי לעיין בהנחיות שלנו בנושא אופטימיזציה של השימוש במיקום. כדי לחסוך בסוללה, כדאי להטמיע פסק זמן, להשתמש באפשרות של שליחת בקשות למיקום בקבוצות או להשתמש בעדכוני מיקום פסיביים.
  • כשמשתמשים בממשקי ה-API של FusedLocationProvider או LocationManager כדי לבקש עדכונים של המיקום, המערכת מפעילה אוטומטית את המכשיר במהלך הקריאה החוזרת של אירוע המיקום. החסימה הקצרה הזו של מצב השינה, שמנוהלת על ידי המערכת, לא נכללת בחישובים של שימוש מוגזם בחסימה חלקית של מצב השינה.
  • מומלץ להימנע מהשגת חסימת מצב שינה נפרדת ורציפה לצורך שמירת נתוני מיקום במטמון, כי זה מיותר. במקום זאת, כדאי לשמור את אירועי המיקום בזיכרון או באחסון המקומי, ולהשתמש ב-WorkManager כדי לעבד אותם במרווחי זמן קבועים.
override fun onCreate(savedInstanceState: Bundle?) {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            // System wakes up CPU for short duration
            for (location in locationResult.locations){
                // Store data in memory to process at another time
            }
        }
    }
}

מעקב אחרי חיישן בתדר גבוה

תרחישים לדוגמה: 

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

איך מצמצמים את השימוש בחסימות של מצב שינה: 

  • אם משתמשים ב-SensorManager, צריך לצמצם את השימוש למרווחי זמן קבועים ורק כשהמשתמש העניק גישה באופן מפורש באמצעות אינטראקציה עם ממשק המשתמש. מעקב תדיר אחרי חיישנים עלול לרוקן את הסוללה במהירות בגלל מספר ההפעלות של ה-CPU והעיבוד שמתבצע.
  • אם אתם עוקבים אחרי מספר הצעדים או המרחק שעברתם, במקום להשתמש ב-SensorManager, כדאי להשתמש ב-Recording API או ב-Health Connect כדי לגשת לנתונים היסטוריים ולנתונים מצטברים של מספר הצעדים במכשיר, וכך לאסוף נתונים בצורה חסכונית בסוללה.
  • אם אתם רושמים חיישן באמצעות SensorManager, צריך לציין maxReportLatencyUs של 30 שניות או יותר כדי להשתמש בחבילות של חיישנים ולצמצם את התדירות של הפרעות CPU. כשהמכשיר מופעל בהמשך על ידי טריגר אחר, כמו אינטראקציה של משתמש, אחזור מיקום או משימה מתוזמנת, המערכת תשלח מיד את נתוני החיישן שנשמרו במטמון.
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(this,
                 accelerometer,
                 samplingPeriodUs, // How often to sample data
                 maxReportLatencyUs // Key for sensor batching 
              )
  • אם האפליקציה שלכם דורשת נתוני מיקום ונתוני חיישנים, צריך לסנכרן את השליפה והעיבוד של נתוני האירועים. הוספת קריאות של חיישנים לחסימת מצב השינה הקצרה שהמערכת מחזיקה לעדכוני מיקום מאפשרת להימנע מהצורך בחסימת מצב שינה כדי לשמור על המעבד פעיל. כדי לטפל בהעלאה ובעיבוד של הנתונים המשולבים האלה, צריך להשתמש ב-worker או ב-חסימת מצב שינה לזמן קצר.

העברת הודעות מרחוק

תרחישים לדוגמה: 

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

איך מצמצמים את השימוש בחסימות של מצב שינה: 

  • אם אפשר לעבד את אירועי הרשת בצד השרת, צריך להשתמש ב-FCM כדי לקבל מידע על הלקוח. אם נדרש עיבוד נוסף של נתוני FCM, אפשר לתזמן עיבוד מהיר
  • אם צריך לעבד אירועים בצד הלקוח באמצעות חיבור Socket, לא צריך חסימת מצב שינה כדי להאזין להפרעות באירועים. כשמנות נתונים מגיעות לרדיו Wi-Fi או לרדיו סלולרי, חומרת הרדיו מפעילה הפרעה לחומרה בצורה של חסימת מצב שינה של ליבת המערכת.אחרי כן תוכלו לתזמן worker או לקבל חסימת מצב שינה כדי לעבד את הנתונים.
  • לדוגמה, אם אתם משתמשים ב-ktor-network כדי להאזין למנות נתונים בשקע רשת, כדאי להפעיל את חסימת מצב שינה רק כשמנות הנתונים נמסרות ללקוח וצריך לעבד אותן.
val readChannel = socket.openReadChannel()
while (!readChannel.isClosedForRead) {
    // CPU can safely sleep here while waiting for the next packet
    val packet = readChannel.readRemaining(1024) 
    if (!packet.isEmpty) {
         // Data Arrived: The system woke the CPU and we should keep it awake via manual wake lock (urgent) or scheduling a worker (non-urgent)
         performWorkWithWakeLock { 
              val data = packet.readBytes()
              // Additional logic to process data packets
         }
    }
}

סיכום

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

נכתב על ידי:
להמשך קריאה