Android Question Stopwatch and Services

Discussion in 'Android Questions' started by brodmuehler, Apr 22, 2015.

  1. brodmuehler

    brodmuehler Member Licensed User

    Hi Everybody

    I programmed a little and very simple stopwatch in order to learn how Services work. But this stopwatch is not working since it always falls behind as soon as my phone switches off. That means that I am doing something wrong.

    Could someone perhaps have a look at my code and give me a hint what is wrong. Iam runningout of ideas and I cannot find a solution in the tutorials and examples.

    I attached my app as a zip-file.

    Thanks a lot and kind regards
    René
     

    Attached Files:

  2. walterf25

    walterf25 Well-Known Member Licensed User

    Seems to be working fine, i don't see the issue you're describing, the service restarts every second.

    Cheers,
    Walter
     
    brodmuehler likes this.
  3. brodmuehler

    brodmuehler Member Licensed User

    Hi walterf25

    I put my tablet with a stopwatch app beside my phone, started both at the same time and let them run. After a while my phone switches off, as it should do to save energy. When my tablet showed 2 minutes I switched my phone back on and my app only showed 105, where it should have shown 120. The longer I wait the bigger the difference.

    Regards
    René
     
  4. walterf25

    walterf25 Well-Known Member Licensed User

    I don't see any count on the notification, did you forget to add that part to your code?, The reason i say it works is because i can see the service starting every 1 second even after the phone's screen turns off.

    Walter
     
    brodmuehler likes this.
  5. walterf25

    walterf25 Well-Known Member Licensed User

    I think i know what you mean, you have the counter on the main activity, in this case the behavior you are seeing is normal, because you are trying to access a view which is on the main activity from a service. The main activity is not accessible from a service when the screen is off, if you were to display the counter in the notification you will see that counter keeps updating regardless of whether the screen is on or off.

    Cheers,
    Walter
     
    brodmuehler likes this.
  6. brodmuehler

    brodmuehler Member Licensed User

    Hi Walter

    thanks for your responses. I have to say that I struggle a bit to get my head around the issue. I thought, that the counter itself is on the Service and hence keeps running. Theonly think that is on the main activity is the label that dispalys the value, it gets from the Service with the counter. I also was of the impression that you actually cannot declare a view in a Service and that I must hand it over to the main activity for display. I must have missed something.

    Regards
    René
     
  7. walterf25

    walterf25 Well-Known Member Licensed User

    T
    The counter will keep running as long as the service is kept alive, but the label in the main activity will not keep updating if the screen is turned off, this is because the main activity gets paused when the screen turns off, once you turn the screen back on the main activity resumes and you will notice that the value on the label will jump from where it left off when the screen turned off to where the counter is currently at when the screen turns on again.

    Hope this explains it a little better.
    Walter
     
    Peter Simpson, lemonisdead and NJDude like this.
  8. brodmuehler

    brodmuehler Member Licensed User

    Hi Walter
    that is exactly what I thought would happen and I actually can see the time jumping when I switch the phone back on and the activity resumes. But there is something that is not working properly. I did the following experiment: I started my stopwatch and the stopwatch on an iPad at the same time. I let my stopwatch running for 10 minutes and avoided that my phone switched off. I stopped both stopwatches and took picture B1. As you can see the stopped time is pretty much the same on both devices. Then I started both stopwatches again but this time I allowed my phone to switch off. I switched my phone back on after 10 minutes and took a second picture B2 from both stopwatches. On B2 you can easily see that the time difference is huge. As far as I can conclude there must be something wrong with my Service module.
    Do you have any idea?
    Kind regards
    René
     

    Attached Files:

    • B1B2.zip
      File size:
      394.3 KB
      Views:
      86
  9. Straker

    Straker Active Member Licensed User

    I'm not very sure, but I think that you cannot have a service restarted each second. When your phone goes to sleep it slows everything down in order to minimize power consumption. Normally service are used for 'slow' tasks which works in background (for example download a huge file, check for something avery hour...) not to perform actions every single second.

    I suppose that if your stopwach will count every 5 minutes and not every second, it will work just fine.
     
    brodmuehler likes this.
  10. brodmuehler

    brodmuehler Member Licensed User

    Hi
    That could well be the case. Going to a 5 minute interval does not support what I want to achieve. There must be a way to make this work. There countless stopwatch apps out there that work fine also when the device go to sleep. I guess I just need to find the right way to do it. Thanks for looking into this and please let me know when you have any idea. Highly appreciateed.
    Regards
    Rene
     
  11. walterf25

    walterf25 Well-Known Member Licensed User

    Actually there is no need to re-start your service every second, you can simply keep the timer running inside the service at a 1 second interval, i forgot to mention that to you yesterday, there is no reason you need to re-start your service every second.

    Cheers,
    Walter
     
  12. brodmuehler

    brodmuehler Member Licensed User

    Hi Walter
    thanks again. That was an excellent idea and I think it improved the situation. But my stopwatch is still lagging behind and the delta still gets bigger over time. The timer is in milliseconds, isn't it?
    Thanks and regards
    René
     
  13. walterf25

    walterf25 Well-Known Member Licensed User

    Maybe i'm confused, but i don't really understand what the problem is.
    Can you explain again how is it that you are getting that huge difference between both stop watches.
    When you turn off the screen the counter will continue running since it is running inside a service, however the label in your main activity will stop updating since the main activity is paused.
    If you add the counter to the notification bar, you will notice that it maintains accurate.

    Regards,
    Walter
     
    brodmuehler likes this.
  14. brodmuehler

    brodmuehler Member Licensed User

    Sorry Walter
    I really do not want to confuse you. Everything you are saying is correct. Turning off the screen stops the label to be updated and when I turn the screen back on the number in the label jumbs up. The counter in the service keeps running in the background but compared to the reference stopwatch, my counter is too slow.

    When you say I should "add the counter to the notification bar", what does that really mean. I attached my code again with the changes I made so far. I really do want to waste your time, but perhaps you have a moment to have a look at my code. You might be able to spot the problem straight away. What happens if you run my stopwatch against one of yours, assuming you have a second device with a stopwatch. Perhaps there is something wrong with my phone.

    Thanks a lot for your patience.
    Kind regards
    René
     

    Attached Files:

  15. RandomCoder

    RandomCoder Well-Known Member Licensed User

    I think that your problem is that you need to set a PartialLock to prevent the CPU from going to sleep. To do this select "Phone: v2.26" from the libraries list and then add a PartialLock to your code, see pws entries below...
    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.
     
        
    Dim Timer1 As Timer
        
    Dim pws As PhoneWakeState
    End Sub

    Sub btnStart_Click
     
        Timer1.Enabled=
    True
          
    StartService(TestService)
        
    ToastMessageShow("Service Started!"False)
        pws.PartialLock
    End Sub

    Sub btnStop_Click

        
    StopService(TestService)
        Timer1.Enabled=
    False
        pws.ReleasePartialLock
     
    End Sub
     
    brodmuehler likes this.
  16. brodmuehler

    brodmuehler Member Licensed User

    Hi
    That really made a difference. It is still lagging a little bit compared to my reference stopwatches in my Android and Apple tablet but close enough that I can use it for what I want to do. However, should someone wants to create a real accurate stopwatch my code would not work. Something is still wrong.
    Thanks a lot for the great help. It is recognized and highly appreciated. Regards Rene
     
  17. RandomCoder

    RandomCoder Well-Known Member Licensed User

    The problem with accuracy is a different one. I believe that the timer internal cannot be relied on for accuracy due to the nature in which tick events are queued in the Android system. You will probably need to sense check and correct the accumulated time using the system clock maybe every 5 minutes, just an idea?
     
    brodmuehler likes this.
  18. brodmuehler

    brodmuehler Member Licensed User

    Interesting point. Would be good to understand how the other apps are coded. Is there an alternative to the timer that goes back to a more accurate signal. Regards René
     
  19. fixit30

    fixit30 Active Member Licensed User

    Another approach for a truly accurate stopwatch would be to store the datetime into a variable when the stopwatch is started, and then with each tick calculate the elapsed time between datetime.now and the start time.
     
  20. RandomCoder

    RandomCoder Well-Known Member Licensed User

    I didn't expect this to cause me as much trouble as it has! I ran into an unexpected problem whereby storing DateTime.Now when the service is created then subtracting it from DateTime.Now with each tick of the timer resulted in an additional hour appearing for some reason???
    I don't understand this but I also found that DateTime.Time(0) results in a hour being returned, is this a bug?
    Anyhow, luckily the problem has been experienced before Time format & milliseconds and @Erel has come to the rescue again.

    Here is your example using a slightly modified version that excludes the milliseconds...

    Main Activity...
    Code:
    #Region  Project Attributes
        
    #ApplicationLabel: ServiceExample
        
    #VersionCode: 1
        
    #VersionName:
        
    'SupportedOrientations possible values: unspecified, landscape or portrait.
        #SupportedOrientations: unspecified
        
    #CanInstallToExternalStorage: False
    #End Region

    #Region  Activity Attributes
        
    #FullScreen: False
        
    #IncludeTitle: True
    #End Region

    Sub Process_Globals
        
    Dim Timer1 As Timer
        
    Dim pws As PhoneWakeState
    End Sub

    Sub Globals
        
    Dim btnStart As Button
        
    Dim lblCount As Label
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    Activity.LoadLayout("MyLayout")
        Timer1.Initialize(
    "Timer1",250)
    End Sub

    Sub Activity_Resume
    End Sub

    Sub Activity_Pause (UserClosed As Boolean)
    End Sub

    Sub btnStart_Click
        Timer1.Enabled=
    True
          
    StartService(TestService)
        
    ToastMessageShow("Service Started!"False)
        pws.PartialLock
    End Sub

    Sub Timer1_Tick
          lblCount.Text=FN(TestService.tp.Hours) & 
    ":" & FN(TestService.tp.Minutes) & ":" & FN(TestService.tp.Seconds)
    End Sub

    Sub btnStop_Click
        
    StopService(TestService)
        Timer1.Enabled=
    False
        pws.ReleasePartialLock
    End Sub

    Sub FN(n As Int) As String
       
    Return NumberFormat(n, 20)
    End Sub
    Service Module...
    Code:
    #Region  Service Attributes
        
    #StartAtBoot: False
        
    #StartCommandReturnValue: android.app.Service.START_STICKY
    #End Region

    Sub Process_Globals
        
    Dim TimerService As Timer
        
    Dim Noti1 As Notification
        
    Dim ts As Long    ' TimeStarted
        Dim te As Long    ' TimeElapsed
        Dim tp As Period' TimePeriod
    End Sub

    Sub Service_Create
        ts = 
    DateTime.Now
        TimerService.Initialize(
    "TimerService",200)
          TimerService.Enabled=
    True
      
        Noti1.Initialize
        Noti1.Icon = 
    "icon" 'use the application icon file for the notification
        Noti1.Vibrate = False
        Noti1.Sound = 
    False  
        Noti1.Light=
    False
        Noti1.SetInfo(
    "Service Example""Counter", Main)
        
    Service.StartForeground(1, Noti1)
    End Sub

    Sub Service_Start (StartingIntent As Intent)
    End Sub

    Sub Service_Destroy
        
    Service.StopForeground(1)
        
    ToastMessageShow("Service Stopped!"False)
    End Sub

    Sub TimerService_Tick
        te = 
    DateTime.Now
        tp = PeriodBetweenWithMilliseconds(ts, te)
    End Sub


    Sub PeriodBetweenWithMilliseconds(time1 As Long, time2 As Long) As Period
       
    Dim p As Period = DateUtils.PeriodBetween(time1, time2)
       
    Return p
    End Sub
     
    brodmuehler and fixit30 like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice