flet icon indicating copy to clipboard operation
flet copied to clipboard

When the app closes, the application does not continue

Open yucel685 opened this issue 1 year ago • 5 comments

The stopwatch that is open in the app does not continue to progress when the Android app is closed or the screen is locked

yucel685 avatar May 13 '24 06:05 yucel685

What did you instead expect?

ndonkoHenri avatar May 13 '24 08:05 ndonkoHenri

when the phone's stopwatch is turned on, the time has progressed, but the stopwatch I made continues where it left off

yucel685 avatar May 13 '24 08:05 yucel685

how can I use the app lifecycle can you help

13 May 2024 Pzt 12:00 tarihinde TheEthicalBoy @.***> şunu yazdı:

I think you might have to listen to app-lifecycle-changes https://flet.dev/docs/controls/page#on_app_lifecycle_state_change, then update your stopwatch accordingly.

— Reply to this email directly, view it on GitHub https://github.com/flet-dev/flet/issues/3279#issuecomment-2107025077, or unsubscribe https://github.com/notifications/unsubscribe-auth/AG3EFOYQ37KN2VDKZIVOP33ZCB6JPAVCNFSM6AAAAABHTRGQTWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMBXGAZDKMBXG4 . You are receiving this because you authored the thread.Message ID: @.***>

yucel685 avatar May 13 '24 10:05 yucel685

how can I use the app lifecycle can you help

yucel685 avatar May 13 '24 10:05 yucel685

how can I use the app lifecycle

You need to add a callback which will listen to on_app_lifecycle_state_change.

ndonkoHenri avatar Oct 10 '24 14:10 ndonkoHenri

The stopwatch that is open in the app does not continue to progress when the Android app is closed or the screen is locked

I created a timer app using the latest pre-release and tried it on android using flet debug, and it ran for about 20 mins in the background before being 'killed'. But according to this SO thread and official docs, that time is not fixed + pretty uncertain.

Timer app

import asyncio
import time

import flet as ft


def format_hhmmss(seconds: int) -> str:
    """Convert elapsed seconds into HH:MM:SS string."""
    h = seconds // 3600
    m = (seconds % 3600) // 60
    s = seconds % 60
    return f"{h:02}:{m:02}:{s:02}"


def main(page: ft.Page):
    page.vertical_alignment = ft.MainAxisAlignment.CENTER
    page.horizontal_alignment = ft.CrossAxisAlignment.CENTER

    # State variables
    running = False
    paused = False
    elapsed = 0  # seconds shown in the UI
    base_elapsed = 0  # accumulated time before the current run
    started_at = 0.0  # wall-clock start timestamp

    def sync_ui():
        """Synchronize UI controls with current state variables."""
        timer.value = format_hhmmss(elapsed)

        # Toggle button switches appearance based on state
        if running and not paused:
            toggle_btn.text = "Pause"
            toggle_btn.icon = ft.Icons.PAUSE
        else:
            toggle_btn.text = "Start"
            toggle_btn.icon = ft.Icons.PLAY_ARROW

        # Stop button only enabled when there is something to stop/reset
        stop_btn.disabled = (not running) and (elapsed == 0)

        page.update()

    async def ticker():
        """
        Background task that updates elapsed time once per second
        while the timer is running.
        """
        nonlocal elapsed
        while running:
            if not paused:
                elapsed = base_elapsed + int(time.time() - started_at)
                timer.value = format_hhmmss(elapsed)
                timer.update()
            await asyncio.sleep(1)

    def handle_toggle():
        """
        Toggle button handler:
        - stopped → start
        - running → pause
        - paused → resume
        """
        nonlocal running, paused, elapsed, base_elapsed, started_at

        # stopped → start
        if not running:
            running = True
            paused = False
            base_elapsed = elapsed
            started_at = time.time()

            # Start background ticker task
            page.run_task(ticker)
            sync_ui()
            return

        # running → pause
        if not paused:
            base_elapsed += int(time.time() - started_at)
            elapsed = base_elapsed
            paused = True
            sync_ui()
            return

        # paused → resume
        paused = False
        started_at = time.time()
        sync_ui()

    def handle_stop():
        """Stop the timer and reset it to 00:00:00."""
        nonlocal running, paused, elapsed, base_elapsed, started_at
        running = False
        paused = False
        elapsed = 0
        base_elapsed = 0
        started_at = 0.0
        sync_ui()

    page.add(
        ft.SafeArea(
            ft.Column(
                spacing=20,
                horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                alignment=ft.MainAxisAlignment.CENTER,
                controls=[
                    timer := ft.Text("00:00:00", size=30, weight=ft.FontWeight.BOLD),
                    ft.Row(
                        alignment=ft.MainAxisAlignment.CENTER,
                        controls=[
                            toggle_btn := ft.FilledButton(
                                "Start",
                                icon=ft.Icons.PLAY_ARROW,
                                on_click=handle_toggle,
                            ),
                            stop_btn := ft.TextButton(
                                "Stop",
                                icon=ft.Icons.STOP,
                                disabled=True,
                                on_click=handle_stop,
                            ),
                        ],
                    ),
                ],
            )
        )
    )

    # Initial UI sync
    sync_ui()


ft.run(main)
Image

Please give it another try with the latest pre-release and let know what you find.

ndonkoHenri avatar Dec 13 '25 23:12 ndonkoHenri