I need to perform the follow logic in my application:
Every minute, I want to be able to listen to GPS location for 20 seconds to get a GEO-location fix.
This obviously needs to run a different thread than the UI thread.
I am however having some problems with using looper and timertask in conjuction...
What's the best way to achieve this?
I guess you need to use a Service :
Android doc :
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.
So the Service start the LocationManager using requestLocationUpdates() and implements LocationListener.
Then you have (at least) two solutions (depending on what you want to do) :
dispatch the event to the Activity that need to use the Location ( with a Broadcast for example )
the Activity has an access to the service and uses a getter to get the latest location.
Related
I want to constantly, without stopping, perform 2-3 kinds of operations from my Service in Android. That is:
check if some hardware is connected and retrieve the data from it every 1 second and save it to the files
send those files a server
perform some calculations
The second job depends on the 1st one.
Note that the Service will have GUI as well if that matters, but the GUI will be used rarely. Most of them time the Service will work in "background" doing what it has to do.
How can I do that? Should there be 3 different threads or what? Or I don't need the thread because it'll be a service?
Any help is appreciated.
If you want to perform all operation in parallel in background then use android service and use ScheduledThreadPoolExecutor class to achieve this.
Otherwise use timer or Executor(with onr thread) inside android service to perform all operation in serial manner.
Let me know, This is helpful for you?
That depends on what type of service you are using, Intent Service or Service.
If you are using Intent Service, then you don't have to worry about creating a new thread, as it itself creates a worker thread.But, just keep in mind that, it takes one care of requests one at a time, in queue manner and stops itself when the processing is done.
But if you want to perform simultaneous request at once, extend from Service. You will have create a worker thread to run this service as it doesn't create a separate thread.
Check developer guide for more info:
https://developer.android.com/guide/components/services.html
To communicate between two services, you have to make use of Broadcast Receiver to receive intents which you can send from your first service or use listener callback, but i would suggest you to use Broadcast Receiver and intents.
I started learning android i've been playing with it and so far so good but i have some doubts about Services, i started learning them today so by gently if a say something very wrong.
For example, i want my app to grab some information over the internet from time to time, this polling period is defined by the user, then the UI gets updated. I though about creating a Service that run lets says every 30 minutes, gets the information and updates the UI.
If i get it right:
An IntentService just executes an operation and stops by itself sending the result through an intent(right?), so i think it's not what i want.
A Bounded Service is most likely used when you want IPC or allow binding from external apps, which again i think it's not what i want.
I think a Local Service is probably what i need, using a LocalBroadcastReceiver to update the UI, how can i make it to run the operation every X minutes( Handler postDelayed, ScheduledExecutorService or Alarm Manager ? )
If i understand it right a Service if not bounded can run infinitely if it's not killed due to low memory problems, making it a foreground Service is the safest ?
Last thing and it's kind of a noob doubt, if the user leaves the application(Click Home Button or opens other app) the app is still in background but the activities are in "Paused" or "Stopped" mode will the Service still be able to talk to them ?
Sorry for long post and thank you.
Your requirement : after every x minutes, start a service, pull some date, update UI.
Solution :
Define or set an alarm for every x minutes, to trigger a receiver.
From receiver start the service.
In the service, start an async task to fetch the data in doInBackGround().
Once data is fetched, from onPostExecute() send a broadcast to your activity.
In the activity have a dynamic receiver registered for broadcast sent from service.
From dynamic broadcast receiver update UI.
From what you've explained I wouldn't personally use a service.
The Android docs on services explain more but here is a snippet:
http://developer.android.com/guide/components/services.html
A Service is an application component that can perform long-running operations in the background and does not provide a user interface.
You could perhaps looks at using an AsyncTask, especially given that you only want it to run whilst the app is running:
http://developer.android.com/reference/android/os/AsyncTask.html
This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
There is a good answer here on how to run an AsyncTask repeatedly at specific time intervals: How to execute Async task repeatedly after fixed time intervals
this scenario is very common according to the Android documentation but still I don't find a straight solution neither there nor anywhere on the net.
So I have a service that should do something like this:
Register a LocationListener to receive the user location
Once the LocationListener is called - stop listening for a 5 minutes
After 5 minutes start listening again and loop from 1
This is the recommended way to save battery power while listening for the user location.
As a service I have a major problem with step 3.
The only way I found to "wait" for 5 minutes is to schedule a java.util.Timer to execute a TimerTask in 5 minutes and this TimerTask should register the LocationListneres again.
However this does not work because of:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Which is also expected because requestLocationUpdates should be called from a "main" thread.
Ok .. nice... but I don't have a Main thread. I don't have an activity. From the TimerTask I can't send an intent to the service to register my listeners back.
How can I ask my own service to register my listeners again?
This is the recommended way to save battery power while listening for the user location.
Really? The only way that's a good pattern is if you are using AlarmManager for the five-minute delay, so the device falls asleep in between location checks.
The only way I found to "wait" for 5 minutes is to schedule a java.util.Timer to execute a TimerTask in 5 minutes and this TimerTask should register the LocationListneres again.
And that would be a horrible use of battery, because it would mean you would need to keep the device powered on constantly, not allowing it to go to sleep.
I don't have a Main thread
Yes, you do. All processes have a main application thread. onCreate(), onStartCommand(), etc. of a service are called on the main application thread.
I don't have an activity.
Then you better write one, as your app will not work on Android 3.1+ without it. Your app will not run until a user launches one of your activities on Android 3.1+.
How can I ask my own service to register my listeners again?
What you are trying to accomplish is a rather complex problem. Not only do you need to arrange for the device to fall asleep and wake back up again, but you also need to deal with lots of edge cases (e.g., what if no location is available, because the device is in airplane mode or is underground or something?).
I wrote LocationPoller to handle your use case, and another developer forked it to create a more feature-rich implementation.
Whether you use one of these directly or simply examine their implementation, they should be useful to help you understand how to solve this problem. All of the details, though, are well beyond the scope of a StackOverflow answer -- it would take several pages in a book to explain it all.
You can specify the parameter in requeestLocationUpdates() to make it run after a certain time.
We needed a location service for our app that was available from anyplace.
We used s singletone with Application context for system services and more, and has two basic methods start and stop which listen to location providers and stop listening respectively.
We have getLastLocation method that retrieves the current most updated and accurate location we could find.
We have another method that gives me a headache :-)
Location getLocationWithWait(Class c) which supposed to get a location if available, if not it will return null and will create a Timer for 45 seconds.if the 45 seconds have passed and no location was found then the timer will broadcast to the class given in the parameter a 'no location' broadcast, otherwise if the location callbacks will be called they will cancel the timer and will send 'location found' broadcast to the class in the parameter.
So here are my questions:
i started to think the whole
architecture here is wrong, any
better way to implement a location
service to cater ANY Activity in my
application ?
i used a Timer an not Handler since
the singletone i use is NOT an
activity so i have no Looper an
creating a thread with looper looks
to me just as bad as creating
another Thread for the timer... i
did wanted to use the Activity
instead, but then... if the activity
pauses and resumes i need to keep
track of the timer's remaining time.
the broadcasts may also be of a
problem since if the activty pauses
it will miss the broadcast and then
i need to keep track in my
singletone after several states,
StickyBroadcast may solve it but
that one i can't send to specific
class but to the whole system only.
So finally will it be any advantage to make this class a Service ?(to be honest i thought of maybe one advantage but not much) i want a location service with timeout much like google do in their "My Location" in maps.
10x.
Wouldn't it be better to use a LocationListener, as described in Requesting Location Updates?
You can then use a 'FastFix' in onResume()
Without knowing a bit more about your requirements, it's difficult to make more specific suggestions.
Hope this helps,
Phil Lello
I've declared a background service from the android manifest, this service is to be started from within the main Activity of the application and run in an infinite loop to perform location updates to an external server.
This background service runs in a separate process than the process of the main activity of the application (using the android:process tag in the manifest declaration of the service). The issue I am having is that when requesting GPS location updates from within the service, then the LocationListener's onLocationChanged() method is never called, even when I send mock location using DDMS/geo command. But on the other hand, requesting GPS location updates from the main activity of the application does work and the onLocationChanged() method is being called properly when a fix is received, so I am wondering what is needed to be modified in order to get the same behaviour from within a service rather than an activity.
Thanks in advance for your help;
Hass.
this service is to be started from within the main Activity of the application and run in an infinite loop to perform location updates to an external server.
Please don't do that, as you waste memory. Please use AlarmManager to trigger a self-stopping Service (like an IntentService) periodically. And, since you appear to be getting locations, consider using my LocationPoller service.
This background service runs in a separate process than the process of the main activity of the application (using the android:process tag in the manifest declaration of the service).
Please don't do that. You waste memory and add no value. It may also be contributing to your problems.
so I am wondering what is needed to be modified in order to get the same behaviour from within a service rather than an activity.
Getting locations within a service works just fine. See the LocationPoller for an example of this in use.