I have a use case, in which I take input from the user of a time interval. For example, the user chooses 10 pm to 4 am. During this time interval, I want to basically track the screen time of the phone using Intent.Action_Screen_On and Intent.Action_Screen_OFF.
How do I approach this problem of taking time interval as input from the user and creating a work manager task which runs in the background during that interval?
This is not what WorkManager is used for. The idea of it is to be used for "persistent work". You give some criteria - constraints that need to be satisfied for the work to be executed and at the right time, based on your constraints(explicit) and the implicit one from the system(based on power management, doze, power buckets, etc) the work will start and some point, the system will ensure that it will finish successfully throughout device restarts, etc.
If you are actively tracking user interactions - you need to use a Service.
Please note that I am not familiar with how exactly Intent.Action_Screen_On and Intent.Action_Screen_OFF works, but I can assure you that WM is not your choice and there is no way for you to incorporate them.
Related
I'm having trouble deciding whether to run some recurring background work with Alarm Manager or Work Manager:
The work is going to consist of Room Database operations so I'll need access to Dao to complete my work.
It is going to be recurring at fixed intervals (hourly, daily, weekly, monthly, etc.)
I need to set a start date and time for the recurrence intervals.
the work will recur until canceled by the user
If the user is using the app when the work is supposed to be scheduled, I want the work to be done immediately. If the user is not on the app (app is in the background or device is turned off), I don't care if the work is done after the scheduled time as long as it is at least started by the next time the user opens the app.
the work needs to continue as scheduled after device reboots and app restarts.
For recurring background work, AlarmManger isn't suitable. As the name implies, it's intended to notify the system of an event at a precise time. Just like a physical alarm that wakes a person up even if the person sleeps, AlarmManager will wake up the device from doze mode which will result in more power usage. it is suitable for suitations like setting remainders such as for calender events which the users probably set by themselves.
On the other hand, WorkManager is intended to carry out background processing or work that would persist. Workmanager is much more efficient for recurring task especially as it allows you set constraints to determine when it should start or stop the background work.
check the link form the offical documentation on WorkManger:
workmanager architecture
tabular comparison between the two
It mostly depends on how important your task is.
https://developer.android.com/guide/background is a really good entry point to help you choose what you should work with.
WorkManager is the modern, universal approach of handling background work and it fits for most use-cases, it automatically reschedules work after a device restart or an application crash, and it is very efficient in terms of battery usage.
As WorkManager does respect Android's doze mode, it does not guarantee, that the work will be done exactly on time, though it does guarantee, that your work will be done within a certain time frame.
On the other hand, AlarmManager is capable of running work precisely on time. But this means that the device will wake up when your work scheduled with AlarmManager is coming due. This will drain battery and your app will probably show up as battery-draining in the Device Health board.
But as stated in the article above, prefer using WorkManager if possible. AlarmManager should only be used for e.g. a time-sensitive calendar notification.
I have an android/winphone application. Small part of app (background broadcastreceiver/task) from time to time (approx 10-15 minutes) checks local file with timestamps and if difference between one of timestamps and current time becomes more than - say - 30 minutes, it shows a notification to a user.
In Android I use AlarmManager.setRepeating(...) to setup periodic check, and to run this setup code I register a BroadcastReceiver on action "android.intent.action.BOOT_COMPLETED" in Manifest. Or call AlarmManager.cancel(...) and AlarmManager.setRepeating(...) on every launch. This way I may ber sure my timers work.
In Windows Universal I use triggers and background tasks. This works the same way with some limitations.
Now I'm porting my app to iOS, and quick look doesn't give me a way to register a function or class to perform quick checks (mostly less than a second) every 10 minutes while the app itself is not launched, and also I would like to register a function on device boot event. Is it possible?
Or should I keep my app running in background? I'd prefer not to do so, as my checks are lightweight and rare.
You can use background fetch for quick executions.
But there are several disadvantages:
Doesn't work in sleep mode.
You cannot catch device-launch event.
It will be dropped in 30 seconds.
I think in common case this is not analog for AlarmManager. Forget about it.
https://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Push notification can be used as a trigger. But, nevertheless, this is a server-side implementation.
In the guide above:
Check the box Background fetch in the Background Modes of your app’s Capabilities.
Use setMinimumBackgroundFetchInterval(_:) to set a time interval appropriate for your app.
Implement application(_:performFetchWithCompletionHandler:) in your app delegate to handle the background fetch.
Your callback event is performFetchWithCompletionHandler
I'm trying to make an app that does certain tasks according to a certain battery level (say a notification when battery level reaches 10%).
The problem is when i launch it the app just checks the event once instead of continuous monitoring.
e.g. (say i launched the app when battery was 11%. Since the notification is scheduled at 10% it wont give any notification. It just check the event a single time instead of continuously monitoring i.e. when battery drains to 10% while running the app,nothing happens)
What is the possible solution to make the code run continuously ?
Try using the Alarm Manager Class: developer.android.com/training/scheduling/alarms.html.
If you pass in your battery check as the pending intent, the trigger time which is when you first want to check (In your case probably the interval time after the current time) and then an interval time (Too often can slow things down a lot, so try to find a time that suits your application, e.g. every few minutes.)
This should then fire on each interval which you could use to trigger your battery check and further functionality.
I'm trying to develop an Android app that among other things, uses location services to get user location and sends it to a remote server. The user can turn this feature on and off according to his own will, but as long as it's turned on, it will get user location periodically (maybe each 30 seconds, don't know it for sure yet). Also, while it is turned on, it must keep tracking the user even if the application is closed.
So far I've considered 2 options:
Option 1 - Use Service, call startForeground to make sure Android don't kill it (the sticky notification is not an issue to me) and use a LocationListener with the said interval, but this seems rather inefficient as the service would be doing nothing most of the time, I mean, the listener would be called each 30 seconds, send the location to the server and the service itself would spend the next 29.9 seconds or whatever just waiting for the next location.
Option 2 - Doing some research, I've seen some approaches using AlarmManager to trigger some background service (like seen in this post), but I'm concerned that using alarms that often (every 30 seconds) might not be good for the battery and system general performance (in a code snippet in this page of Android's Developer guide there's a comment saying that "hopefully your alarm will have a frequency lower than 30 MINUTES").
Maybe there's another option that I still haven't thought about, or maybe there's a way to put the service from option 1 to sleep for some time or something like that. Bottom line, I'm looking for the approach that doesn't impacts on performance, consumes the minimum amount of battery and has the least chance of being killed by Android.
Any help and/or suggestions are welcome.
I have an App where the user can create multiple countdown alarms. Each one has it's own name, time to count, ringtone, etc.
I extended the CountDownTimer to hold each alarm setup and created a Singleton manager to manage all the alarms.
Everything is working fine until I leave the App.
The counters don't actually die. They have a weird behavior. After starting a counter:
1) if I press back key until the home screen and then power off the screen the alarm will trigger as it should.
2) if I press the home button then turn off the screen it will trigger only if I open the app.
3) if I just turn off the screen while still on the app it will trigger as soon as I turn on the screen.
I expected trouble because for that kind of thing I need to use Services, Handlers or other stuff like these.
The problem is, I'm new to Android and after reading a lot about it, I couldn't find a solution.
As far as I understood I should use Services, but it can have only one instance. How would I work with multiple alarms?
Is there other way of doing it?
I need a way to start each alarm and tell the system to keep counting no matter what happens! (and to call an Activity when it finishes)
Any help?
Is there other way of doing it?
If your goal is to alert the user of events in the future, regardless of whether your app is running, dump all your CountdownTimer logic, and switch to AlarmManager. It is specifically designed for this sort of scenario. You can set up an AlarmManager event for each timer, to get control when the end time is reached.
Also note that you will need to maintain information about your registered events in a file or database:
so users can add and remove them, and
so you can set up AlarmManager again if the user reboots their device
and to call an Activity when it finishes
Users may reject your app for that behavior. Not everyone wants to be interrupted in the middle of what they are doing with their device. Please allow this to be configurable, so the user can opt for something less intrusive, like a Notification.
You should replace your CountdownTimers with AlarmManager (as in CommonsWare's answer), after setting it up it will trigger your function to execute on specified time, here is official guide:
http://developer.android.com/training/scheduling/alarms.html
Soon you will find that after device reboot your alarms are lost, you need to restart them by catching android.intent.action.BOOT_COMPLETED broadcast.
Also you should not do a lot of work in your alarm onReceive, you should pass information to some other component like IntentService, to make it safe while device is asleep you should use WakeLock (sample project).
[edit] ---- you should also store your alarm/ringtone related data in some persistant storage, you can use for it shared preferences, or (more work) sqlite database.
I you really want to use timer (i.e. when you want to show countdowns on screen):
You don't have to have multiple timers to show multiple countdowns.
Everything you have to do is just put the target time into some collection, or event put it into the View.setTag().
Then you have timer (let say 1s tick) - on every single tick you have to iterate over all your gauges, check the target time and current time, parse the number and adjust the gauge.
However - as the timers works on separate (non main) threads - you will have to use handler or something like that.
If you want to just set some alarms - take the CommonsWare's answer - it's good one.