חזרה להקראה בכמה קטעים

ב-Android 9 (ובגרסאות קודמות), אפליקציות נכנסו למצב PAUSED כשהתקיימו התנאים הבאים:

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

ההבדל בין המצבים האלה הוא משך ההשהיה של האפליקציה, אבל אי אפשר להבחין ביניהם ברמת האפליקציה.

ב-Android 10, כל הפעילויות שניתן להתמקד בהן בחבילות גלויות נמצאות במצב RESUMED. השינוי הזה משפר את התאימות לחלונות מרובים ולמצבי MD באפליקציות שמשתמשות ב-onPause() במקום ב-onStop() כדי להפסיק את רענון ממשק המשתמש ואת האינטראקציה עם המשתמש. כלומר:

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

איור 1. ריבוי משימות במכשיר מתקפל

איור 2. מצב מרובה חלונות בגרסה למחשב

פעילויות יכולות להיות במצב PAUSED אם אי אפשר להתמקד בהן או אם הן מוסתרות חלקית, למשל:

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

בגישה הזו מצוין לאפליקציות שפעילות יכולה לקבל קלט ממשתמש רק במצב RESUMED. לפני Android 10, פעילויות יכלו לקבל קלט גם במצב PAUSED (לדוגמה, נסו לגעת בשתי הפעילויות במסך המפוצל בו-זמנית במכשיר עם Android 9).

כדי לשמור על האות resumed מגרסאות קודמות של Android (וכדי להעביר מידע על המועד שבו אפליקציות צריכות לקבל גישה למשאבים עם גישה בלעדית או למשאבים מסוג singleton), ‏ Android 10 כולל קריאה חוזרת חדשה:

Activity#onTopResumedActivityChanged(boolean onTop)

כשמפעילים את הקריאה החוזרת הזו, היא מתבצעת בין Activity#onResume() לבין Activity#onPause(). הקריאה החוזרת הזו היא אופציונלית ואפשר לדלג עליה, כך שפעילות יכולה לעבור ממצב RESUMED למצב PAUSED בלי להפוך לעליונה ביותר במערכת. לדוגמה, במצב ריבוי חלונות. הקריאה החוזרת הזו היא אופציונלית, ולכן היא לא חלק ממחזור החיים של הפעילות, ומומלץ להשתמש בה לעיתים רחוקות.

הפעילות הקודמת שהופסקה מקבלת ומסיימת את ההרצה של onTopResumedActivity(false) לפני שהפעילות הבאה שהופסקה מקבלת את onTopResumedActivity(true), אלא אם הפעילות הקודמת אורכת יותר מדי זמן לטיפול בקריאה למתודה ומגיעה לזמן הקצוב לתפוגה של 500 אלפיות השנייה.

תאימות

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

כמה פעילויות שהופעלו מחדש בתהליך אחד של אפליקציה

  • בעיה. ב-Android מגרסה 9 ומטה, רק פעילות אחת במערכת מושהית בכל פעם. כל המעברים בין פעילויות כוללים השהיה של פעילות אחת לפני שממשיכים בפעילות אחרת. חלק מהאפליקציות ומסגרות העבודה (כמו Flutter או LocalActivityManager של Android) משתמשות בעובדה הזו ומאחסנות את המצב של הפעילות שהופעלה מחדש בסינגלטונים.
  • פתרון. ב-Android מגרסה 9 ומטה, אם שתי פעילויות מאותו תהליך מופעלות מחדש, המערכת מפעילה מחדש רק את הפעילות שמופיעה גבוה יותר בסדר Z. אפליקציות שמטרגטות את Android 10 יכולות לתמוך בהפעלה מחדש של כמה פעילויות בו-זמנית.

גישה למצלמה בו-זמנית

  • בעיות. הבעיות האלה קיימות גם ב-Android מגרסה 9 ומגרסאות קודמות. לדוגמה, פעילות במסך מלא שהופסקה יכולה לאבד את המיקוד של המצלמה לפעילות שהושהתה בחלק העליון במצב 'תמונה בתוך תמונה', אבל היא יכולה להיות חשופה יותר אם משתמשים במצב ריבוי חלונות או ריבוי מסכים.
    • בגלל שינויים שבוצעו במצב RESUME, יכול להיות שאפליקציות יתנתקו מהמצלמה גם כשהן ממשיכות לפעול. כדי לפתור את הבעיה, האפליקציות צריכות לטפל בניסיון ניתוק של המצלמה בלי לקרוס. כשמתנתקים, האפליקציות מקבלות קריאה חוזרת (callback) של ניתוק, וכל הקריאות ל-API מתחילות להחזיר CameraAccessException.
    • resizeableActivity=false לא מבטיח גישה בלעדית למצלמה, כי אפשר לפתוח אפליקציות אחרות שמשתמשות במצלמה במסכים אחרים.
  • פתרונות. המפתחים צריכים לכלול לוגיקה למקרים שבהם אפליקציה מנותקת מהמצלמה. אם אפליקציה מנותקת מהמצלמה, היא צריכה לעקוב אחרי קריאות חוזרות (callback) של זמינות המצלמה כדי לנסות להתחבר מחדש ולהמשיך להשתמש במצלמה. בנוסף לקריאה החוזרת (callback) הקיימת CameraManager#AvailabilityCallback#onCameraAvailable(), ב-Android 10 נוספה קריאה חוזרת CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged(), שמתייחסת למקרה שבו המיקוד (ועדיפות המצלמה) עובר בין כמה פעילויות שהופעלו מחדש. מפתחי אפליקציות צריכים להשתמש בשתי פונקציות הקריאה החוזרת האלה כדי לקבוע מתי כדאי לנסות לקבל גישה למצלמה.

Multi-resume

ב-Android 10, מצב מחזור החיים של הפעילות נקבע לפי הנראות והסדר בעומק (Z-order). כדי לוודא שהמצב הנכון אחרי עדכוני החשיפה בפעילות, ולהעריך איזה מצב במחזור החיים רלוונטי, מפעילים את השיטה ActivityRecord#makeActiveIfNeeded() ממיקומים שונים. ב-Android 10, המצב הפעיל הוא RESUMED או PAUSED, והוא פועל רק בשני המקרים האלה.

ב-Android 10, חידוש פעילות מתבצע בנפרד בכל מחסנית במקום במיקום יחיד במערכת. הסיבה לכך היא שאפשר לבצע כמה מעברים בין פעילויות בו-זמנית במצבי ריבוי חלונות. מידע נוסף זמין במאמר ActivityStack#mInResumeTopActivity.

הפעילות העליונה שהופעלה מחדש

אחרי פעולות שיכולות לגרום לשינוי בפעילות העליונה (כמו הפעלה, המשכה או שינוי בסדר Z של פעילות), מופעלת הפונקציה ActivityStackSupervisor#updateTopResumedActivityIfNeeded(). השיטה הזו בודקת אם הפעילות העליונה שהופסקה השתנתה, ומבצעת את העדכון אם צריך. אם הפעילות הקודמת שהופסקה לא משחררת את המצב שלה, נשלחת אליה הודעה על אובדן המצב שלה ומוגדר פסק זמן בצד השרת (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). דוח על המצב של הפעילות שהופסקה נשלח לפעילות הבאה אחרי שהפעילות הקודמת משחררת את המצב שלה, או כשמגיע פסק הזמן (ראו שימושים ב:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

TopResumedActivityChangeItem נוסף פריט חדש של טרנזקציה לדיווח על שינויים במצב העליון של חידוש הפעולה ללקוחות, והוא מבוסס על ארכיטקטורת ActivityLifecycler מ-Android 9.

המצב העליון של הפעילות שחודשה מאוחסן בצד הלקוח, ובכל פעם שהפעילות עוברת למצב RESUMED או PAUSED, המערכת גם בודקת אם צריך להפעיל את הקריאה החוזרת onTopResumedActivityChanged(). כך מתאפשר ניתוק מסוים בתקשורת של מצבי מחזור החיים ומצב ההפעלה העליון בין צד השרת לצד הלקוח.