Android Question How to solve a problem?

Alex_197

Well-Known Member
Licensed User
Longtime User
My app HHA-EVV does clock in and clock out for a home care agent. On clock in / clock out the app sends location and timestamp back to the server. If there is no Internet the data stored in the database. The next time user starts the app right after login the app collects the all unsent info and if Internet is Ok, sends it to the server. But there is a problem. Agent did clock out, didn't have Internet at that time, the info stored in the database and he exited from the app. The next time he started the app 3 days later. If it's a Friday and he returns to the app 3 days later it's already next week and he won't be paid for the days he didn't have Internet even though he did nothing wrong.

I was thinking about creating another app that will constantly run in the background and every hour will check if there is something unsent and if the connection Ok - send it. But as far as I remember - Google Play market doesn't allow background apps anymore. And there is another problem - let's say this background app sends the info to the server and at the same time user started HHA-EVV app which is after login sees also that there is unsent and also will try to send it - it will be disaster.

Maybe we can rise a flag but it's also not reliable solution.

An ideas?

Thanks.
 

emexes

Expert
Licensed User
Check for and warn user of unsent data when exiting app? Won't catch everything, eg if battery runs out, but it can only make things better.

Also, isn't it still possible to schedule app wake-ups? Once per hour doesn't feel like it'd be a huge imposition on battery life. Although presumably you'd want to start nagging the user towards the end of the work week if there is relevant unsent data.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Google doesn't allow "constantly running" background apps, but you should have no problem scheduling a service to run at a specific time each day (just like alarm app works - using StartServiceAt call)

For the situation with the worker not getting paid for last weeks work because there was no internet, you should configure your app to "report in" every day even if there is no new checkin/out data to report. This way, when your backend goes to calculate the weekly payroll, if it didn't hear from your app on a particular day, it could report to the backend admin with a message like "Checkin/out data has not been received from the remote app on day xxxx, so there could be missing wage info that was not reported".

For the situation of both a background service and a user starting the app trying to report at the same time, this should not be a problem because I'm pretty sure the OS will not let two different instances of your reporting service to run, so only one can report at a time. And when the app tries to run the upload routine right after the previous background upload routine ran, it should simply exit immediately because the second call of the service should not find any unsent records to upload because the previous call did that.
 
Last edited:
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Google doesn't allow "constantly running" background apps, but you should have no problem scheduling a service to run at a specific time each day (just like alarm app works - using StartServiceAt call)

For the situation with the worker not getting paid for last weeks work because there was no internet, you should configure your app to "report in" every day even if there is no new checkin/out data to report. This way, when your backend goes to calculate the weekly payroll, if it didn't hear from your app on a particular day, it could report to the backend admin with a message like "Checkin/out data has not been received from the remote app on day xxxx, so there could be missing wage info that was not reported".

For the situation of both a background service and a user starting the app trying to report at the same time, this should not be a problem because I'm pretty sure the OS will not let two different instances of your reporting service to run, so only one can report at a time. And when the app tries to run the upload routine right after the previous background upload routine ran, it should simply exit immediately because the second call of the service should not find any unsent records to upload because the previous call did that.
If the user wasn't scheduled to work this day he won't start the app at all and we will wait until his next schedule day which might be 1 week later.

For the situation of both a background service and a user starting the app trying to report at the same time, this should not be a problem because I'm pretty sure the OS will not let two different instances of your reporting service to run - how does the OS will know about it? The user exited from the app completely, for example by clicking clear all button or just rebooted his phone. Now on the OS start my service will start and then user will start the app a few hours later. Let's assume that Internet connection wasn't Ok and only know the Internet is Ok so how does the OS turned off the service and started my app?
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Simply that if the data is stored locally with the correct date and timestamp, why wouldn't the server app accept that as correct and pay the person appropriately.
Why would the server app only accept real time submissions? If I am way off the mark, just ignore this.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
If the user wasn't scheduled to work this day he won't start the app at all and we will wait until his next schedule day which might be 1 week later.

For the situation of both a background service and a user starting the app trying to report at the same time, this should not be a problem because I'm pretty sure the OS will not let two different instances of your reporting service to run - how does the OS will know about it? The user exited from the app completely, for example by clicking clear all button or just rebooted his phone. Now on the OS start my service will start and then user will start the app a few hours later. Let's assume that Internet connection wasn't Ok and only know the Internet is Ok so how does the OS turned off the service and started my app?
You would not have a separate program - you would simply have a service inside your app that reports the hours in the background at a set time. And since there is only one service that does the upload, then it's impossible to have two services/apps trying to do the upload at the same time.

And you will program this service to run once a day using the StartServiceAt call. Whats cool about this function is that even if the user exits your app, when the set date/time occurs, the service will automatically run even if the user doesn't start the app.

Lets say the report time is 1pm everyday. You could program the service that when it runs at 1pm and the internet is not good, then set the report time to 2pm, etc until it connects. And when it finally connects, then set the next upload to 1pm the following day.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Simply that if the data is stored locally with the correct date and timestamp, why wouldn't the server app accept that as correct and pay the person appropriately.
Why would the server app only accept real time submissions? If I am way off the mark, just ignore this.
How can I sent the locally stored info back to the server without Internet? And if in a few hours later Internet is Ok the app might not be started because the next schedule time for the user might be 3 days later or 1 week later and for one week the whole office won't have any idea about what's is going on until the user will start the app next time.

That's exactly what happened a few days ago. User clocked in, information was sent to the server, then he clocked out but didn't have Internet to send clock out info so the billing department sees that user didn't clock out. We spoke with him and he said - connection problem, will do in the morning. We waited for the whole day (he wasn't scheduled to work this day) and he didn't start the app so nothing was sent. The day after he was scheduled to work started the app and finally sent clock out info.

So we're thinking how to prevent it from happening again.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
You would not have a separate program - you would simply have a service inside your app that reports the hours in the background at a set time. And since there is only one service that does the upload, then it's impossible to have two services/apps trying to do the upload at the same time.

And you will program this service to run once a day using the StartServiceAt call. Whats cool about this function is that even if the user exits your app, when the set date/time occurs, the service will automatically run even if the user doesn't start the app.

Lets say the report time is 1pm everyday. You could program the service that when it runs at 1pm and the internet is not good, then set the report time to 2pm, etc until it connects. And when it finally connects, then set the next upload to 1pm the following day.
Sounds good but it's password protected info because of Department of Health regulation. If the user exited the app - nothing won't be sent because he must to be logged in.
We recorded user's login time and location in the app and send it to the server, not only clock in/out. So the rule is - don't start anything without user authentication.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
You can program the "upload" service to run every hour using the API I mentioned.

When your upload runs, it will upload any unreported checkin/out time if the internet connection is OK. If the connection was not ok, then simply use the API to run the upload service in another hour.

However, and this is important, even if there is no new checkin/out data to report, your app should still send a "No data to report" signal to the back end

The backend software should then be configured to at least expect to hear from the app every hour. And if it doesn't hear from the app, then it should report "I have not heard from the app since xxxx time ago (more then an hour), so there might be checkin/out data that has not been reported.". This way your backend will at least know there might be unreported data. But if the backend did recently hear from your app, then you can safely assume the backend has all the checkin/out data and can print the employee checks.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Sounds good but it's password protected info because of Department of Health regulation. If the user exited the app - nothing won't be sent because he must to be logged in.
We recorded user's login time and location in the app and send it to the server, not only clock in/out. So the rule is - don't start anything without user authentication.

And remember, the StartServiceAt API will run your app's service in the background (at the set time) even of the employee doesn't manually start your app.

I don't see a privacy/security problem for the app to at least say "no new data to report" to the backend every hour - this way the backend will at least know there is no new checkin/out data to report.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
And remember, the StartServiceAt API will run your app's service in the background (at the set time) even of the employee doesn't manually start your app.

I don't see a privacy/security problem for the app to at least say "no new data to report" to the backend every hour - this way the backend will at least know there is no new checkin/out data to report.
DOH and the common sense are not always compatible - the rule is - no login time recorded - don't do anything. But yes, that I'm going to do - create a notification for a billing department that clock in / clock out wasn't sent and let them to take care about it over the phone to nudge the user if he wants to be paid.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Sounds good but it's password protected info because of Department of Health regulation. If the user exited the app - nothing won't be sent because he must to be logged in.
We recorded user's login time and location in the app and send it to the server, not only clock in/out. So the rule is - don't start anything without user authentication.
Are you saying that once the user "checks IN", it is OK to send data to the backend, but once the user "checks OUT" that your app is prohibited from sending any data to the backend?
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Are you saying that once the user "checks IN", it is OK to send data to the backend, but once the user "checks OUT" that your app is prohibited from sending any data to the backend?

App is prohibited from sending any data to the backend if the user is not authenticated by entering username / password.

I mean that if the user clicked on Exit button and stopped the app or even if he didn't stop the app and the app is still running he might be logged out like on the web site. For example user logged in, did clock In, sent the info back to the server and left the phone on a table for 1 hour. Upon his return he will see a message - your idle time (30 minutes) has expired, please login again. It was done as a precaution in case the phone was lost or stolen and the app was running when it happened. So in either case - the user wasn't logged in and because of that nothing can be send.

Briefly

On login - send the info (time stamp and location)
On clock In - send the info
Between clock in and clock out - send the info (it calls task info describing what he is doing, he must to fill them before open clock out screen and this info will be send back to the server with time stamp and location)
On clock Out - send the info (time stamp and location)

The worst case scenario - no Internet for the whole day, let's say user is in some rabbit hole or even in Manhattan, believe me - there are a lot of places in Manhattan even now when you can loose your connection just around the corner.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
You would not have a separate program - you would simply have a service inside your app that reports the hours in the background at a set time. And since there is only one service that does the upload, then it's impossible to have two services/apps trying to do the upload at the same time.

And you will program this service to run once a day using the StartServiceAt call. Whats cool about this function is that even if the user exits your app, when the set date/time occurs, the service will automatically run even if the user doesn't start the app.

Lets say the report time is 1pm everyday. You could program the service that when it runs at 1pm and the internet is not good, then set the report time to 2pm, etc until it connects. And when it finally connects, then set the next upload to 1pm the following day.
Can you show me some examples how to use StartServiceAt ?

Thanks
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Just do a search in this forum - this was the first entry:

StartServiceAt (Service As Object, Time As Long, DuringSleep As Boolean)Schedules the given service to start at the given time.

Service - The service module. Pass Me when calling from a service module that schedules itself.
Time - The time to start the service. If this time has already past the service will be started now.
The actual delivery time might change to reduce battery usage. Use StartServiceAtExact if the exact time is important.
DuringSleep - Whether to start the service when the device is sleeping. If set to false and the device is sleeping
at the specified time, the service will be started when the device wakes up.
Setting DuringSleep to True can have a large impact on the battery usage.
StartServiceAt can be used to schedule a repeating task. You should call it under Service_Start to schedule the next task.
This call cancels previous scheduled tasks (for the same service).
Example:
StartServiceAt(SQLService, DateTime.Now + 30 * 1000, false) 'will start after 30 seconds.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Thanks
Just do a search in this forum - this was the first entry:

StartServiceAt (Service As Object, Time As Long, DuringSleep As Boolean)Schedules the given service to start at the given time.

Service - The service module. Pass Me when calling from a service module that schedules itself.
Time - The time to start the service. If this time has already past the service will be started now.
The actual delivery time might change to reduce battery usage. Use StartServiceAtExact if the exact time is important.
DuringSleep - Whether to start the service when the device is sleeping. If set to false and the device is sleeping
at the specified time, the service will be started when the device wakes up.
Setting DuringSleep to True can have a large impact on the battery usage.
StartServiceAt can be used to schedule a repeating task. You should call it under Service_Start to schedule the next task.
This call cancels previous scheduled tasks (for the same service).
Example:
StartServiceAt(SQLService, DateTime.Now + 30 * 1000, false) 'will start after 30 seconds.
Do I need to call
B4X:
StartServiceAt

on main activity create?
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I believe you can call it from anywhere - even from within the service you want to schedule.
 
Upvote 0
Top