מסך 'פריטים אחרונים'

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

במסך הפריטים האחרונים נעשה שימוש במודל שמתמקד במסמכים – שהוצג ב-Android 5.0 (רמת API‏ 21) – שבו יכולים להופיע כמה מופעים של אותה פעילות שמכילה מסמכים שונים כמשימות במסך הפריטים האחרונים. לדוגמה, יכול להיות שב-Google Drive תהיה משימה לכל אחד מכמה מסמכי Google. כל מסמך מופיע כמשימה במסך 'הפריטים האחרונים':

מסך הפריטים האחרונים עם שני מסמכים מ-Google Drive, כל אחד מהם מוצג כמשימה נפרדת.

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

מסך האפליקציות האחרונות עם Chrome ו-Gmail שפועלות כמשימות נפרדות.

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

הסיווג ActivityManager.AppTask מאפשר לכם לנהל משימות, והדגלים של הפעילות בסיווג Intent מאפשרים לכם לציין מתי פעילות מתווספת למסך הפעילויות האחרונות או מוסרת ממנו. בנוסף, המאפיינים <activity> מאפשרים להגדיר את ההתנהגות במניפסט.

הוספת משימות למסך 'האפליקציות האחרונות'

שימוש בדגלים של המחלקה Intent כדי להוסיף משימה מאפשר לכם לשלוט טוב יותר מתי ואיך מסמך נפתח או נפתח מחדש במסך 'פריטים אחרונים'. כשמשתמשים במאפיינים <activity>, אפשר לבחור אם המסמך תמיד ייפתח במשימה חדשה או אם ייעשה שימוש חוזר במשימה קיימת עבור המסמך.

שימוש בדגל הכוונה להוספת משימה

כשיוצרים מסמך חדש לפעילות, קוראים לשיטה startActivity() ומעבירים אליה את הכוונה להפעיל את הפעילות. כדי להוסיף מעבר לוגי כך שהמערכת תתייחס לפעילות שלכם כמשימה חדשה במסך 'אחרונים', צריך להעביר את הדגל FLAG_ACTIVITY_NEW_DOCUMENT בשיטה addFlags() של Intent שמפעילה את הפעילות.

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

private fun newDocumentIntent(context: Context): Intent =
    Intent(context, NewDocumentActivity::class.java).apply {
        addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
        putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++)
    }

@Composable
fun CreateDocumentButton() {
    val context = LocalContext.current
    Button(
        onClick = {
            val intent = newDocumentIntent(context)
            // Add FLAG_ACTIVITY_MULTIPLE_TASK if needed based on state
            context.startActivity(intent)
        }
    ) {
        Text("Create New Document")
    }
}

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

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

class DocumentCentricActivity : ComponentActivity() {
    private var documentState by mutableStateOf(
        DocumentState(
            count = 0,
            textResId = R.string.hello_new_document_counter
        )
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val initialCount = intent.getIntExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0)

        documentState = documentState.copy(count = initialCount)

        setContent {
            MaterialTheme {
                DocumentScreen(
                    count = documentState.count,
                    textResId = documentState.textResId
                )
            }
        }
    }

    override fun onNewIntent(newIntent: Intent) {
        super.onNewIntent(newIntent)
        // If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this Activity is reused.
        documentState = documentState.copy(
            textResId = R.string.reusing_document_counter
        )
    }

    data class DocumentState(val count: Int, @StringRes val textResId: Int)

    companion object {
        const val KEY_EXTRA_NEW_DOCUMENT_COUNTER = "KEY_EXTRA_NEW_DOCUMENT_COUNTER"
    }
}

@Composable
fun DocumentScreen(count: Int, @StringRes textResId: Int) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center
    ) {
        // UI reacts to whichever string resource ID was passed down
        Text(text = stringResource(id = textResId))
        Spacer(modifier = Modifier.height(8.dp))
        Text(text = "Counter: $count")
    }
}

בדוגמת הקוד שלמעלה, הפעילות מטפלת בניתוב ברמת מערכת ההפעלה (onCreate ו-onNewIntent), ואילו הפונקציה @Composable אחראית רק על עיבוד ממשק המשתמש על סמך המצב שסופק.

איך מוסיפים משימה באמצעות מאפיין הפעילות

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

intoExisting
הפעילות משתמשת מחדש במשימה קיימת במסמך. זהה להגדרה של הדגל FLAG_ACTIVITY_NEW_DOCUMENT בלי להגדיר את הדגל FLAG_ACTIVITY_MULTIPLE_TASK, כמו שמתואר בקטע שימוש בדגל Intent כדי להוסיף משימה.
always
הפעילות יוצרת משימה חדשה למסמך, גם אם המסמך כבר פתוח. השימוש בערך הזה זהה להגדרת הדגלים FLAG_ACTIVITY_NEW_DOCUMENT ו-FLAG_ACTIVITY_MULTIPLE_TASK.
none
הפעילות לא יוצרת משימה חדשה למסמך. במסך 'הפעילות האחרונה' הפעילות מוצגת כמו שהיא מוצגת כברירת מחדל. מוצג בו משימה אחת של האפליקציה, שממשיכה מכל פעילות שהמשתמש הפעיל לאחרונה.
never
הפעילות לא יוצרת משימה חדשה למסמך. הגדרת הערך הזה מבטלת את ההתנהגות של הדגלים FLAG_ACTIVITY_NEW_DOCUMENT ו-FLAG_ACTIVITY_MULTIPLE_TASK. אם אחת מההגדרות האלה מוגדרת בכוונת המשתמש, ובמסך הפריטים האחרונים מוצגת משימה אחת של האפליקציה, הפעילות ממשיכה מהפעילות האחרונה שהמשתמש הפעיל.

הסרת משימות

כברירת מחדל, משימת מסמך יוצאת אוטומטית ממסך הפריטים האחרונים כשהפעילות שלה מסתיימת. אפשר לשנות את שיטת הפעולה הזאת באמצעות המחלקה ActivityManager.AppTask, הדגל Intent או המאפיין <activity>.

תמיד אפשר להחריג משימה ממסך הפריטים האחרונים על ידי הגדרת המאפיין <activity>android:excludeFromRecents לערך true.

אתם יכולים להגדיר את מספר המשימות המקסימלי שהאפליקציה יכולה לכלול במסך 'האחרונים' על ידי הגדרת המאפיין <activity> android:maxRecents לערך של מספר שלם. כשמגיעים למספר המשימות המקסימלי, המשימה שהייתה בשימוש הכי מזמן נעלמת מהמסך 'פריטים אחרונים'. ערך ברירת המחדל הוא 16, והערך המקסימלי הוא 50 (25 במכשירים עם זיכרון נמוך). ערכים שקטנים מ-1 לא תקינים.

שימוש במחלקה AppTask כדי להסיר משימות

בפעילות שיוצרת משימה חדשה במסך האחרונות, אפשר לציין מתי להסיר את המשימה ולסיים את כל הפעילויות שמשויכות אליה באמצעות קריאה לשיטה finishAndRemoveTask():

@Composable
fun RemoveTaskButton() {
    val context = LocalContext.current
    Button(
        onClick = {
            // It is good practice to remove a document from the overview stack if not needed anymore.
            (context as? Activity)?.finishAndRemoveTask()
        }
    ) {
        Text("Remove from Recents")
    }
}

שמירת משימות שהושלמו

אם רוצים לשמור משימה במסך הפריטים האחרונים, גם אחרי שהפעילות שלה הסתיימה, צריך להעביר את הדגל FLAG_ACTIVITY_RETAIN_IN_RECENTS בשיטה addFlags() של ה-intent שמפעיל את הפעילות.

private fun newDocumentIntent() =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement())
        }

כדי להשיג את אותו אפקט, מגדירים את מאפיין <activity> android:autoRemoveFromRecents לערך false. ערך ברירת המחדל הוא true לפעילויות שקשורות למסמכים ו-false לפעילויות רגילות. השימוש במאפיין הזה מבטל את הדגל FLAG_ACTIVITY_RETAIN_IN_RECENTS.

הפעלת שיתוף של כתובות URL אחרונות (Pixel בלבד)

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

מסך הפריטים האחרונים עם קישור לשיתוף תוכן אינטרנט שנצפה לאחרונה.

כל אפליקציה יכולה להפעיל קישור ל'פריטים אחרונים' למשתמשים על ידי מתן ממשק משתמש באינטרנט ושינוי ברירת המחדל של onProvideAssistContent(), כמו בדוגמה הבאה:

class MainActivity : ComponentActivity() {

    // Track the current URL as state so the UI can update it during navigation
    private var currentWebUri by mutableStateOf("https://example.com/home")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AppTheme {
                // Pass a lambda to your Compose UI so it can update the URL state
                // as the user navigates through your app.
                MainScreen(
                    onPageChanged = { newUrl -> currentWebUri = newUrl }
                )
            }
        }
    }

    override fun onProvideAssistContent(outContent: AssistContent) {
        super.onProvideAssistContent(outContent)

        // The system calls this when the user enters the Recents screen.
        // Provide the active URI tracked by the Compose state.
        outContent.webUri = Uri.parse(currentWebUri)
    }
}