Currently, in Android, to do a task periodically based on time or any other factors like charging state, network state etc, the basic three options are: Android AlarmManager (which works periodically based on time), GCMTaskService (requires Google Play Service on device) and JobScheduler (requires Android Version > 21). Recently, I've come across these two libraries for scheduling jobs, one from Firebase and one from Evernote.
My primary question is: How do these two libraries compare? What are their strength and weaknesses?
I want to build an app where a user is reminded of taking medicines periodically after certain time period.
My secondary question is: would simple AlarmManager suffice for this purpose, or should I go for any of these two libraries?
Thanks.
How do these two libraries compare? What are their strength and weaknesses?
There's a nice table of comparison in Firebase JobDispatcher github page:
The key difference is Google Play services presence: Firebase needs device to have it installed, whereas Evernote is Play Services independent.
I want to build an app where a user is reminded of taking medicines periodically after certain time period. Would simple AlarmManager suffice for this purpose, or should I go for any of these two libraries?
The rule of thumb is, that most possibly you won't need AlarmManager, because it is a battery drainer. One of key features of job dispatchers is that they combine jobs and execute them in a single window, thus device won't wake up too often.
You'd better stick with job dispatchers, unless taking medicines should have exact timing like alarm (e.g. you want to notify user to take the medicine exactly in 3 hours).
Related
I've been using WorkManager to create notifications for my app. For my purposes I figured PeriodicWorkRequest is the most fitting, but after a bit of testing and reading online it's seems extremely unreliable. Using the minimal interval (15 minutes), and the app being closed, the worker woke up 5-6 times and then seems to be killed.
So how does one go about creating background work that wakes up in reasonable time intervals? What is the best approach for creating event-based notification? My idea was checking for the event (for example, checking for something new in the database) in small time intervals (with 15 minutes also being less than ideal), but seeing as it doesn't work well with PeriodicWorkRequest and is also the recommended approach as per the documentation, what exactly are my options?
Basically, the idea of Android is for you not to be able to do what you want to do because we as developers try to kill the battery.
You need to see how the evolution of the restrictions goes:
Version 6 - Doze:
https://developer.android.com/training/monitoring-device-state/doze-standby
https://developer.android.com/about/versions/marshmallow/android-6.0-changes#behavior-power
Version 7 Another state of Doze with even more restrictions:
https://developer.android.com/about/versions/nougat/android-7.0-changes#perf
Broadcast Restrictions:
https://developer.android.com/guide/components/broadcasts
https://developer.android.com/about/versions/nougat/android-7.0-changes#bg-opt
Version 8.0 Background execution limits:
https://developer.android.com/about/versions/oreo/background#services
Version 9 StandBy Buckets - where depending on how the app is used you have different resources to use - like time to wake up the app, time to use the Network, etc
https://developer.android.com/about/versions/pie/power#buckets
https://developer.android.com/about/versions/12/behavior-changes-all#restrictive-app-standby-bucket
https://developer.android.com/topic/performance/appstandby
Battery Save improvements:
https://developer.android.com/about/versions/pie/power#battery-saver
Power Management Restrictions - really important.
https://developer.android.com/topic/performance/power/power-details
Version 11 and 12 App hibernation
https://developer.android.com/topic/performance/app-hibernation
Long story short - you need to prevent all these restrictions to harm your work. But you need to comply because it is better for the user.
But there is no API that will just say - "f**k all these restrictions and do whatever the dev wants to do."
If you need exact timing - you need AlarmManager.
If you do not know when you need to do your work and depend on the outside - Push Notifications which then can transfer the work to the WorkManager.
If you need periodic work that is not time-critical - you might not use the AlarmMangaer and be sure that the work is finished, but you can't be sure when, because there are many restrictions and the priority will be saving the resources.
Also, you can ask the user to be exempted from Battery Optimization:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
If you want to know why exactly the work is not executed you need to check the JS dump and see what restriction is not satisfied:
https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging#use-alb-shell0dumpsys-jobscheduler
I want to sync the data with server between 12 am - 6 am only.
I have solutions like WorkManager and sync adapter at my disposal.
But some manufactures put restrictions on these work managers and syncadapter also.
What is a sure shot solution that a network request will can be made between these non active hours(most users are not using the app) ?
There is no sure solution. This is Android. Every vendor can do whatever they like.
What restrictions you are talking about? Because you are saying "some vendors"? In general Android applies restrictions related to how much time you can be executed per 24 hours period and how much network you can use. It is dependant on the Power Bucket you are in. And the Power Bucket itself depends on how often the user interacts with your app. Check here:
https://developer.android.com/topic/performance/power/power-details
You can implement a dialog asking the user to exempt you from Battery Optimization. This will fix the restrictions on most vendors. Check here:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
I currently use the Firebase JobDipatcher to perform a periodic task in the background. The problem is the background service only gets executed when battery optimization is disabled and standby state of the app is manually set to ACTIVE under developer options. Is there a way to do the background task without manually changing all this, because i cannot ask every user of the app to do so. And saw many posts that google will suspend the app if the power management permissions are requested within the app. Any help would be much appreciated.
In one word answer is BIG NO
As developers remains unhappy with such small answers, so i am starting the HUGE theory, here we go -
STRATEGY NO - 1 :
Use AlarmManager
All alarms are forgotten by the android on Reboot, so keep all alarms in app Sqlite database, implement BOOT_COMPLETED broadcastreceiver, which is still allowed to define statically & re-schedule all alarms by taking from apps database.
All your project & hard work will work as per your plan, but only on emulators
Because in real world, 99% devices are with chinese ROMs like MIUI, OxygenOs, ColorOs, FunTouchOs, .. which never triggers your apps BOOT_COMPLETED broadcastreceiver.
Because they all are ahead in saving battery life, by stopping all apps background services..!!
Nice question,:- Then why whatsapp, facebook, tiktok, twitter processes are getting executed normally...?? And why not mine...??
Nice answer,:- If Chinese ROMs disallowed above apps background services then no one will buy their devices..!! And lets do not talk about your application as it does not affect the world in any way, your app is useless ( as per chinese ROMs ) , so they disallows all other packages background tasks..!!
All Chinese ROMs never triggers AlarmManagers if the app is not in foreground. Never triggers if app is removed from recents
In short & sweet treat Alarmmanager as depriciated.
STRATEGY NO - 2 :
Use FirebaseJobScedular as you stated
If user updates Google Play Services , then system forgets all jobs..!!
Again FirebaseJobScedular was developed to run all jobs on every device in market, but as chinese ROMs never allows any processes / classes / Jobs from their own wishlist, this makes no sense again.
This library is depriciated by google now.
STRATEGY NO - 3 :
Use WorkManager, the new library which is taking place over the FireBaseJobScedular officially.
Again the same thing, WorkManager is still in development, you can use it, but the case is same that many chinese ROMs discard this libraries jobs too..!!
STRATEGY NO - 4 :
Run all time foreground service.
BOOT_COMPLETED from your broadcastreceiver start it again.
But even if you use START_STICKY, many chinese ROMs used to suspend its tasks, you can see it in foreground, but works gets suspended.
STRATEGY NO - 5 :
Use WakeLocks
But as the android version changes, it has changed to the newer newer implementational strategies in every versions
STRATEGY NO - 6 :
Programatically make battery optimisation off for your app, but google discontinues your app from app store in such case
Navigate user to battery optimisation settings intent, by opening it programatically & let him choose battery optimisations on his own, is allowed by google
But as no user is in market, who knows it, as even many developers dont know this yet, how end users can understand it..??
Again if power saving mode ( it is different than battery optimisation okay ) is made ON by user then, no way your battery optimisations is never considered.
What the ***** should i do then ...?
Nothing as developer.
Train your support / sales team to "LOCK" your app in the recents of every phone, after which, users are unable to swipe it away from the recents, even if it is swiped away, your all above strategies will work & your jobs / alarms / tasks will be executed, as it happens on your android emulator or as on stock android
Train your support / sales team how to make battery optimisations to "Do not optimise for this app" too..
It is so out of the box solution..??
Yes, it is. As in the market you will notice 1% stock android devices and 99% chinese modified ROMs
This all knowledge came to me after i lost last 9 to 10 years resolving the same problem, Hussshhhh
In my Android application the user has an option of using the application in offline mode. When the user opts to enter the offline mode, I download all the content from the server(which might take even upto 7 minutes) for offline usage. The usage of the application henceforth is dependent on the download of offline content.
I am using a service to download the offline content. But the service may not work in Android 8 if the app goes to the background. So what is the best approach to download the offline content for Android 8? Is it a foreground service or JobIntentService or a WorkManager?
Anything that is backed by JobScheduler — which includes JobIntentService and WorkManager — has a 10-minute limit. You indicate that your work may take up to 7 minutes, which makes me somewhat nervous.
In the short term, make your existing service be a foreground service, as that will keep your code working (other than any problems that Doze mode might impose).
If your 7-minute download work is really a series of smaller things that add up to 7 minutes, you might eventually migrate to WorkManager. Divide your work into smaller chunks and set up chained work with WorkManager, so you are certain to not go over the 10-minute limit for any of those chunks of work. Plus, WorkManager lets you establish constraints to say that your work should only be performed if you have an Internet connection. Right now (late August 2018), though, WorkManager is only 1.0.0-alpha07, so I would not ship a product based on WorkManager until it at least reaches a 1.0.0 final version.
The best approach would be to use WorkManager. As stated in the docs that:
WorkManager is intended for tasks that require a guarantee that the
system will run them even if the app exits, like uploading app data to
a server, or downloading data from server.
The benefits of using WorkManager over services includes handling of doze, standby, battery optimizations and constraint execution etc.
You can schedule a worker with WorkManager to download data for your app from server, and once data is available, you can go on with your offline mode.
We notice that AlarmManagerCompat alone, isn't a reliable way to implement alarm/ reminder feature in our app, due to different AlarmManager behaviour in different version of OS. (For instance, Doze mode)
Initially, we plan to use Evernote's android-job library, to help us implement alarm/ reminder feature in our app.
However, along the way, we also notice that Google just release WorkerManager.
So far, WorkerManager works well for us, when we run some one-time background jobs (Almost immediate, with internet connectivity constraint) after the app quit.
We have plan to use WorkerManager to implement alarm/ reminder feature.
I was wondering, how reliable is WorkerManager to implement such feature? Has anyone try it out? We are targeting API 15 and above.
WorkManager is not appropriate for anything that must fire at a specific time as jobs, including those used by WorkManager or android-job, will not fire while the device is dozing.
For exact timing, you should absolutely be using AlarmManagerCompat and specifically, setExactAndAllowWhileIdle() which fires an alarm at exactly the specified time on all API levels.
As your exact timed alarm can and will happen while the device is dozing, your app should not require network connectivity to post your alarm/reminder notification. Ideally, the information should be in the PendingIntent itself and not even need any database fetch/etc.