Android Question Putting a service to sleep

rleiman

Well-Known Member
Licensed User
Hi Everyone,

I'm trying to get my head around scheduling services to wake up then make it sleep. Can you look at my code because this simple app gets stuck in a loop waking up over and over again as soon as it is woken up using SetExactAndAllowWhileIdle. This indicates I'm missing some coding to put it to sleep or I'm not using the correct coding.

The logic for this simple app is the user will click on a button to start the service. Once the service is started it uses kvs.get to retrieve the time when it should start up again then it should go back to sleep and wake up at a later time. It does actually wake back up but then it gets stuck in a loop.

This is the main module:
B4X:
#Region  Project Attributes
    #ApplicationLabel: Service Wakeup Test
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

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

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private kvs As KeyValueStore
    Private ButtonStartService As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)

    Activity.LoadLayout("Main")

    ' Initialize.
    '------------
    kvs.Initialize(File.DirInternal, "Settings")  
    kvs.Put("ServiceWakeupTime", "18:00")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

' Event handlers.
'----------------
Sub ButtonStartService_Click

    StartService(ServiceWakeup)

    ToastMessageShow("The time to wake up at " & kvs.Get("ServiceWakeupTime") & _
        " is now set." , True)
       
    StopService(ServiceWakeup)  
       
    Activity.Finish
End Sub
This is the service:
B4X:
#Region  Service Attributes
    #StartAtBoot: False
   
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Private sf As StringFunctions
    Private kvs As KeyValueStore
    Private nNotify As Notification
    Private phWakeState As PhoneWakeState
   
    Private lngTimeToWakeup As Long
End Sub

Sub Service_Create

    phWakeState.PartialLock
    Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS

    sf.Initialize

    nNotify.Initialize
    nNotify.Icon = "icon"
    nNotify.Sound = False
    nNotify.Light = False
    nNotify.Vibrate = False
    nNotify.SetInfo("Service Wakeup Test", "I'm at Service_Create.", "")
    nNotify.Notify(1)
   
    kvs.Initialize(File.DirInternal, "Settings")  
   
    lngTimeToWakeup = TimesToTicks(sf.Mid(kvs.Get("ServiceWakeupTime"), 1, 2), _
                    sf.Mid(kvs.Get("ServiceWakeupTime"), 4, 2), "00")

    SetExactAndAllowWhileIdle(lngTimeToWakeup, "ServiceWakeup")
End Sub

Sub Service_Start (StartingIntent As Intent)
   
    nNotify.Initialize
    nNotify.Icon = "icon"
    nNotify.Sound = False
    nNotify.Light = False
    nNotify.Vibrate = False
    nNotify.SetInfo("Service Wakeup Test", "I'm at Service_Start.", "")
    nNotify.Notify(2)
       
    Service.StopAutomaticForeground 'Call this when the background task completes (if there is one)
    phWakeState.ReleasePartialLock
    StopService(Me)
End Sub

Sub Service_Destroy

End Sub

' Misc sub routines.
'-------------------
Sub SetExactAndAllowWhileIdle(Time As Long, ServiceName As String)
    Dim Phone As Phone
    If Phone.SdkVersion < 23 Then
        StartServiceAtExact(ServiceName, Time, True)
    Else
        Dim in As Intent
        in.Initialize("", "")
        in.SetComponent(Application.PackageName & "/." &  ServiceName.ToLowerCase)
     
        Dim Jin As JavaObject = in
        Jin.RunMethod("setAction", Array(Null))
     
        Dim ctxt As JavaObject
        ctxt.InitializeContext
     
        Dim Am As JavaObject = ctxt.RunMethod("getSystemService", Array("alarm"))
     
        Dim Pi As JavaObject
        Pi = Pi.InitializeStatic("android.app.PendingIntent").RunMethod("getService", _
            Array(ctxt, 1, in, 134217728))
        Am.RunMethod("setExactAndAllowWhileIdle", Array(0, Time, Pi))
    End If
End Sub

Sub TimesToTicks (Hours As String, Minutes As String, Seconds As String) As Long
   
    Dim strTime As String

    DateTime.TimeFormat="HH:mm:ss"
   
    ' Pad an extra 0 if needed for the time strings.
    '-----------------------------------------------
    If Hours.Length=1 Then
        Hours="0" & Hours
    End If
   
    If Minutes.Length=1 Then
        Minutes="0" & Minutes
    End If
   
    If Seconds.Length=1 Then
        Seconds="0" & Seconds
    End If
   
    ' Build time string.
    '-------------------
    strTime = Hours & ":" & Minutes & ":" & Seconds
   
    ' Return the ticks value of the time string.
    '-------------------------------------------
    Return DateTime.TimeParse(strTime)
End Sub
 
Last edited:

rleiman

Well-Known Member
Licensed User
Where is the next time ?


You are calling ServiceWakeup at 18:00 over and over again.

Hi,

When the user taps a button the app starts the service then assigns another time 18:00 to start the service up again.

I also discovered the constant looping does not happen if I remove this line in Service_Start:

B4X:
StopService(Me)
There is another problem that crept up. This line causes the phone to vibrate even though I have lines that set the vibration to false:

B4X:
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS
If I remove that line, everything works normal without the vibrations.
 

XbNnX_507

Active Member
Licensed User
constant looping does not happen if I remove this line in Service_Start:
as i said before, it happens because you are calling ServiceWakeup at 18:00 over and over again at a later time ( ex 18:01 , 18:02), This seems to be an Oreo thing since in marshmallow or kitkat this would not happen. ( ServiceWakeup would never had been executed if the time has passed. )

This line causes the phone to vibrate even though I have lines that set the vibration to false
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS
This is normal behavior, user will be notified when foreground services are running.
 

rleiman

Well-Known Member
Licensed User
as i said before, it happens because you are calling ServiceWakeup at 18:00 over and over again at a later time ( ex 18:01 , 18:02), This seems to be an Oreo thing since in marshmallow or kitkat this would not happen. ( ServiceWakeup would never had been executed if the time has passed. )


Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS
This is normal behavior, user will be notified when foreground services are running.
Hi,

At least I know I can now stop the looping by not using StopService.

How about Service.AutomaticForegroundMode? I can live with the notification sounds but a lot of my customers don't want to hear them or even have the device vibrate, but I still want to use Service.AutomaticForegroundMode. Seems like it's over-riding my notification settings. Is there a way to stop it from doing that?

My development device is running on Marshmallow.

Thanks.
 
Top