diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/workers/LocationHelper.java b/app/src/main/java/com/aldo/apps/familyhelpers/workers/LocationHelper.java index 243cb6a..5383929 100644 --- a/app/src/main/java/com/aldo/apps/familyhelpers/workers/LocationHelper.java +++ b/app/src/main/java/com/aldo/apps/familyhelpers/workers/LocationHelper.java @@ -6,8 +6,6 @@ import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SHARE_LOCATION_C import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SHARE_LOCATION_CHANNEL_ID; import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SHARE_LOCATION_NOTIFICATION_ID; import static com.google.android.gms.location.Granularity.GRANULARITY_FINE; -import static com.google.android.gms.location.Priority.PRIORITY_BALANCED_POWER_ACCURACY; -import static com.google.android.gms.location.Priority.PRIORITY_HIGH_ACCURACY; import android.app.Activity; import android.app.Notification; @@ -16,8 +14,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; import android.os.Looper; import android.util.Log; import android.widget.Toast; @@ -37,7 +33,6 @@ import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; -import java.lang.ref.WeakReference; import java.util.List; import io.reactivex.rxjava3.subjects.BehaviorSubject; @@ -118,6 +113,11 @@ public final class LocationHelper { */ private boolean mIsSubscribed; + /** + * The current granularity used. + */ + private int mCurrentPriority = -1; + /** * Private C'Tor for singleton instance. * @@ -214,18 +214,26 @@ public final class LocationHelper { * @param context The {@link Context} from where this was called. * @param minIntervalMillis The minimum time interval in millisecond * @param minDistance The minimum distance for an update to be received. + * @param priority The requested granularity of updates. * @return true if subscription started, false otherwise. */ - public boolean startLocationUpdates(final Context context, final int minIntervalMillis, final int minDistance) { - if (mIsSubscribed) { - Log.d(TAG, "startLocationUpdates: Already subscribed, no need to update"); + public boolean startLocationUpdates(final Context context, final int minIntervalMillis, + final int minDistance, final int priority) { + if (priority == mCurrentPriority) { + Log.d(TAG, "startLocationUpdates: Already subscribed with this granularity, no need to update"); return true; } + if (mIsSubscribed) { + Log.d(TAG, "startLocationUpdates: Priority changed, stop subscription first"); + mFusedLocationProvider.removeLocationUpdates(mLocationCallback); + mCurrentPriority = -1; + } if (ContextCompat.checkSelfPermission(context, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + mCurrentPriority = priority; final LocationRequest locationRequest = new LocationRequest.Builder(minIntervalMillis) .setGranularity(GRANULARITY_FINE) .setMinUpdateDistanceMeters(minDistance) - .setPriority(PRIORITY_BALANCED_POWER_ACCURACY) + .setPriority(mCurrentPriority) .build(); mFusedLocationProvider.requestLocationUpdates(locationRequest, mLocationCallback, Looper.getMainLooper()); mIsSubscribed = true; @@ -244,6 +252,7 @@ public final class LocationHelper { Log.d(TAG, "stopLocationUpdates: Subscription already ended, no need to end again"); return; } + mCurrentPriority = -1; mFusedLocationProvider.removeLocationUpdates(mLocationCallback); mIsSubscribed = false; mSharingStateSubject.onNext(false); diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/workers/ShareLocationBackgroundWorker.java b/app/src/main/java/com/aldo/apps/familyhelpers/workers/ShareLocationBackgroundWorker.java index 18e467b..18ce427 100644 --- a/app/src/main/java/com/aldo/apps/familyhelpers/workers/ShareLocationBackgroundWorker.java +++ b/app/src/main/java/com/aldo/apps/familyhelpers/workers/ShareLocationBackgroundWorker.java @@ -1,12 +1,22 @@ package com.aldo.apps.familyhelpers.workers; +import static android.content.Intent.ACTION_POWER_CONNECTED; +import static android.content.Intent.ACTION_POWER_DISCONNECTED; +import static android.os.BatteryManager.BATTERY_STATUS_CHARGING; +import static android.os.BatteryManager.EXTRA_STATUS; import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS; import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS; import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SHARE_LOCATION_CANCEL_ACTION; import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SLEEP_TIMER_NOTIFICATION_ID; +import static com.google.android.gms.location.Priority.PRIORITY_BALANCED_POWER_ACCURACY; +import static com.google.android.gms.location.Priority.PRIORITY_HIGH_ACCURACY; +import static com.google.android.gms.location.Priority.PRIORITY_LOW_POWER; import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -43,6 +53,10 @@ public class ShareLocationBackgroundWorker extends Service { public void onCreate() { super.onCreate(); mLocationHelper = LocationHelper.getInstance(this); + final IntentFilter batteryFilter = new IntentFilter(); + batteryFilter.addAction(ACTION_POWER_CONNECTED); + batteryFilter.addAction(ACTION_POWER_DISCONNECTED); + registerReceiver(new BatteryStateReceiver(), batteryFilter); } @Override @@ -57,9 +71,20 @@ public class ShareLocationBackgroundWorker extends Service { stopSelf(); return START_NOT_STICKY; } + final IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + final Intent batteryStatus = registerReceiver(null, batteryFilter); + final int priority; + if (batteryStatus != null && batteryStatus.getIntExtra(EXTRA_STATUS, -1) == BATTERY_STATUS_CHARGING) { + Log.d(TAG, "onStartCommand: Phone is charging, go for high accuracy"); + priority = PRIORITY_HIGH_ACCURACY; + } else { + Log.d(TAG, "onStartCommand: Status unknown or not charging, balanced power consumption."); + priority = PRIORITY_BALANCED_POWER_ACCURACY; + } mShareLocationRunnable = () -> mLocationHelper.startLocationUpdates(ShareLocationBackgroundWorker.this, - DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS); + DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, + DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, priority); mHandler.post(mShareLocationRunnable); startForeground(SLEEP_TIMER_NOTIFICATION_ID, mLocationHelper.buildNotification(this)); return super.onStartCommand(intent, flags, startId); @@ -77,4 +102,38 @@ public class ShareLocationBackgroundWorker extends Service { mHandler.removeCallbacks(mShareLocationRunnable); super.onDestroy(); } + + /** + * Base {@link BroadcastReceiver} to listen for the battery state update, listening for whether + * the device got plugged or unplugged. + */ + private class BatteryStateReceiver extends BroadcastReceiver { + + @Override + public void onReceive(final Context context, final Intent intent) { + if (intent == null) { + Log.w(TAG, "onReceive: Empty intent, return..."); + return; + } + if (ACTION_POWER_CONNECTED.equals(intent.getAction())) { + Log.d(TAG, "onReceive: Phone was plugged in, changing to high accuracy mode"); + mLocationHelper.startLocationUpdates(context, + DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, + DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, + PRIORITY_HIGH_ACCURACY); + } else if (ACTION_POWER_DISCONNECTED.equals(intent.getAction())) { + Log.d(TAG, "onReceive: Phone was unplugged, changing to battery saving mode"); + mLocationHelper.startLocationUpdates(context, + DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, + DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, + PRIORITY_BALANCED_POWER_ACCURACY); + } else { + Log.d(TAG, "onReceive: Unknown action [" + intent.getAction() + "], go to low power mode"); + mLocationHelper.startLocationUpdates(context, + DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, + DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, + PRIORITY_LOW_POWER); + } + } + } }