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 :)
Related
I'm developing a location aware app. This app will start tracking users when they are in their workday. These are the requirements:
The service should run on a regular basis (every 30 or 45 min).
It won't matter if the service does not trigger at the same basis everytime.
The service needs to upload data to our firestore db.
I doesn't need to be triggered on specific conditions (data is on, phone is charging, etc...)
I need this to run even if the user restarts his phone.
We may need to track the distance traveled by the user. (This is not a requirement per se, but it may be a feature someday)
I know there are a lot of ways to achieve this, but I have not decided which is the option that best fits my scenario. This is what I've thought so far:
Foreground service combined with BroadcastReciever in case the phone is rebooted
Background service using the new jetpack's Workmanager.
Which will the best solution? Do you think there is a better solution than those?
Thanks!
Was thinking create a GPS location tracker so when they are in work premise as well as outside it kinda shows.
Then consider adding the number 5 of the above. Like you said there could be mire awesome solutions than these so lets wait for options.
This question is vague but I am not sure what to Google for exactly.
But in my app I have a section where you create a list of tasks with various attributes, and a lot of these numbers are summed up and displayed in daily totals visually. But these daily totals should reset every 24 hours (based on the hour of the day the user chooses for the cutoff, e.g. 3 am if someone works late).
Right now: my database can hold all the data by day. Then my daily counters will visually display the numbers by pulling the corresponding data from the database looking for the current day. That's the easy part.
The hard part: I can refresh the counter after the time cutoff if the user rotates the screen or restarts the app because then it'll be looking for items in the database with a new day that won't be found, so everything will be 0 as intended. But what if the user is just staring at the screen as the time cutoff rolls by? How do I make the app refresh the counters once the time hits? What if they're not even using the app at all (either it's minimized in the background or not even active).
Do I need to have some kind of always-running loop in the background that checks the current time against the values in the database? If so, isn't this inefficient if it's always needing to pull values from a database based on time? What's the correct practice for something like this?
You can setup a service and schedule that service to run periodically so that it does whatever job you want it to do
maybe this article can help you.
Alarm manager and services will be ideal for you to implement to do something for your requirement.
Services : It will be running all the time irrespective of your life-cycle of activity.
Alarm manager: Inside services use alarm manager to trigger event to update UI at regular interval.
Finally you can use Local braodcast reciever to update your Activity from services.
You can check implemetation in details below :
Android update activity UI from service
The whole project consists in making an android application based on crowd sensing that collects data from volunteers (phase 1) and then based on the collected data, every user has a file in the server and the file would be separated into multiple online episodes and I will apply Artificial intelligence algorithms to make the data mining better.
For example, if in phase 1 I can determine that the volunteer is usually at home before 8am and he has no valuable information for me to analyse then the application wouldn't even send data to the server.
I'm still in phase 1, I'm trying to make an android application that starts running as soon as the user in connected to internet, it would send the data (battery, gps, activity...) to the server and based on the activity (walking, running...) it would determine when the next flow of data is sent. For exemple if he is walking then, the next time the data is sent to the server would be in 5 minutes.
While searching, I found many solutions on how to make an android application run in the background while keeping sensors collecting full time (high energy consumption) and the better solution would be to have a schedule for example every 5 minutes.
What I want to know is, is there an android studio solution to make the schedule dynamic? because it depends on the activity as I said before, so each time it collects information it schedules the next time the information is collected again (the next time we use sensors to collect the data then send it to the server).
I hope I made my point clear: what is always running in the background is an application that has a countdown to a specific moment; when that moment arrives the sensors are ON to collect data and send it to the server and that data is also used to make the next countdown (based on the activity data collected) and then the sensor are off until the countdown ends.
I would appreciate your suggestions.
Probably the best option for your project is AlarmManager. It can execute your code periodically or at a particular time, samples could be found here.
Also the app could be launched by system state event(like wi-fi on/off). To catch these events you need to use BroadcastReceiver, samples are here.
So you don't really need to implement countdown timers or background threads. Moreover manually created countdown background thread could be killed by the system at any time.
I am designing an Android application that needs to receive constantly changing information (so the update interval must be very small).
Right now I am reading this information by consuming a REST WebService, but I am wondering if this is the best approach, regarding the battery drainage. This application would have to refresh the data being shown very often (specifically GPS data read from another system).
I have been reading about Google Cloud Messaging but I didn't find any comparisons between the two approaches.. Theoretically both approaches fit my needs since the data changes so frequently that it doesn't really matter whether it is updated by request or on a timer..
So my question is: Should I stick with WebServices or shift to GCM? Is there another battery-efficient solution?
Thanks in advance!
GCM utilises a connection that is already there - using this over your current polling methods is definitely recommended and will be much friendlier with the battery.
Think about it, in your case GCM will send you a notification to let you know you need to refresh data so instead of just calling refresh you have: receive the notification, process it and then call refresh. So if you need to refresh so often, like just say each minute and it's constant just skip the notification.
I would set a recurring alarm, get the intent in a BroadcastReceiver and trigger an IntentService for the refresh
I have a background service that receives data roughly once per second from an external BT sensor. That data comes in, and gets sent to the UI using a broadcast intent/receiver. The live data is displayed in real time. This all works well right now.
What I need to do now and can't figure out: Have a button on the UI set up so that it starts a count of data coming in from the broadcast receiver (which is coming in roughly every second - but is not consistent enough to set a clock by), and stops after a given duration like 10 seconds. Every time new data comes in, it should be added to the total, and then after the duration of 10 seconds, the UI should be updated with the total, along with some message like "the total was 31".
This sounds easy, but using an async task - which seemed like the way to go - has been giving me trouble since I can't really set the task up to run a loop (afaik) since the looping timing needs to depend on the incoming broadcast receipt.
Any ideas on the best way to accomplish this if not via async task? I imagine the solution might be a simple one, but I'm not seeing it. Thanks for any help!
A Timer and TimerTask would help you with the timing issue and if you wanted to go all out you could implement the timer using ScheduledThreadPoolExecutor.