7
\$\begingroup\$

I have this background service, which runs continuously even when the application closed (Paused or Stopped).

The service is to retrieve the user location and post it to server.

public class LocationUpdaterService extends Service
{
 public static final int TWO_MINUTES = 120000; // 120 seconds
 public static Boolean isRunning = false;
 public LocationManager mLocationManager;
 public LocationUpdaterListener mLocationListener;
 public Location previousBestLocation = null;
 @Nullable
 @Override
 public IBinder onBind(Intent intent) {
 return null;
 }
 @Override
 public void onCreate() {
 mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
 mLocationListener = new LocationUpdaterListener();
 super.onCreate();
 }
 Handler mHandler = new Handler();
 Runnable mHandlerTask = new Runnable(){
 @Override
 public void run() {
 if (!isRunning) {
 startListening();
 }
 mHandler.postDelayed(mHandlerTask, TWO_MINUTES);
 }
 };
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 mHandlerTask.run();
 return START_STICKY;
 }
 @Override
 public void onDestroy() {
 stopListening();
 mHandler.removeCallbacks(mHandlerTask);
 super.onDestroy();
 }
 private void startListening() {
 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
 || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
 if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER))
 mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListener);
 if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER))
 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
 }
 isRunning = true;
 }
 private void stopListening() {
 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
 || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
 mLocationManager.removeUpdates(mLocationListener);
 }
 isRunning = false;
 }
 public class LocationUpdaterListener implements LocationListener
 {
 @Override
 public void onLocationChanged(Location location) {
 if (isBetterLocation(location, previousBestLocation)) {
 previousBestLocation = location;
 try {
 // Script to post location data to server..
 }
 catch (Exception e) {
 e.printStackTrace();
 }
 finally {
 stopListening();
 }
 }
 }
 @Override
 public void onProviderDisabled(String provider) {
 stopListening();
 }
 @Override
 public void onProviderEnabled(String provider) { }
 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) { }
 }
 protected boolean isBetterLocation(Location location, Location currentBestLocation) {
 if (currentBestLocation == null) {
 // A new location is always better than no location
 return true;
 }
 // Check whether the new location fix is newer or older
 long timeDelta = location.getTime() - currentBestLocation.getTime();
 boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
 boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
 boolean isNewer = timeDelta > 0;
 // If it's been more than two minutes since the current location, use the new location
 // because the user has likely moved
 if (isSignificantlyNewer) {
 return true;
 // If the new location is more than two minutes older, it must be worse
 } else if (isSignificantlyOlder) {
 return false;
 }
 // Check whether the new location fix is more or less accurate
 int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
 boolean isLessAccurate = accuracyDelta > 0;
 boolean isMoreAccurate = accuracyDelta < 0;
 boolean isSignificantlyLessAccurate = accuracyDelta > 200;
 // Check if the old and new location are from the same provider
 boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
 // Determine location quality using a combination of timeliness and accuracy
 if (isMoreAccurate) {
 return true;
 } else if (isNewer && !isLessAccurate) {
 return true;
 } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
 return true;
 }
 return false;
 }
 /** Checks whether two providers are the same */
 private boolean isSameProvider(String provider1, String provider2) {
 if (provider1 == null) {
 return provider2 == null;
 }
 return provider1.equals(provider2);
 }
}

So, I figured to use a Handler to listen to LocationListener once every 2 minutes because I am assuming this is saving more battery usage.

But, I don't know if there's still any way I can improve my code so that:

  1. It's saving much battery power
  2. Memory friendly
  3. The code is easier to read and maintain
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 26, 2016 at 12:17
\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

To save power you can use/implement a function to detect when the user is stationary. You can for example define a user in stationary state when the location has not changed in more than 2 minutes (set this parameter so it does not fire too often, as when the user stops at a red light). When stationary states are detected, stop listen for location updates from the GPS and start listen for SIGNIFICANT_MOTION_SENSOR to detect active states. Be aware that not all models have this software sensor so you have to support situations when this is the case.

Stephen Rauch
4,31412 gold badges24 silver badges36 bronze badges
answered Mar 24, 2018 at 16:31
\$\endgroup\$
2
\$\begingroup\$

One good approach is to request location updates in batch like this. so you will be less frequently requesting for location updates:

LocationRequest request = new LocationRequest();
request.setInterval(10 * 60 * 1000);
request.setMaxWaitTime(60 * 60 * 1000);

In this case, location is computed roughly every ten minutes, and approximately six location data points are delivered in a batch approximately every hour. While you still get location updates every ten minutes or so, you conserve battery because your device is woken up only every hour or so. reference

Toby Speight
87.9k14 gold badges104 silver badges325 bronze badges
answered Nov 27, 2018 at 13:49
\$\endgroup\$
-3
\$\begingroup\$

What about location listener running in the background is'nt like two services running in the background .And you have minimum time update interval 0 .that will consume lot of battery

answered Sep 28, 2016 at 8:15
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.