Android Question Timer CountDown with problem

jeronimovilar

Active Member
Licensed User
Longtime User
Hi,
I create a timer app with beep, vibrate functions. I Initialize with 1000 and on timer_tick i show the minute and second on label.
The problem is not working with the real time. I compared with two different clocks and the app is slow 2 seconds in 8 minutes first.
What can i do to countdown is REAL?

JPG shows comparative
START:
Sub Timer_start

    Timer1.Initialize("Timer1", 1000)
    Timer1.Enabled = True
    
End Sub
Timer_Tick:
Sub Timer1_Tick
    'CountDown1 is Minute
    'CountDown2 is Second
    'Both is shows in label
    'Log(CountDown1 & ":" & CountDown2)
    If CountDown2 <= 0 Then
        CountDown1 = CountDown1 - 1
        CountDown2 = 59       
        If CountDown1 < 0 Then
            Timer1.Enabled = False
            CountDown2 = 0
            CountDown1 = 0
        End If
        'ToastMessageShow(CountDown1,False)
    Else
        CountDown2 = CountDown2 - 1
    End If
    
End Sub

Tanks and sorry my brazilian english šŸ¤­
 

Attachments

  • Timer.jpg
    Timer.jpg
    133 KB · Views: 89

JohnC

Expert
Licensed User
Longtime User
Don't rely on calculating the time by the number of ticks.

Instead, display the remaining countdown time using math:

1) Lets say the user sets a 15 minute countdown timer.
2) When the timer starts, save the value of "DateTime.Now" + 15 minutes = The time in the future that the countdown timer will end" and put that future time value in a variable called "CountdownEndTime".
3) Then for each tick of the timer, display the time remaining as a math result: Displayed Time = CountdownEndTime - DateTime.Now

This way even if the clicks are not precisely 1 second, the displayed time will always be accurate.
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
If I may add, the above is the right solution but you should decrease the interval to say 1/20 of a second to avoid the display not being updated frequently enough.
(You might reduce it to even 1/100 of a second).

Remember, all the timer does is update the display of a real time interval - therefore not a significant computational burden..
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
It can also be done without a timer.

Put
Private countDownEnabled As Boolean
in Globals

To cancel, set countDownEnabled to false

B4X:
Private Sub countDown(seconds As Int)
    Dim startTime As Long = DateTime.Now
    countDownEnabled = True
    Do While countDownEnabled
        Dim count As Int = (DateTime.now - startTime) / 1000
        If count >= seconds Then Exit
        Log(seconds - count)  'or update display
        Sleep(100)
    Loop
End Sub
 
Upvote 0

jeronimovilar

Active Member
Licensed User
Longtime User
Me again
How to "transform" the ansewer in Minutes+":"+seconds to show on button text (14:59...14:58...)?

B4X:
Private Sub countDown(seconds As Int)
    Dim startTime As Long = DateTime.Now + (15 * 60000)
    Dim countDownEnabled = True
    Do While countDownEnabled
        Dim count As Int = (DateTime.now - startTime) / 1000
        If count >= seconds Then Exit
        Log(seconds - count)  'or update display
        Button2.Text = count '<-- how to shows?'
        Sleep(100)
    Loop
End Sub
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
ChatGPT 4 suggested this code:

B4X:
Private Sub countDown(seconds As Int)
    Dim startTime As Long = DateTime.Now
    Dim countDownEnabled As Boolean = True
    Dim remainingTime As Int
    Dim minutes As Int
    Dim secs As Int
    Do While countDownEnabled
        Dim count As Int = (DateTime.Now - startTime) / 1000
        If count >= seconds Then
            countDownEnabled = False ' disable timer when time is up
        Else
            remainingTime = seconds - count
            minutes = remainingTime / 60
            secs = remainingTime Mod 60
            'Display the time in mm:ss format
            Button2.Text = $"${NumberFormat2(minutes, 2, 0, 0, False)}:${NumberFormat2(secs, 2, 0, 0, False)}"$
        End If
        Sleep(1000) ' pause for a second
    Loop
End Sub
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
This is my prompt:
B4X:
Please Modify the below B4A code so that I can call this routine with the number of seconds that I want to start a countdown timer with and have the button text display the remaining time in mm:ss format:

Private Sub countDown(seconds As Int)
    Dim startTime As Long = DateTime.Now + (15 * 60000)
    Dim countDownEnabled = True
    Do While countDownEnabled
        Dim count As Int = (DateTime.now - startTime) / 1000
        If count >= seconds Then Exit
        Log(seconds - count)  'or update display
        Button2.Text = count '<-- how to shows?'
        Sleep(100)
    Loop
End Sub
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I asked it why and it said:

If you change Sleep(1000) to Sleep(100) you will effectively change the interval of the loop from 1 second to 100 milliseconds. This means the counter will update 10 times a second. If you want the seconds to continue decrementing at the rate of one per second while checking the time 10 times per second, you can keep the rest of the code as it is.

However, please note that it may result in more CPU usage and could make your application more demanding on the system due to the faster loop rate. If you want to decrease the demand on the system, consider maintaining the sleep duration at 1000 milliseconds, unless more frequent updates are needed for your specific use case.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I see. That means it doesn't "understand" how sleep works.
There is an event queue that needs to be handled one at a time. It is possible that the sleep handler comes too late for the change in seconds.
And at least for a partial second the count down timer will be wrong.

Perhaps you can set ChatPGT straight.

Also since you fed it the code for countdown timers, will it generate that code now with the simple question:
"What is the B4X code for implementing and displaying a countdown timer in minutes and seconds?"
Just curious.
 
Upvote 0
Top