صفحه نمایش اخیر

صفحه «اخیرها» که با نام‌های صفحه «مرور کلی»، «لیست وظایف اخیر» یا «صفحه برنامه‌های اخیر» نیز شناخته می‌شود، یک رابط کاربری در سطح سیستم است که فعالیت‌ها و وظایف اخیراً دسترسی یافته را فهرست می‌کند. کاربر می‌تواند در لیست حرکت کند، وظیفه‌ای را برای از سرگیری انتخاب کند یا با کشیدن انگشت روی آن، وظیفه‌ای را از لیست حذف کند.

صفحه Recents از یک مدل سند محور - که در اندروید ۵.۰ (سطح API ۲۱) معرفی شد - استفاده می‌کند که در آن چندین نمونه از یک فعالیت مشابه که حاوی اسناد مختلف هستند، می‌توانند به عنوان وظایف در صفحه Recents ظاهر شوند. به عنوان مثال، گوگل درایو ممکن است برای هر یک از چندین سند گوگل یک وظیفه داشته باشد. هر سند به عنوان یک وظیفه در صفحه Recents ظاهر می‌شود:

صفحه Recents دو سند گوگل درایو را نشان می‌دهد که هر کدام به عنوان یک کار جداگانه نمایش داده شده‌اند.

مثال رایج دیگر زمانی است که کاربر در حال استفاده از مرورگر خود است و روی Share > Gmail ضربه می‌زند. صفحه Compose برنامه Gmail ظاهر می‌شود. ضربه زدن روی دکمه Recents در آن زمان نشان می‌دهد که Chrome و Gmail به عنوان وظایف جداگانه اجرا می‌شوند:

صفحه برنامه‌های اخیر که کروم و جیمیل را به عنوان وظایف جداگانه نشان می‌دهد.

معمولاً، شما به سیستم اجازه می‌دهید نحوه نمایش وظایف و فعالیت‌های شما را در صفحه Recents تعریف کند. نیازی به تغییر این رفتار نیست. با این حال، برنامه شما می‌تواند نحوه و زمان نمایش فعالیت‌ها در صفحه Recents را تعیین کند.

کلاس ActivityManager.AppTask به شما امکان مدیریت وظایف را می‌دهد و پرچم‌های فعالیت کلاس Intent به شما امکان می‌دهند مشخص کنید چه زمانی یک فعالیت به صفحه Recents اضافه یا حذف شود. همچنین، ویژگی‌های <activity> به شما امکان می‌دهند رفتار را در مانیفست تنظیم کنید.

اضافه کردن وظایف به صفحه Recents

استفاده از پرچم‌های کلاس Intent برای اضافه کردن یک وظیفه، کنترل بیشتری بر زمان و نحوه باز شدن یا بازگشایی یک سند در صفحه Recents به شما می‌دهد. وقتی از ویژگی‌های <activity> استفاده می‌کنید، می‌توانید بین باز شدن همیشگی سند در یک وظیفه جدید یا استفاده مجدد از یک وظیفه موجود برای سند، یکی را انتخاب کنید.

برای اضافه کردن یک وظیفه از پرچم Intent استفاده کنید

وقتی یک سند جدید برای اکتیویتی خود ایجاد می‌کنید، متد startActivity() را فراخوانی می‌کنید و intent ای را که اکتیویتی را اجرا می‌کند به آن ارسال می‌کنید. برای ایجاد یک وقفه منطقی تا سیستم، اکتیویتی شما را به عنوان یک وظیفه جدید در صفحه Recents در نظر بگیرد، فلگ FLAG_ACTIVITY_NEW_DOCUMENT را به متد addFlags() مربوط به Intent که اکتیویتی را اجرا می‌کند، ارسال کنید.

اگر هنگام ایجاد سند جدید، پرچم FLAG_ACTIVITY_MULTIPLE_TASK را تنظیم کنید، سیستم همیشه یک وظیفه جدید با اکتیویتی هدف به عنوان ریشه ایجاد می‌کند. این تنظیم اجازه می‌دهد که یک سند در بیش از یک وظیفه باز شود. کد زیر نشان می‌دهد که چگونه اکتیویتی اصلی این کار را انجام می‌دهد و اکتیویتی جدید را از composable شما شروع می‌کند:

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")
    }
}

وقتی اکتیویتی اصلی یک اکتیویتی جدید را اجرا می‌کند، سیستم در میان وظایف موجود به دنبال وظیفه‌ای می‌گردد که intent آن با نام کامپوننت intent و داده‌های intent مربوط به اکتیویتی مطابقت داشته باشد. اگر وظیفه پیدا نشود، یا intent شامل پرچم FLAG_ACTIVITY_MULTIPLE_TASK باشد، یک وظیفه جدید با activity به عنوان ریشه آن ایجاد می‌شود.

اگر سیستم وظیفه‌ای را پیدا کند که هدف آن با نام کامپوننت هدف و داده‌های هدف مطابقت داشته باشد، آن وظیفه را به جلو می‌آورد و هدف جدید را به onNewIntent() ارسال می‌کند. فعالیت جدید، هدف را دریافت می‌کند و یک سند جدید در صفحه Recents ایجاد می‌کند، همانطور که در مثال زیر نشان داده شده است:

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")
    }
}

در کد قبلی، Activity مسیریابی در سطح سیستم عامل ( 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 را لغو می‌کند. اگر هر یک از این موارد در اینتنت تنظیم شده باشند و صفحه Recents یک وظیفه واحد را برای برنامه نمایش دهد، برنامه از هر فعالیتی که کاربر آخرین بار فراخوانی کرده است، از سر گرفته می‌شود.

حذف وظایف

به طور پیش‌فرض، یک وظیفه سند به طور خودکار پس از پایان فعالیتش از صفحه Recents خارج می‌شود. شما می‌توانید این رفتار را با کلاس ActivityManager.AppTask ، با یک پرچم Intent یا با یک ویژگی <activity> لغو کنید.

شما همیشه می‌توانید با تنظیم ویژگی <activity> android:excludeFromRecents به true ، یک وظیفه را به طور کامل از صفحه Recents حذف کنید.

شما می‌توانید حداکثر تعداد وظایفی را که برنامه شما می‌تواند در صفحه Recents قرار دهد، با تنظیم ویژگی <activity> android:maxRecents روی یک مقدار صحیح، تعیین کنید. وقتی به حداکثر تعداد وظایف رسیدید، آخرین وظیفه‌ای که اخیراً کمتر استفاده شده است از صفحه Recents ناپدید می‌شود. مقدار پیش‌فرض ۱۶ است و حداکثر مقدار ۵۰ (۲۵ در دستگاه‌های با حافظه کم) می‌باشد. مقادیر کمتر از ۱ معتبر نیستند.

از کلاس AppTask برای حذف وظایف استفاده کنید

در فعالیتی که یک وظیفه جدید در صفحه Recents ایجاد می‌کند، می‌توانید با فراخوانی متد 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")
    }
}

وظایف تمام شده را حفظ کنید

اگر می‌خواهید یک وظیفه (task) را در صفحه 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های اخیر (فقط پیکسل)

در دستگاه‌های پیکسل که اندروید ۱۲ یا بالاتر را اجرا می‌کنند، کاربران می‌توانند لینک‌های محتوای وب اخیراً مشاهده شده را مستقیماً از صفحه «آخرین‌ها» به اشتراک بگذارند. پس از بازدید از محتوا در یک برنامه، کاربر می‌تواند به صفحه «آخرین‌ها» برود و برنامه‌ای را که محتوا را در آن مشاهده کرده است پیدا کند، سپس روی دکمه پیوند ضربه بزند تا URL را کپی یا به اشتراک بگذارد.

صفحه «موارد اخیر» با پیوندی برای اشتراک‌گذاری محتوای وب اخیراً مشاهده‌شده.

هر برنامه‌ای می‌تواند با ارائه یک رابط کاربری وب و بازنویسی onProvideAssistContent() ، همانطور که در مثال زیر نشان داده شده است، لینک کردن Recents را برای کاربران فعال کند:

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)
    }
}