I'm trying to have a background gps location listener as a service that can be used by all activities in my app. It should also be scanning for locations until I "kill" it. However I realized that after a couple of hours the gps service gets killed and I can't get anymore locations.
How do I keep this service alive (the locationManager and location listener at least) until I want it off?
Thanks
public class GPS extends IntentService {
public static LocationListener loc_listener = null;
public static LocationManager locationManager = null;
public GPS() {
super("GPS");
}
#Override
protected void onHandleIntent(Intent intent) {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (loc_listener == null) {
loc_listener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
};
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, loc_listener);
}
public static void killGPS() {
if (locationManager != null && loc_listener != null) {
locationManager.removeUpdates(loc_listener);
}
}
}
However I realized that after a couple of hours the gps service gets killed and I can't get anymore locations.
First, it is an exceptionally bad idea to keep GPS powered on all of the time, as the user's battery life will suffer greatly. Your application needs to offer tremendous value (e.g., Google Navigation) to warrant this power cost.
Second, never register a listener from an IntentService. Once onHandleIntent() ends, the service shuts down... but you leak your registered listener. This effectively keeps a background thread going. However, since you have no active components, Android eventually will terminate your process.
Related
I'm trying to have a background gps location listener as a service that can be used by all activities in my app. It should also be scanning for locations until I "kill" it. However I realized that after a couple of hours the gps service gets killed and I can't get anymore locations.
How do I keep this service alive (the locationManager and location listener at least) until I want it off?
Thanks
public class GPS extends IntentService {
public static LocationListener loc_listener = null;
public static LocationManager locationManager = null;
public GPS() {
super("GPS");
}
#Override
protected void onHandleIntent(Intent intent) {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (loc_listener == null) {
loc_listener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
};
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, loc_listener);
}
public static void killGPS() {
if (locationManager != null && loc_listener != null) {
locationManager.removeUpdates(loc_listener);
}
}
}
However I realized that after a couple of hours the gps service gets killed and I can't get anymore locations.
First, it is an exceptionally bad idea to keep GPS powered on all of the time, as the user's battery life will suffer greatly. Your application needs to offer tremendous value (e.g., Google Navigation) to warrant this power cost.
Second, never register a listener from an IntentService. Once onHandleIntent() ends, the service shuts down... but you leak your registered listener. This effectively keeps a background thread going. However, since you have no active components, Android eventually will terminate your process.
I am using the routine requestSingleUpdate() reoutine of the android LocationManager library with a LocationListener. The functionality I am trying to implement is that the user can press a button and the app will get their current location and perform reverse geocoding to get the approximate address.
My problem is that depending on the network situation of the device, getting a location fix may take a long time. How can I implement a timeout that will cause my 'requestSingleUpdate()' to give up and tell the user to find out their own bloody address?
my code:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
locationManager.requestSingleUpdate(criteria, new LocationListener(){
#Override
public void onLocationChanged(Location location) {
// reverse geo-code location
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}, null);
LocationManager doesn't seem to have a timeout mechanism. But LocationManager does have a method named removeUpdates(LocationListener listener) which you can use to cancel any callbacks on the specified LocationListener.
So, you could implement your own timeout with something like the following pseudo-code:
final LocationManager locationManager
= (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// ...
final LocationListener myListener = new LocationListener() {
//... your LocationListener's methods, as above
}
Looper myLooper = Looper.myLooper();
locationManager.requestSingleUpdate(criteria, myListener, myLooper);
final Handler myHandler = new Handler(myLooper);
myHandler.postDelayed(new Runnable() {
public void run() {
locationManager.removeUpdates(myListener);
}
}, MY_TIMEOUT_IN_MS);
I'm not certain what happens if you call locationManager.removeUpdates(myListener) after you get the Location. You might want to check for that before you call removeUpdates. Or, you could add something like this to the onLocationChanged method in your callback (and possibly to the other methods as well) :
myHandler.removeCallbacks(myRunnable); // where myRunnable == the above Runnable
I've an app that gets the user's location. I've registered the locationManager and listener in oncreate(). I've requested and removed updates in onResume() and onPause() respectively. The app finds the location and calls the getTime() on the loc object of onLocationChanged, this is to get an external time and then later compare to system time. This time is set in an applicationObject so that it's available app-wide. Everything works fine and i toast the time to the user from the applicationObject time setter method.
What i'm finding is that when i have found the time by getting a fix on the user's location, and i move to the next activity, the app continues to get the time for another 20 secs and sometimes more.
How can this be when i have unregistered the locaction listener in the first activity's onPause() method?
#Override
protected void onPause() {
mlocManager.removeUpdates(mlocListener);
super.onPause();
}
#Override
protected void onResume() {
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
super.onResume();
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
Log.e(TAG, "external time = " + loc.getTime());
DateTime dt = new DateTime(loc.getTime());
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "formatted ext time = " + formattedNowTime3);
nfcscannerapplication.setExternalTime(dt);
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}//end of MyLocationListener
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.entryscreen);
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
.
The onPause() may be called only after the new activity has started.
If you only want a single onLocationChange(), you can use requestSingleUpdate() and your problem is gone.
Regards.
Set mlocListener to null just after removeUpdates();
I'm trying to have GPS coordinates sent to a text message. This code works, but every time the GPS updates location, it tries to send a new text message. I can't figure out how to stop the location updates. This is what I have currently...I realize it may not be the most efficient way to do it.
Any help would be appreciated!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}
public void GPSDisable() {
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.removeUpdates(mlocListener);
}
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
double latitude = loc.getLatitude();
double longitude = loc.getLongitude();
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", "5555555555");
smsIntent.putExtra("sms_body", "Location:"+latitude+","+longitude);
GPSDisable();
startActivity(smsIntent);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
I would set two global variables latitude and longitude.
This variables would be updated every onLocationChanged. You cannot change this comportament, but you can get out from there the sending of sms.
I would send the sms on a timer after 5 seconds let's say.
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", "5555555555");
smsIntent.putExtra("sms_body", "Location:"+latitude+","+longitude);
startActivity(smsIntent);
}
},
5000 );
And your onlocation changed could look like this
#Override
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
latitude = loc.getLatitude();
longitude = loc.getLongitude();
}
First I would advise you to have a look at this article.
Having said this, generally you should "unsubscribe" from the location manager when you do not need any more updates. Typically, you subscribe for location updates in "onCreate" and unsubscribe in "onDestroy" when you need updates for as long as your Activity is 'alive'.
Even better is to subscribe/unsubscribe when your activity is getting visible or hidden respectively (via "onResume"/"onPause" respectively). Have a look here for details on the Activity's lifecycle.
Now, about your specific problem, it is not clear what is your desired behavior. Do you want to send an SMS message every time the location changes? Or only when some time passes?
Assuming what you need is to send SMS whenever your location changes but not too often, I would suggest the following:
1. Register for location updates in "onResume" and unregister in "onPause".
2. Maintain some local variables that tell you which was the last time you sent an SMS message and what were the coordinates in it. These variables should probably persist Activity lifecycle events (e.g. when the Activity is destroyed, you should "store" these values, and restore them when you recreate it).
3. Whenever there is a new location update, check if it is too soon or too close (compared to the previous SMS) and if not send another message, updating the variables.
Having said these, please note that this will work for as long as your Activity is visible. If you need a similar functionality that does not require you to keep the Activity visible, I would suggest you use a BroadcastReceiver.
i'm new in java/android app and i'm creating an app that uses user-location. I want the location to be updated at the begining of the app.
The problem is that my location class is an activity and i don't want to show another contentview for this class.
Actually, i want the location thing to be done in background, without changing the UI, in a separated class.
Is it possible? How?
Thanks :P
There is no need to put the location in a different activity, the LocationManager already does it in the background:
public void getLocation(){
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
gpsLocationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
//do something with the new location
if (location != null)
gpsLocation = location;
}
};
gpsLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 0, gpsLocationListener);
}
Using the LocationManager you should be able to use what ever kind of activity (or service) you want.