I need to find the user position with a timeout, then I wrote a code like this
Start a LocationListener
GPSLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
_timerGPSLocation.cancel();
}
#Override
public void onStatusChanged(String provider, int status, Bundle b) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDistance, _GPSLocationListener);
`
Setup a timer for the timeout
_timerGPSLocation = new Timer();
_timerGPSLocation.schedule( new TimerTask() {
#Override
public void run() {
_locationManager.removeUpdates(_GPSLocationListener);
}
}, (long)(timeout*1000) );
I think that doing this (trying to read coordinates and setup a timer with timeout) for many times can let the GPS contact some satellites and give me the right location.
There is a better way for doing this?
Calling _locationManager.removeUpdates on the timeout will remove all contacted satellites?
EDIT:
My goal is to read the GPS at regular intervals (5 minutes). I need also to set a timeout while try to get the location using GPS read. if no location is read after the timeout I need to stop the location listener. I've achieved this using the code liste here.
Now my question is if removing the LocationListener because it's go in timeout will cause the loss of the "acknowledgement" between the GPS and the satellite.
Scheduling a timer would work for what you're trying to do. Similarly you could use a handler and pass it a thread or a Looper object. As in
Handler h = new Handler();
h.postDelayed(Runnable r, long millis);
With that you could also post a runnable, i.e thread or looper at a time delay to cancel location updates.
EDIT: postDelayed is used for a runnable to run after a certain delay. postAtTime posts at a certain uptime of the program
Related
*Please have a look at the below written source code lines and suggest:-*
In the below mentioned code lines I am trying to request for GPS and Network location in every 60 seconds.
if (gps_enabled)
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, locationListenerGps);
}
if (network_enabled)
{
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 0,
locationListenerNetwork);
}
Below mentioned is the code for location change listeners:-
LocationListener locationListenerGps = new LocationListener()
{
public void onLocationChanged(Location location)
{
mCurrentGpsLocation = location;
String userCurrentGpsLocation = findUserAddress(mCurrentGpsLocation, mPreviousGpsLocation);
mPreviousGpsLocation = location;
for(int i = 0, size = mLocationUpdateListeners.size(); i<size; i++)
{
LocationUpdateListener listener = mLocationUpdateListeners.get(i);
listener.recieveGpsNotification(userCurrentGpsLocation);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
LocationListener locationListenerNetwork = new LocationListener()
{
public void onLocationChanged(Location location)
{
mCurrentNetworkLocation = location;
String userCurrentNetworkLocation =findUserAddress(mCurrentNetworkLocation, mPreviousNetworkLocation);
mPreviousNetworkLocation = location;
for(int i = 0, size = mLocationUpdateListeners.size(); i<size; i++)
{
LocationUpdateListener listener = mLocationUpdateListeners.get(i);
listener.recieveNetworkNotification(userCurrentNetworkLocation);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
And on receiving location change event for GPS and Network, I simply call my listeners recieveGpsNotification() and recieveNetworkNotification() methods respectively.
Logic of recieveGpsNotification() are as follows :-
public void recieveGpsNotification(String gpsLocation)
{
sendEmail();
}
**Problems :-
1) I expect call to sendMail() should come after every 60 sec but I am receiving notifications very frequently and after 4-5 notifications my application crashes. Please help if you see any error in implementation logic.
2) Will i also receive notifications for GPS even when my activity is in pause state or in stopped state, because i want to receive notification even when my activity is in background or it is stopped?
Additional Query :-
Whenever android framework provides us with GPS location updates, every time notification come through a different thread or is it the thread that request for notifications?
Thanks in Advance.
**
Try adding a min distance to each update. Also consider grouping the updates together for your sendEmail() method
Move your Location Listener logic into a Service that runs in the background. This will keep the updates coming. However, be aware that GPS updates are awful for battery life and users will not be happy to see GPS trying to get a lock all the time.
I believe those updates happen on the thread in which they are declared. So you should move your findUserAddress() method and other complex operations to a different thread.
Also, You should only use one method to get GPS updates. The normal use case is to try GPS Adapter, if not enabled or preset, fall through to use the Network listener. Since you have both you will be getting both updates on different intervals.
Details:
I have a service that needs to do the following:
- listen constantly for GPS locations, with 50 meters as parameter (works fine) and send it to a server
- each 60 seconds, if no GPS location was read, start listening for a Network location and send it to the server
This may sound weird, but this is the project requirement. So the user is constantly being tracked using GPS. When he stops, or GPS is not locked, or is inside a building, every 60 seconds start a quick Network location read, and send this location to the server. As the service uses the same thread as the main app, each server update is done in its own thread. And another important thing: each location read should be sent one after another, so for instance if the user is driving, and multiple reads are done, each should be send to the server, after the previous one has been sent. That's why I decided to use ScheduledExecutorService as I can submit threads and they will be execute one after another.
Here is the code:
private ScheduledExecutorService scheduleTaskExecutor;
Handler locationHandler = new Handler();
private Location lastNetworkLocation;
#Override
public void onStartCommand() {
scheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
//prepare to execute Network reading every 60 seconds
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
initNetworkReadings();
//usually a network location read is done almost instantly
//however after 5 seconds I check if a location has been read by the Network listener inside the locationRunnable
locationHandler.postDelayed(locationRunnable, 5000);
}
}
}, 60, 60, TimeUnit.SECONDS);
locationRunnable = new Runnable() {
#Override
public void run() {
if (lastNetworkLocation !=null){
//send location to the server if valid
}
lastNetworkLocation = null;
}
}
}
private void initNetworkReadings() {
locationManager.removeUpdates(locationListenerNetwork);
try {
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (isGpsEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
}
}
LocationListener locationListenerNetwork = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
lastNetworkLocation = location;
// stop listening for Network locations
locationManager.removeUpdates(locationListenerNetwork);
}
...
}
Each time I read a GPS location I add it to the threads queue as:
scheduleTaskExecutor.submit(new Runnable() {
#Override
public void run() {
updateLocationOnServer(readLocation);
}
});
The problem I have is that the Network location listener never gets onLocationChanged() called,when I use it like in the code above, in the Runnable. BUT if I add on service start, the initNetworkReadings(), I get onLocationChanged() fired right away. So I believe it has something to do with being used in scheduleAtFixedRate.
What do you think it could be the problem ? Anything bad in the way I thought of the workflow ?
What if you try to set up your repitition with a Handler and a Runnable instead of scheduleAtFixedRate()?
Handler h = new Handler();
Runnable run = new Runnable(){
//Do your repeititive work here!
h.postDelayed(run, 60 * 1000);
};
h.post(run);
Same problem,
I have a background service that detect locations.
If network is avaible, it uses networks, otherwise it uses gps.
It works well with many smartphones
( nexus s 4.1, galaxy nexus 4.2, galaxy note) , but with Galaxy s3 jb (4.1) network location never rises any location.
Same code with gps locations, works just fine.
i have to get my location inside service from another class by this code
Mylocation mylol = new Mylocation();
private void locationClick() {
mylol.getLocation(this, locationResult);
mylol.cancelTimer();
// runDialog(3);
}
public LocationResult locationResult = new LocationResult(){
;
#Override
public void gotLocation(final Location location){
//Got the location!
double MyFinalLat=location.getLatitude();
double MyFinalLon=location.getLongitude();
Myloc=MyFinalLat+","+MyFinalLon;
Toast.makeText(getBaseContext(),"Your current location"+Myloc,
Toast.LENGTH_SHORT).show();
};
};
}
but i should make the gpss take his time to find locattion
how can i make my service slaaps for 20 secons for exampl??
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
my_button.setBackgroundResource(R.drawable.defaultcard);
}
}, 2000);
The code:
Thread.sleep(20000);
Will make the current thread sleep for 20 seconds. From an Activity, this would probably cause a force close, because it effectively make your process seem like it's locked up (I assume). In a Service, as you describe, you may be alright though.
BTW the 20 seconds isn't incredibly precise, as noted in the docs.
I'm working on a HTC Legend and try to build my own gps logging app. Everything works as expected beside the fact, that I have a gap of 30 minutes in every track.
This gap where I do not get gps data is always around minutes 30 to 60 - so after 30 minutes of activity, I have no gps data for 30 minutes. And without doing anything (not even restarting the app), it starts collecting data again after this 30 minutes break.
Does anyone have an explanation for this? It's driving me crazy...
Forgot to mention that I collect data with the straight forward requestLocationUpdates stuff, but no issues here...
EDIT: Code sample as requested:
private LocationListener ll = new LocationListener(){
#Override
public void onLocationChanged(Location loc) {
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
And here's the corresponding NMEA listener because I will handle raw GPS data:
GpsStatus.NmeaListener nl = new GpsStatus.NmeaListener() {
#Override
public void onNmeaReceived(long timestamp, String nmea) {
/*
* Use patcher and matcher to find a proper GPRMC sentence and remove symbols at the end like \n, # etc.
*/
m = p.matcher(nmea);
Log.d(LocationLoggerApp.TAG, "Time for a break...");
//Notify activity that app is ready for upload
broadcastIntent.putExtra("LOG", "Got valid GPRMC sentence");
sendBroadcast(broadcastIntent);
}
};
And here we have the line from the onStart function where above stuff is "loaded":
/*
* Request location updates as workaround because the function addNmeaListner DOES NOT enable GPS on the phone!
*/
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval*1000, 0, ll);
lm.addNmeaListener(nl);
Regards,
Martin
Any chance of some code samples? My first suggestion is to check you've set your minTime and minDistance parameters correctly.
public void requestLocationUpdates (long minTime, float minDistance, Criteria criteria, PendingIntent intent)
My app checks at a specific time whether a user is at a given location. I use the alarm manager to start a service that makes this call:
locationManager.requestLocationUpdates(bestProvider, 0, 0, listener);
And also checks:
locationManager.getLastKnownLocation(bestProvider);
But I'm having problems when running on a real device. For one thing, getLastKnownLocation is most likely the last place the GPS was on, which could be anywhere (i.e., it could be miles from the user's current location). So I'll just wait for requestLocationUpdates callbacks, and if they aren't there within two minutes, remove the listener and give up, right?
Wrong, because if the user's location is already stable (i.e., they've used GPS recently and haven't moved) then my listener will never be called because the location doesn't change. But the GPS will run until my listener is removed, draining the battery...
What is the right way to get the current location without mistaking an old location for the current location? I don't mind waiting a few minutes.
EDIT: It's possible that I'm wrong about the listener not being called, it may just take a little longer than I thought... Hard to say. I'd appreciate a definitive answer still.
The code may be something like that:
public class MyLocation {
Timer timer1;
LocationManager lm;
public boolean getLocation(Context context)
{
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
lm.removeUpdates(this);
//use location as it is the latest value
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//use location as we have not received the new value from listener
}
}
}
We start the listener and wait for update for some time (20 seconds in my example). If we receive update during this time we use it. If we don't receive an update during this time we use getLastKnownLocation value and stop the listener.
You can see my complete code here What is the simplest and most robust way to get the user's current location on Android?
EDIT (by asker): This is most of the answer, but my final solution uses a Handler instead of a Timer.
If the user's location is already stable, then getLastKnownLocation will return the current location. I'd call getLastKnownLocation first, look at the timestamp (compare Location.getElapsedRealTimeNanos() with SystemClock.elapsedRealTimeNanos()) then register a listener if the fix is too old.