Android Question Services (Can't keep it alive)

walterf25

Expert
Licensed User
Longtime User
Hello all, i've been noticing this problem for a very long time, i have read all the threads that talk about Services, I stopped working on an app almost a year ago because i could not figure out why my Services were being killed and not re-started.

Basically i was working on an Email Client App, I use Starter Service as the entry point to initialize, connected and authenticate the user's email address and login information, I use a library i wrapped that takes care of the oAuth2 part of it, I can authenticate the email address and login using the Access Token from the oAuth2 side of it, all this works just fine, i can retrieve all the emails from the Inbox and display them on a listview just fine.

The problem is that I have a separate Service which checks for New Emails every 30 seconds and displays a notification if there's a new email, Everything works fine as long as i keep my USB cable connected to the phone, i have even created a file which logs all the important events to it just so that I can see what's going on when I disconnect the USB cable. I do acquire a Partial lock at the beginning of the Service to prevent the CPU from going to sleep as advised on a few threads i've read.
The application runs fine for a while after disconnecting the USB cable, the issue is that the based on the logs i've obtained from the logs file i can see that the Service will stop being re-scheduled after a while, i can even see the Starter Service is also stopped and not re-started, I would like to get to the bottom of this problem if it is a problem at all, i wouldn't doubt that I might be doing something wrong, but i have tried extensively to make this app work but got frustrated and stopped working on it as I mentioned before.

I use StarServiceAt to schedule the service to be started every 30 seconds, I can see in the logs file that indeed the service is re-started every 30 seconds for a while but then it just stops, I have also added Try, Catch blocks everywhere in my code and log the exceptions to the logs file but so far I have not seen any errors/exceptions in the logs file that tells me something crashed, at least that would give me an idea of what is going on, but the Services just stop.

Based on the last logs file i obtained from a test done last night the app/Services only ran for about 43 minutes, I re-started the app this morning at 7:21AM and the Services stopped at 7:47AM, i am attaching the logs file from this morning's run.

One thing i did noticed is that while checking in the logs if the Services is started every 30 seconds, at 7:34 the service was re-started and re-scheduled but it didn't get re-started until 7:37 that's about 3 minutes difference, why is that?

any how, i hope someone who has came across this issue can shed some light, maybe i just don't understand how to use Services?.

I have replaced part of the access token in the logs file with 'XXXX" for security purposes.

Thanks everyone.
 

Attachments

  • Logs2.txt
    17 KB · Views: 392

Peter Simpson

Expert
Licensed User
Longtime User
Upvote 0

walterf25

Expert
Licensed User
Longtime User
This will not work. The minimum interval is 15 or 30 minutes.

If you want to do something every 30 seconds then you should use a foreground service.
Thanks for the reply Erel, how are this type of applications achieved without having to display a notification then? I mean there are tons of apps out there that do this, i did a test last night, i created a different test project with a service running every 30 seconds and just doing a for loop from 0 to 499 and logging the iterations in a text file just to see if i saw the same behavior as my email app, i looked at the logs this morning and it seems that the service never stopped, i ended up with a huge log file which is what i was expecting, but i believe this was due to my phone being charging all night, if this is the case what is the reason for the service to be kept alive while the phone is being charged, although the phone was placed on my wireless charger, is this because the CPU never goes to sleep, if so, isn't it the same when we acquire a partial wake lock?

In the case of the official Gmail app, how are they able to display a notification as soon as a new email arrives, they must be keeping some type of background service to check for this? wouldn't that be the case?

Am i missing something?

Thanks,
Walter
Thanks Peter, i've already looked at that but i don't want to display a notification to maintain my service running in foreground mode.

Thanks,
Walter
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Hi Erel, I understand and have used firebase messaging on a number of apps already, what I'm still confused about is how will I check for new emails every 30 seconds, the firebase messaging is only to receive to the push notifications, what will be providing the push notifications in this case?

I guess my confusion is still about having my library check for any new emails every 30 seconds, to do this as I understand i need to do it in a service, If I use firebase messaing how will this help me achieve that? based on the times i've used firebase messaging there has to be a server which pushes the messages and the service in the application will receive this message and raise a push notification, are you saying I would need to implement the part of my library which checks for new emails every 30 seconds inside this firebase message Service?

Walter
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The only way for your app to do something every 30 seconds is by using a foreground service. This is not a good idea in most cases.

The "correct" solution is to use push notifications. The server will notify the client when there are new messages. The exact details depend on your specific requirements.
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
The only way for your app to do something every 30 seconds is by using a foreground service. This is not a good idea in most cases.

The "correct" solution is to use push notifications. The server will notify the client when there are new messages. The exact details depend on your specific requirements.
Thanks Erel, the question is how would the server know when there is a new message, does that mean i have to implement Google's Mail API running on a separate server which will then push the notification to the device/client?

Walter
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
how would the server know when there is a new message

Of course you must have an own server. Are you really talking about emails? I assume you mean exchanging "messages".

I do it like WhatsApp:

1. Server with php and MySQL (cheap for 10$/month). If you get more users, change the plan
2. One client app (a) sends a message to another client (b)
3. Via OkHttpUtils client app a calls a php script (secured of course) and the message is written to a database
4. The script knows who is getting this message and sends a FCM message (data) to client b
5. The receving app b is getting the FCM message an fetches the message via the php script and the message is deleted from the db
6. The sender is getting a FCM message "fetched" (you know the two blue checkmarks from WhatsApp)

I mostly try to handle all the communication like the OS does: Event triggered. So I never came across the problem like "my service isn't running anymore".
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Of course you must have an own server. Are you really talking about emails? I assume you mean exchanging "messages".

I do it like WhatsApp:

1. Server with php and MySQL (cheap for 10$/month). If you get more users, change the plan
2. One client app (a) sends a message to another client (b)
3. Via OkHttpUtils client app a calls a php script (secured of course) and the message is written to a database
4. The script knows who is getting this message and sends a FCM message (data) to client b
5. The receving app b is getting the FCM message an fetches the message via the php script and the message is deleted from the db
6. The sender is getting a FCM message "fetched" (you know the two blue checkmarks from WhatsApp)

I mostly try to handle all the communication like the OS does: Event triggered. So I never came across the problem like "my service isn't running anymore".
Thanks for the response Kmatle, i am using a library I wrapped which is supposed to handle everything, as i mentioned on my first post, the library works great, it handles all the communication with the iMAP server etc. there are two methods in the library which can be used to check for any new emails, one is called CheckforNewEmails which does a search in the INBOX folder for any new UID (Unique Identifier Number) if there are any new UIDs then you can call the FetchEmailByUID method which retrieves all the information including attachments from any new emails, this part also works great, the only problem is calling this methods in a background service, because this methods would have to be called at least every 30 seconds, and as I understand the Services created with B4A have a minimum interval of 15 or 30 minutes, the second method is called idlecheck, this method only checks for any new UIDs but doesn't actually fetch the actual email information, but then again it also needs to be called every so often to check for any new emails.

I'd like to give your solution a try, i'm not sure if you can share some of your scripts, i have done very little work in PHP, i'm sure i can come up with a good solution if i can take a look at an example, i have no idea how to implement the email server side, so please let me know if you can at least point me in the right direction.

By the way I do plan on releasing this library once i have this part working, this library can do iMAP, POP3, SMTP, it handles the oAUTH2 part internally, and has many more classes which i have not wrapped yet, i can wrap them as needed but for now i only wrapped what I needed for my purposes.

Thanks again, hope to hear back from you soon.

Walter
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi @walterf25
my understanding is that you problem is mainly due to where you run the 30 seconds check.
As @KMatle showed above, having a server (or even a PC running H24..) performing the check, then sending an FCM message to your mobile app will solve it.

I don't know whether you already used B4J, but it won't be that difficult to write a non-UI server program which checks an email account every 30secs, stores locally UIDs and sends out alerts for newer ones only.
As a first attempt, you could use your developing PC as the "server". Once everything is sorted out, just buy a cheap VPS plan and run your own B4J program on it. This is to avoid the PHP part of the above hint since you seems to feel uncomfortable with it. Going the PHP way buys you a cheaper hosting plan (PHP+MySql are standard offerings) while the VPS route will cost a bit more.

One way or the other, the recurring check should be run outside your mobile app.

udg
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Hi @walterf25
my understanding is that you problem is mainly due to where you run the 30 seconds check.
As @KMatle showed above, having a server (or even a PC running H24..) performing the check, then sending an FCM message to your mobile app will solve it.

I don't know whether you already used B4J, but it won't be that difficult to write a non-UI server program which checks an email account every 30secs, stores locally UIDs and sends out alerts for newer ones only.
As a first attempt, you could use your developing PC as the "server". Once everything is sorted out, just buy a cheap VPS plan and run your own B4J program on it. This is to avoid the PHP part of the above hint since you seems to feel uncomfortable with it. Going the PHP way buys you a cheaper hosting plan (PHP+MySql are standard offerings) while the VPS route will cost a bit more.

One way or the other, the recurring check should be run outside your mobile app.

udg
Hi udg, i have managed to port the B4A library to B4J, i was able to get one of Erel's Server's examples and modify it to fit my needs, the way i'am doing it now is that i have added some more code the B4A app where it sends the access token used to login (obtained through oAuth2) to the B4J app, the B4J app then takes this access token key and logs in with the given email address and start checking for new emails every 30 seconds, I have added the FireBase push notifications code to the B4A app and when there's a new email the B4J app sends a push notification to the B4A app, this works beautifully, i think this has a lot of potential.

I was able to run the B4J jar file on a google virtual machine running linux Debian and it runs just fine too.

Now my next challenge is figure out how to run multiple instances of the class that is taking care of checking for new emails but for many more users not just one, any ideas?

Regards,
Walter
 
  • Like
Reactions: udg
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Walter,
first of all let me congratulate for having achieved what you planned. (IMHO you've got now enough material to publish a great tutorial..ehehe)
To serve several users, I will think about a DB table where you register the users to serve and a function to call a few times per day (or just once) to load this list in an array or list in your existing program.
At given intervals (30 secs) you iterate on the array and pass that info to a function that initiate the discovering mail management you already have.

As a second thought, for each customer you could record how often to check for his/her new mail.

How much is "much more users"? Tens, hundreds, more?

Regards,
udg
 
Last edited:
Upvote 0
Top