onLocationChanged is not called from IntentService - android

I have an AlarmManager that triggers every 30 minutes to an IntentService, and this intent service is to get the user's location each time. I have 2 ways of getting location: first it checks the getLastKnownLocation(), and if it was within the last 2 minutes it uses that, this part works perfectly.
The second way is if the last location was old or returns null, in which I want to get the new location once. For some reason this never calls onLocationChanged(). This results in my IntentService not returning coordinates much of the time, it only returns them if the getLastKnownLocation() was recent.
Here is my code for how it is set up, why is it that if I want to get a new location, it is never called? Check the comments in the code to see what is called and what is never called.
LocationListener locationListener;
LocationManager locationManager;
private final double MIN_COORD_DIFF = 0.0006;
public CoordinateAlarmReceiver(){
super("CoordinateAlarmReceiver");
}
#Override
protected void onHandleIntent(Intent intent) {
//THIS IS CALLED CORRECTLY
MyLog.i("coordinate alarm received");
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Location lastLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//if last location was in past 2 minutes, use that
if(lastLocation != null && lastLocation.getTime() > Calendar.getInstance().getTimeInMillis() - 2 * 60 * 1000) {
//THIS IS CALLED CORRECTLY
storeLocation(lastLocation);
MyLog.i("Last location was recent, using that");
}
else { //otherwise get new location
//THIS IS CALLED CORRECTLY
MyLog.i("Last location was old, getting new location");
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//THIS IS NEVER CALLED
MyLog.i("Got new coordinates");
storeLocation(location);
locationManager.removeUpdates(this);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}

You should use a Service instead of a IntentService. The IntentService finish when complete the task however, the service is running and can listen the location change events. Try to use a service.
Hope it helps you!!

Related

Android Location Services - LocationListener does not work

OLD QUESTION:
I'm trying to get my device's location coordinates and I've followed all the steps that I've found in multiple areas while researching. I've set up a LocationManager and used the requestLocationUpdates function that is tied to a LocationListener. However, the LocationListener does not respond. I've tried debugging as well as walking around outside in order for the onChangedLocation function to execute but nothing happens. In debugging the requestLocationUpdates function for my LocationManager is executed but the LocationListener is never executed.
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
textView = (TextView) findViewById(R.id.textView);
textView2 = (TextView) findViewById(R.id.textView2);
locationListener = new myLocationListener();
textView.setText("Longitude", TextView.BufferType.NORMAL);
textView2.setText("Latitude", TextView.BufferType.NORMAL);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, locationListener);
requestLocationUpdates
Above is the use of the requestLocationUpdates function.
private class myLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
//Log.e("Latitude: ", "" + location.getLatitude());
//Log.e("Longitude: ", "" + location.getLongitude());
if(location != null)
{
textView.setText(Double.toString(location.getLongitude()), TextView.BufferType.NORMAL);
textView2.setText(Double.toString(location.getLatitude()), TextView.BufferType.NORMAL);
}
else
{
textView.setText("No Location", TextView.BufferType.NORMAL);
textView2.setText("No Location", TextView.BufferType.NORMAL);
}
Toast.makeText(getApplicationContext(),"onLocationChanged Success",Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
}
myLocationListener
This is myLocationListener that implements LocationListener. I've added a little bit of extra code for testing purposes. The toast would never pop up so it appears as though this code is never executed. If anyone could help me out with this I would really appreciate it.
Thank you!
NEW QUESTION:
After continuing on developing in this page while waiting for a response I noticed that it takes about a minute for the location services to actually begin working. So, now my question is: how do I overcome the obstacle of a user having to wait to use the app? I've seen apps that use location based content and it does not take that long. I know that there is the getLastKnownLocation function but what if a user travels 50 miles before opening the app again? Any help on this would be appreciated. Thank you!
Each device which makes location request for gps, has to wait until gps hardware become warm. The wait time changes by device and where you stay. If you are inside a building, this time could take 1 minute or more.
To avoid wait, you can use getLastKnownLocation method, if returns a cached location, check location's date via getTime method. Determine yourself, is it old location by your scenario ?
if it's too old location, you have to make location request and wait.

Real time data update

My app uses google map to show user's location in real time. Therefore I would like it to be updated with every data change on my Parse server.
I've looked all over the net and as I see it I have 3 options:
using syncAdapter - the problem is that everywhere it is written that it does not meant for real time data transfer (I don't really understand why), on other hand it must be more efficient than updating every 5 sec.
using asyncTask - the problem is that it probably consumes a lot of battery and data usage to run it every 5 sec.
using service - same problem as asyncTask.
As i'm very confused, please help me understand what is the appropriate way to implement my real time map.
Thank's all
The best way i know is to use LocationListener to update the location only if it has been changed. You can use the onLocationChanged() method to update the location.
public class LocationHelper {
private LocationManager locationManager;
private Location currentLocation;
public LocationHelper(Context context) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
public void setLocation(Location location) {
currentLocation = location;
}
private final LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
setLocation(location);//Only update location if it has changed.
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
}
If the location hasn't been changed, you can just remember the last known location.

Android Application not working when notification from gps is received frequently

*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.

Android - Reliably getting the current location

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.

Getting an updated location in Android

I'm using the code shown below to get an updated value for location every time a button is clicked. When my activity is resumed I get an update every second, so that when I call getLastKnownLocation I expect to have a location that have been updated in the last second.
Is that the correct way to do that?
I would expect the onLocationChanged event to be triggered every time I execute a 'geo fix' command (or max after 1s since I request update every 1s), but it's only triggered the first time. Why?
Any help/suggestion welcome!
Thanks
package org.digitalfarm.atable;
...
public class Atable extends Activity {
private Button mSearchButton;
private TextView mytext;
private LocationManager locationManager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSearchButton = (Button)this.findViewById(R.id.button);
mytext = (TextView) findViewById(R.id.dude);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
mSearchButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String provider = locationManager.getBestProvider(criteria, true);
Location location = locationManager.getLastKnownLocation(provider);
}
});
}
//Start a location listener
LocationListener onLocationChange=new LocationListener() {
public void onLocationChanged(Location loc) {
//sets and displays the lat/long when a location is provided
String latlong = "Lat: " + loc.getLatitude() + " Long: " + loc.getLongitude();
mytext.setText(latlong);
}
public void onProviderDisabled(String provider) {
// required for interface, not used
}
public void onProviderEnabled(String provider) {
// required for interface, not used
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// required for interface, not used
}
};
//pauses listener while app is inactive
#Override
public void onPause() {
super.onPause();
locationManager.removeUpdates(onLocationChange);
}
//reactivates listener when app is resumed
#Override
public void onResume() {
super.onResume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,100.0f,onLocationChange);
}
}
The time, specified in requestLocationUpdates is the shortest possible time interval for which a maximum of one update will occur. So you have registered for at most one update every second, but the actual update may take more that that to occur, and, furthermore, no guarantee is given for that.
From the documentation:
minTime - the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
Try to set that time interval to 0 and if there are no other problems (although it all seems fine to me), you should start getting the updates "as frequently as possible".

Categories

Resources