[ShareLocation] Added functionality to set priority of updates

Now the priority of updates changes automatically, based on the current
charging state. If the device charges, then high accuracy is used,
otherwise the device will go to low power consumption mode.
This commit is contained in:
Alexander Dörflinger
2025-03-26 11:12:33 +01:00
parent 5e5c308d37
commit 211bdd195f
2 changed files with 78 additions and 10 deletions

View File

@@ -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);

View File

@@ -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);
}
}
}
}