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.
Related
I am devolping an Android App that need to execute an accumulation of internet tasks periodically (like a web bot). Those tasks need to get stored at a specific time so I thought about using Alarm Manager and a
embeded Database. Due to it, the app could be active much more time, although those save tasks do not need web connection. Later I will throw another Alarm Manager to execute all the tasks queued and do web stuff.
Otherwise I am not sure if it is better to use a foreground service. The app will be working all the day saving the tasks (each 5 or 15 min) but only running task queue with internet each 30mins.
I feel capable of developing both systems but I would like to know which one is better in terms of performance, of battery consumption.
Thank you very much.
Only a recommendation try to find and use a nice library to do it, every Android Update change something about foreground/background servicess.
one is
TimedDog
and for more
enter link description here
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 :)
I am building an app that shows user's friends' real-time locations on a map.
Each user updates his currnet location on the server (Parse.com) every defined interval (time and distance).
When a user opens the FindFriends activity, he'll get a map with markers on friends locations.
The friends locations data can be retrieved in two methods:
When activity is running, I am calling an AsyncTask that will download locations data from the server in a while loop (inside doInBackground), and after each time I call publishProgress() to handle the changes on the map.
I wrote a cloud code that is called every time a user updates his location on the server, which sends push notification to the relevant users (the user cant see the notification). When the FindFriends activity is running, a broadcast reciever is getting those pushes and update locations data on the map.
My question is: Which method is better for my needs or maybe I should do it differently? Of course I would like to keep battery consumption to minimum but not at expense of getting almost real time data.
I don't really think that this is an appropriate question, since you really should just make a prototype using each implementation, and see which is more performant in your particular use case. However, I can say that I definitely prefer the cloud solution. I've used GCM to implement a messaging client, and from my testing the updates are definitely really quick (very little noticeable lag time, when testing two clients side by side). So, I don't think that implementing it with GCM would negatively impact your user experience, and it does have the plus side of eliminating pointless server polling when, potentially, no updates could be present - which saves on battery.
If you want real time data then push notification GCM is not a good idea because, there is no guarantee that all users will get push notification in time. Sometime you will encounter delays in push notification.
Under given circumstances AsyncTask or Service can be a good way to perform required task, if they are handled properly. You should have control on AsyncTask/Service so that you can stop it any time you want.
We have an android(or iphone) client we are developing. The client allows the android user to send entries to a server which we also develop. If the client does not have data services (GPRS) at the moment the user sends the entry to the server, the client also supports saving the entry to an offline database and sending it later to the server.
One important aspect of the whole process is accuracy of the timestamps on which the user sent the entry to the server (whether the entry is made in real time or sent by the client from the offline database)
When available on the client, we get a GPS location and are able to use the GPS timestamp to send that to the server (or save the GPS timestamp on the offline DB and send it later to the server). However if the user has turned off the GPS (and all other location services), the device will not have a GPS fix and therefore the server can not determine accurately when an entry was made.
We can not use the local device clock as the user may change the clock to make entries on different times than they actually occurred (these entries are part of the users salary so he might have an interest to "fix" them).
So basically I am searching for a way to determine as best I can the time some entry was made when I can not trust the internal clock of the mobile. The algorithm should support both entries sent in real time or entries sent from an offline DB. the algorithm should also support cases where the user changes the time of the mobile, turns the mobile on/off, turns the GPS on/off while the application is running on the mobile etc...
Few ideas that I thought of:
Although I can not trust the mobile's time, it can still perform as a stop watch:
Have a class that will loop until the application exists, the loop will sleep 1 second and increase an internal clock variable by 1 second. On every GPS location my code gets we update the internal clock variable. This way I have an absolute clock that came from outside the device (from the GPS) and when the client sends an entry to the server, we can use the internal clock as an absolute time.
PROS: the user can not modify this clock as it is only updated when we get a location from the GPS
CONS: the application needs at least one GPS fix before the user can make any reliable entries
I can take advantage of the fact that the server has an accurate clock which is correct. If the client would send to the server info that the age of the entry is 10 minutes, the server could use its internal time and know the exact time the entry was made on.
The biggest problem is how to know the entry age? I thought about saving the entries to the offline DB with an age of 0, then every 1 second increase the age of the entry in the DB. The problem is that if the app is closed and/or the device is off this will now happen
This is where I am currently stuck. Any ideas on how to solve this are more than welcome
Thanks
Here's how I handle this issue for iPhone. When the app starts, I call my server and ask for the current GMT time (you could also call a public NTP server if you preferred). I then compare it to the system time. If it is different by more than X then I popup a message saying, sorry your system time is wrong so you can't use the app until you fix this. I then monitor for the user changing the system time while the app is running and if they do that, then I do the compare again (and popup the error message if the time is off by more than X). This ensures that their system time is always correct (within some reasonable allowance) and you can trust [NSDate date]. However, this solution does require a valid network connection. If this solution works for you, I can post the sample code.
i think i am going to combine Jules and Joel's answers into one solution which will provide for my needs the best solution:
since the user might change the clock when the mobile doed not have GPRS, just detecting the time change event will not help us as we can not validate at that moment the new time is correct.
As Joel recommended i will pull the time from my server when my application is started (at that point i still must have communications with the server or else my application will not start). The time pulled from the server along with the current device upTime will be saved.
when the user wants to make an entry i will calculate the current time using (Server Base Time + Current UpTime - Base UpTime). this way i will have an independent source of time regardless of the current clock of the device
this will defenitly work on android
on iPhone we will try to use something out of http://www.cocoadev.com/index.pl?FindingUptime to get the upTime
Jules & Joel, thanks for your answers!
Look into android.os.SystemClock. Specifically, elapsedRealtime() returns a time since the phone was switched on, which is not affected if the clock is changed by the user.
You can correlate times in event the phone is switched off by having code that runs when it is switched on and checks the realtime clock. As the clock can't be changed when the phone is off, I suspect you could use this to put together a system that will catch any simple attempts at cheating. (If the user roots the phone all bets are off -- they could modify the behaviour of the APIs from under you).
Running code every second will kill the phone's battery life. Most phones would be unlikely to last a day if you did this.
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.