I need execute an action on a specific date
Handler(Looper.getMainLooper()).postAtTime({
texto.text = "Testo ha cambiado"
},2020-02-12)
postAtTime takes a milliseconds value. You'll need to use some date library (like Date) to create an object representing the date you want. Then use its "convert to milliseconds / Unix time" method (for Date it's getTime()) to get a value you can pass to postAtTime
But if you post a message to the Handler, your app will need to stay running the whole time until the time your message is handled. If the app is closed (including by the system) that message is gone. And your app needs to be running in the foreground when it happens too. It's not meant for scheduling important events that have to happen even if the app is closed, and it's really not meant for things way off in the future
You probably want to use AlarmManager
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
(there's also WorkManager which isn't about a specific time but might be better for whatever you're doing)
Related
I am trying to introduce auto-save functionality on one of my Android applications. The idea is that as the user inputs first name, last name and after a fixed interval I would like to save that information to the server before the user hits Next button. The final goal is to have something similar to the draft option in the Gmail app where your email information is automatically saved. So, if there is a timer that runs every 10 seconds, I will pass the information on the screen to the ViewModel and let it deal with the logic of saving the data to the server.
A couple of options I have explored are.
Execute recurring code with a specified interval using Handler.
PeriodicWorkRequest -- however this option has a minimum interval of 15 minutes which is a little too much for my use case.
AlarmManager -- This option runs even if your application is not currently running, In my opinion, this option can be an overkill.
I wanted to know if there are best practices/blogs around this and if anyone I on the wrong path or potential red flags with this approach.
you can make countdown for 10 second, when countdown is down save the data and call the countdown again.
when your activity is destroyed, so stop the countdown
My app needs to perform myAction() 12 or 24 hours after the user clicks a button.
I understand I can't use handler.postDelayed(Runnable, long) for this because the long argument is based on uptime rather than actual time.
So I think I am just left with TimerTask/Timer or AlarmManager, but I'm not sure which of these would be most appropriate - plus, I hear a lot of bad comments about TimerTask/Timer, saying that it's unreliable, etc.
Also, I have the requirement where if the device is restarted, then I still need myAction() to be performed at the same time it would have been (or as soon after as possible) as if the device had never been turned off. For this requirement, maybe I need to store details of myAction() in the database and then use a BootReceiver to recall it for execution when the device restarts, but it would nice if there was a class that could take care of this, too.
So what would be an appropriate and reliable way of calling myAction() in 12/24 hours time, whilst accommodating device restarts?
Use GCM Network Manager or Firebase Job Dispatcher.
These are the 2 best practice approaches to doing periodic work on Android.
https://developers.google.com/cloud-messaging/network-manager#run_tasks
https://github.com/firebase/firebase-jobdispatcher-android
(Note, although the name implies that they are related to push messaging, they are not. Both are solutions for running periodic work locally on a device.)
Regarding the problematic stated below I have come to a point where I need to make a decision on whether to:
Start a Service once that has an AlarmManager inside which then starts the query every 10 minutes. This Service will only be stopped if the user sets an "Onn-Off" Switch to "Off".
Use an AlarmManager to start an IntentService every 10 Minutes. This Service will then only be started when needed and closed afterwards
Which of these ways is better when it comes to:
- Ability to exchange data received by the Service (Or Intenservice) with other activities/services
- Battery usage
- Overall "good coding habits" ?
Thanks!
Original Question:
I am a pretty new Android Developer and have come across a situation that I do not know how to solve. I have already spent several days searching for a solution but could not find one.
While trying to develop my first app idea I have started playing around with receiving and parsing data from the internet. What I have achieved so far is generating a query that receives JSON data via an API and parses this JSON. All of which is done inside an AsyncTask. The received data is then shown on the screen.
However, for the purpose of my app idea, I need this to be done in the background. What I have thought of is:
Starting a Service that pretty much has the same logic as my Asynctask. Managed by an AlarmManager, this service then requests, receives and parses the data in a specific time interval.
Now the tricky part begins:
The data that I receive (let's say every 10 minutes) shall be used to change an alarm clock. So, as a simple example, let's say the user can set his alarm clock to 08:00 in the morning. The application then checks the current temperature every 10 minutes and changes the alarm clock time to 07:45 if the temperature is below 0° celcius because the user has to wake up earlier to clear the ice off his car.
Also, when "waking up" the application, the current (or rather the latest received) tempereture shall be shown in the UI.
What would be the best way to achieve this? I am having some issues regarding passing/receiving data from AsyncTasks/Services to/from Activities.
My first approach would be to start a single service from the MainActivity, passing some data to the Service (like the initial time the alarm shall start and the current location of the user). The Service then has two seperate AlarmManagers. One of which is set to perform the actual alarm (waking up the user in the morning) and the other manages the time interval of getting the data from the internet.
My questions:
- Does my train of thought make any sense at all so far?
- What is the best way to pass and receive data to/from a service? My best guess would be to use intents to pass and a broadcastreceiver to receive data from the service. would this make sense in this specific situation?
I fear that it is not welcomed to post questions without putting in any effort of your own before. Although I did not add any actual source code, I hope you can see that I have dealt with these questions for quite a while now but could not really start coding before I know the structure of the application.
Thanks in advance
Use AlarmManager to start an IntentService as often as necessary (in your example, it should be sufficient to start checking the temperature about two hours before the user plans to get up and maybe again after one hour and finally half an hour before the normal wakeup time. More often only in case of extreme weather conditions.
It's not necessary to check the temperature exactly at 03:33 a.m. so use
setInexactRepeating(), this will be easier on the battery.
See also Scheduling Repeating Alarms
Write the results to SharedPreferences and have one IntentService check 15 minutes before normal wakeup time if the user should get up right then. Cancel the normal wakeup alarm in this case. Communicating via SharedPreferences (think of a mailbox) and local (!) Broadcasts is a good idea - cheap and secure :)
my problem is that I want to run a service that compares the current time of the device. And a "x" hour make some things.
But I don't have idea how can I make that.
Thank you a lot
Schedule a repeating alarm using AlarmManager (see this training lesson).
Then in the BroadcastReceiver, compare the current time with the list of times when you want to do some things if matches do it.
You can start a thread in your service which checks the time at particular intevrvals. These intervals can be defined by you by putting this statement:
Thread.sleep(time_in_milliseconds);
in your Thread's "run" method.
You can then use the SimpleDateFormat class to get the current time and compare hours with desired value. Once it is equal to the desired value, you can perform whatever task you wanted to do. Consider going through the SimpleDateFormat oracle docs for more detail and learning about Threads in case you don't know anything about them.
My application is time dependent and I don't want change in device date and time affect my application, like if user deliberately set device date to any previous date . Is there any way to get current date and time when user is connected to mobile network or WiFi I don't want to use GPS.
Javadoc of the SystemClock class describe different ways of counting elapsed time for various scenarios and conditions.
In your case you have to use
long time = SystemClock.elapsedRealtime();
Return the time since the system was booted, and include deep sleep.
This clock is guaranteed to be monotonic, and continues to tick even
when the CPU is in power saving modes, so is the recommend basis for
general purpose interval timing.
Call it for the first time when you want to start tracking the use of Network (I assume you already know how to do it) and store that value.
When you receive event about user not using network anymore, call the same method again and calculate spent time.
long elapsed = time - SystemClock.elapsedRealtime();
Next you can transform milliseconds to String for example like this:
String formattedElapsedTime = DateUtils.formatElapsedTime(elapsed/1000);//note that this method takes second as arguments so we have to divide it by 1000
You should call webservice and get current date and time of server. Then server would be responsible for the actual date/time. Best way is to build your own webservice, because it gives you more control than using third party.