I'm really new to Android (and java) programming. I'm struggling to create a reliable repeating background task. It should run quite often, let's say in every 10sec, even if the phone is in sleep. I've tried already a lot of things, but without success.
As I learned, AlarmManager is not reliable under ~15min interval.
Tried with FireBase JobDispatcher also.
Now I'm using service and timertask with scheduleAtFixedRate in the background. Till now this is the best, but still unreliable.
In every run of the task I have to do a database read, do some notification if needed, and write some data to DB.
I'm using FULL_WAKE_LOCK also, but still have a lot of missing notifications, or sometimes I get 10-20 notification in the same time with the delay of few minutes.
What would be the right way to do this job and make it reliable?
(push is not possible at the moment from server side)
Related
I have tried many solution but useless, all say use foreground service.
is there a way to trick android or to use a proper way.
i know it's restriction from android to inform the user that an app is draining the battery without using it.
The answer is use a foreground service. You can't have a background service for more than 2 minutes on modern Android.
Now if your timer is long (say 1 minute+) an alarm instead of a timer would work better. That wouldn't require a service, its a broadcast and your app would be restarted to handle it. Of course if you go into Doze those are still limited.
The background services are not encouraged any more from Android Oreo (>25). I want the socket to keep connected in my chat application even when the app is closed.
How can I implement new changes to android 26?
Some people says, use JobIntentService
Some people says, use JobService
Some people says, use JobScheduler
Some people says, start service as Foreground Service
Any help would be appreciated.
I faced the exact same problem working on a chat application so I know your pain. Our conclusion was:
you don't keep a connection alive 24/7, if you need to deliver a
message to an user that has no connection alive, send a push message
via Firebase.
If you want to keep a connection alive in background, you will face many problems. The first one, targeting Oreo, is that if your app is in background (definition of "background" in this context is here) it won't be allowed to run except for small time windows.
You can definitely use JobScheduler to run periodic tasks, they won't be executed at exact intervals or times to reduce battery usage (which is good) but it won't help you in keeping a connection alive. At best, you can use JobScheduler to periodically pull messages from you server. In order to use JobScheduler you need to create a JobService class.
JobIntentService is a new class introduced in API 26 of support library. It is a replacement for IntentService, it will run as a JobService on android API 26+ and as a Service (similar to IntentService in the sense that it will execute code in a background thread) on older APIs. On Oreo its background execution will still be limited so it won't help you in keeping a connection alive.
Using a foreground Service can really help you reducing the likelihood of the process being killed, but, you will need to display a permanent notification. It doesn't sound like a good solution for a chat app.
If you still think that having a 24/7 connection alive is a viable option, you need to consider also doze mode. You could ask the user to whitelist your app to run even in doze mode but you should have a very good reason to do that. Again, you would face the other bg execution limit in Oreo.
Another issue you will face is other apps. There are resources management apps that will aggressively kill other apps in bg to reduce memory and battery usage. For instance, I cursed this one quite a bit.
Another issue is created by android. When the system is running low on memory, it will start killing processes of apps in bg. There is a an order in which they're killed, if I recall correctly should take into account last time it was in fg and current memory usage. Not the worst of the problems but still, it happens.
Then, if I still haven't convinced you in giving up the idea of the permanent connection, let me share with you yet another problem you would face. Some vendors implements extremely aggressive policies when it comes to killing bg processes, so that they're battery will last longer. For instance, Xiaomi.
Last tip, unrelated, but it took us a while to figure this out so I'm going to share it. If the user force stops your app from settings, your app is dead (that is, "stopped state") until the user actively launches it again, it won't even receive Firebase push messages.
If your server is configured on XMPP, then it would be easy for you.
Actually, there isn't any need to keep the socket alive at all the time. This is very expensive for the battery and I'm sure you don't want that.
Case: You are working on a Messaging app.
If your socket is broken, then the client will receive the message in the form of Google FIREBASE notification. And the moment your client will receive a notification from firebase, just enable the socket, and you'll be back on track.
The reason I suggested you to use XMPP is because XMPP maintains a queue of undelivered/offline messages. And when your socket is connected again, you simply pull the offline messages from the server.
I don't think this will help you out, but this may make a room for some another idea for you.
I want to make my app run in the background like a process that runs always.
I need it because I want to get locations update for GPS every 2 minutes (longitude, latitude) and to use the information in a method.
For that I need for the app to be running when the phone is asleep or not in the UI of the app in other words I need the app will run always.
I'm sure that there is a way to make it , thanks anyway for any answers :)
This was just the first google search result I found:
http://www.vogella.com/articles/AndroidServices/article.html
The answer here is to use a service, if this tutorial is lacking there are 6.4 billion others.
We have something like this, but it is made up of several parts.
Firstly you will want your code to run (and be registered in the manifest) as a Service
You will probably also want to request android.permission.RECEIVE_BOOT_COMPLETED so that you can write and register a BroadcastReceiver that gets notified by android.intent.action.BOOT_COMPLETED action and its onReceive method kicks off the service.
In our case we also have a front-end activity which also pokes the service to make sure it is running, but it's been a while snce I checked to see if this was still required.
Our service is nearly empty and onCreate immediately calls a custom Handler which then manages the 'ticks' which wakes the Handler and fires a Runnable if there is work to do, but this is where my code diverges from yours. In our case we only attempt to update the GPS location when the service 'ticks' (usually every minute) and there is work to do. It usually only performs a couple of dozen operations per client per day so I can't really advise on how it will impact battery usage.
I have an application which records information using a tablet which is sync'ed to a server where reports are then run on the results. The users spend all day using the tablets and travel a lot throughout the day.
The time when the users complete these tasks is crucial to the reports and we have had several occurrences where we can't rely on the device time.
The user sometimes manually sets the time to something different on the device in order to look like they have done more work - this happens more than we expected
When relying on the time set to 'automatic', the time sometimes jumps around as the users travel between networks
When the tablet is initially switched on, sometimes the device time is set to 1970
I have a webservice to get the server time which is not currently used because we can't rely on the users having internet connection because they generally don't have any connection at all due to the nature of the work. However, they sync the data everyday usually, or at least once every few days.
I'd like to create something that gets the server time and counts the time from then on and the app would use this time. Any time they connect, this time will be updated, just to make certain the time is synced. Does anyone have any suggestions as to the best way to do this? Bear in mind that the time that we send up is crucial - it could be the case that if misreported on several occasions, someone could lose their job.
Thanks in advance!
Android do have 3 different kind of timer...
SystemClock
One of them will be useful to you,uptimeMillis()
Once the app starts, save the current uptimeMillis... when the app ends.. you could get the difference from "uptimeMillis() - oldUpTimeMillisThatWasStored"...
Android do sent a broadcast when the time or timezone is changed...
And if you have a broadcast receiver which catches for these changes from manifest file...
you will know when the time is changed (even if you app is not running)..
ACTION_TIME_CHANGED
You need persistent internet connection. Otherwise you have to rely on client time which can be modified as you already mentioned. You may be able to track the changes, but only as long as the app is running which can easily be faked by disabling the app (Settings -> Apps) before changing the time.
Scenario:
User completes task, client time gets stored
User modifies time
Device gets internet and syncs with server, telling him its current time and the task so server can calculate tasks "real" completion time. <-- ERROR
I left this unfinished, but have now implemented a solution.
I've created a Service which runs in the background, and downloads the date at intervals from a webservice, and uses a Timer to increment the time in between calls to the webservice.
Further to this, I use GPS to get the current time and date, and it uses this if possible, and if not then it uses this internal clock.
The time should be right most of the time, in theory!
I would like to write my first Android app using Java and I was wondering how to schedule the app to perform a certain task, or call a method at a user-specified time of day. Also, I would like this to happen without having to keep the app constantly running in the background.
Is there a way to have the user set up a time at which the Android system wakes the app to do what it's supposed to do? Or do I have to have the app load on startup and constantly running in the background?
Yes, it's called an Alarm. Have a look at AlarmManager.