Android Question Notification service that runs after 24 hours

ThRuST

Well-Known Member
Licensed User
I want to create a service that runs after 24 hours from when it is started and show a notification, and at the same time the service must stop. (It will be run again in the app). Can someone please provide a working example with subs included to easily understand what's going on. Many people tend to post only a short code snippet in belief that everybody will know how a service works but this is not always the case. If the service is started at 12.00 the first time it will run again the next day at 12.00 even when the phone is restarted. I have read many posts about people using timers and that works for me as well but there's not much about what I want, which is more complicated but more effective as it saves the battery. It is not clear about the differences between ServiceStart and ServiceStartAt as well as how to associate the timed service with something that will happen so an explanation about service_create_service_start_service_tick and service_destroyed is appreciated to know how to start and stop the service. As this is more complex than using a counting timer please prove a complete example in which subs to put the code. It is important to use services with caution especially when started at bootup or else it will cause problems since it will be difficult to stop the service that's why I ask help in this matter. Adding the extra time to provide subs will probably be of great help to many.

Cheers,
ThRuST
 

Erel

Administrator
Staff member
Licensed User
Timers will not help at all.

Have you seen the services tutorial? http://www.b4x.com/android/forum/threads/7542/#content

StartService - Starts the service now.
StartServiceAt - Starts the service at the scheduled time.

Nothing bad will happen if you don't stop the service.

You just need to call:
B4X:
StartServiceAt(me, DateTime.Add(DateTime.Now, 0, 0, 1), true)
In Service_Start. The service will be started each day. You also need to start the service after boot (to make the first start).
 

ThRuST

Well-Known Member
Licensed User
Thanks for pointing this out. The last parameters is what I understand time and during sleep on or off, and service_create takes care of the global variables and service_start handles the time service should start. But where to put the code to do stuff? If I put it right under service_start ir fires at the same time I start the service with StartService(TmrService) from a button in the activity. So what about this? I must start the service from a button, and the service should start after 24 hours!!
The idea is to let to user decide if the notification after 24 hours should be active or not, then it's just to start or stop the service. I could use a little counter in service_start from 0 to 2 to avoid the notification to run directly. Perhaps I am making this more complex than it is. So what to do about this? Please also point out the parameters since they are more than what it says in the Intellisense. There's no need to fire the notification directly, since the whole idea is to remind the user the next 24 hours. In this case, to remind to take the medicine. Users will be annoyed if the notification fires once it is taken. I assume android will remember the time when the phone is restarted, or must the time be stored in a file for the phone to 'remember' where to continue? Sorry for growing questions but this is a great way to learn how to deal with the useful services.
 

Erel

Administrator
Staff member
Licensed User

ThRuST

Well-Known Member
Licensed User
I just want to start the service from the activity that will show a notification after 24 hours when the user exits the app and a day has passed. When the service runs the code the service will stop (since it is started again from a button in the activity) The service will just need to act as a simple reminder showing a notification message. It is important that the notification (or other code) does not start directly. That's why it seems confusing to use StartService(TmrService) in the activity to start the service directly (which should run later!!). So to sum things up I appreciate you other programmers fill me in on this. Thanks.



Service_Start

hour and minute are global variables

' Here we start the service at a specific hour and minute value

StartServiceAt(Me, DateTime.Add(DateTime.Now, hour, minute, 1), True)

' Code that will run because of the scheduled service
If StartingIntent.HasExtra("android.intent.extra.ALARM_COUNT") Then

' Shows notification message
ShowNotification

end if

end sub


Sub ShowNotification

Dim n As Notification
n.Initialize
n.Icon = "icon"
n.AutoCancel = True
n.Sound = False
n.Vibrate = True
n.SetInfo("appname", "message goes here", Main)
n.Notify(1)

End Sub
 

lemonisdead

Well-Known Member
Licensed User
it seems confusing to use StartService(TmrService) in the activity
Not if you plan your service in the Activity_Pause of your main Activity
B4X:
Sub Activity_Pause (UserClosed As Boolean)
    If UserClosed Then
        StartServiceAt(TmrService,DateTime.Now+24*DateTime.TicksPerHour,True) 'Replace with your globals
    End If
End Sub
 

ThRuST

Well-Known Member
Licensed User
Will your solution start the code in the service module? because that's what I used. So lemonisdead, where to put the code that should be run after 24 hours have passed? I am suing a service module maybe your idea is better to keep it simple. Please provide more to your example where the code will run after the schedueled time, thanks.
 

lemonisdead

Well-Known Member
Licensed User
I am sorry, I don't know if I well understand the question : What I had understood is that you want to start your service 24 hours after the user had closed it.
That's the reason why I have suggested to start the notification service using StartServiceAt when the user has closed the Activity. But you could eventually remove the check on "UserClosed" and it will restart the service 24 hours after the user has eventually put the app in the background

In the same spirit, if you put a StartServiceAt inside your service's Sub Service_Destroy, you can restart the service automatically.

Please provide more to your example where the code will run after the scheduled time
The code ran after the scheduled time is the one inside your service TmrService. If the TmrService is already started, the Service_Start sub will be called directly.

I am sorry again, I don't think I well understand the question but I will be happy to help more if needed
 

ThRuST

Well-Known Member
Licensed User
Sorry for being unclear. Actually I am working on a hospital app that when the user clicks a button to take his medicine, the automatic service will show a notification after 24 hours. It seems to be the most flexible idea. For this to work I have to stop the service and restart it again everytime the user clicks a button. I created a service module for this, but after reading your answer it may seem better to use it directly in the activity. Where should the code be placed when the scheduled time is reached? My example specifies a service module but may be different when used in an activity since I learned to follow Erels advice by using process_globals, service_create, service_start in the service module.
 

lemonisdead

Well-Known Member
Licensed User
Please find attached a sample project. I hope it could help

At the first time, the user has to press the Activity's button to acknowledge that he has taken the pill. Thereafter, the notification is shown after the delay.
For that example, I have set a delay of 10 seconds after the button press and the new notification but you can change the delay as you wish of course

What you'll have to add is to :
  • store / read the target time in case of the user restarts the phone/tablet
  • make the service to start at boot to plan the new notification again
  • a way to stop planning the new reminder
 

Attachments

Last edited:

ThRuST

Well-Known Member
Licensed User
Lemonisdead, do you mind post your code to TakeMyPill.zip in here. I discovered that I have an earlier version of B4A so I cannot open your source code. This will be a problem for everyone with an earlier version so I'd appreciate to study your solution as text. Cheers :rolleyes:
 

lemonisdead

Well-Known Member
Licensed User
B4X:
#Region  Project Attributes
    #ApplicationLabel: TakeMyPill
    #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
    '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 Button1 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("l1")

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_click
    If Not(IsPaused(showNotification)) Then
        StopService(showNotification)
    Else
        StartServiceAt(showNotification,DateTime.Now+10*DateTime.TicksPerSecond,True) 'change the delay : 24*DateTime.TicksPerHour
    End If
    Activity.Finish
End Sub

B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #StartCommandReturnValue: android.app.Service.START_STICKY
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim n As Notification
End Sub
Sub Service_Create
    n.Initialize
    setNotification
End Sub

Sub Service_Start (StartingIntent As Intent)
    If n.IsInitialized Then n.Notify(1)
End Sub

Sub Service_Destroy
    If n.IsInitialized Then n.Cancel(1)
    StartServiceAt(Me,DateTime.Now+10*DateTime.TicksPerSecond,True) 'change the delay : 24*DateTime.TicksPerHour
End Sub

'this sub sets the notification configuration
Sub setNotification
    If n.IsInitialized     Then
        n.Vibrate=True
        n.Icon="alert"
        n.SetInfo("Take your Pill","Click here to acknowledge",Main)
        n.Light=True
        n.Number=1
        n.OnGoingEvent=True
        n.AutoCancel=True
        n.Insistent=True
        n.Sound=True
    End If
End Sub

The l1 layout contains only a button named Button1
And you'll need a alert.png image in \res\Drawable (read only) for the notification's image
 
Last edited:
Top