[ShareLocation] Added Settings to change values for location updates

Now the requested frequency and the priority of location updates can be
selected in a newly integrated SettingsActivity which can be extended
for future use.
This commit is contained in:
Alexander Dörflinger
2025-03-26 13:30:03 +01:00
parent 211bdd195f
commit ed2693236c
13 changed files with 273 additions and 48 deletions

6
.idea/sonarlint.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SonarLintProjectSettings">
<option name="bindingSuggestionsEnabled" value="false" />
</component>
</project>

View File

@@ -42,7 +42,8 @@ dependencies {
implementation 'com.google.android.gms:play-services-location:21.3.0' implementation 'com.google.android.gms:play-services-location:21.3.0'
// Glide // Glide
implementation 'com.github.bumptech.glide:glide:4.16.0' // Check for the latest version implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation 'androidx.preference:preference:1.2.0'// Check for the latest version
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
//CircleImageView //CircleImageView

View File

@@ -20,10 +20,15 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.MyApplication" android:theme="@style/Theme.MyApplication"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings" />
<meta-data <meta-data
android:name="com.google.android.geo.API_KEY" android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBrwogmBLNjbhngmON_RWhKrV1woF6ypR4" /> android:value="AIzaSyBrwogmBLNjbhngmON_RWhKrV1woF6ypR4" />
<activity <activity
android:name=".HelperGridActivity" android:name=".HelperGridActivity"
android:exported="true"> android:exported="true">
@@ -33,23 +38,23 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".ShareLocationActivity" /> <activity android:name=".ShareLocationActivity" />
<service <service
android:name=".workers.SleepTimerHelper" android:name=".workers.SleepTimerHelper"
android:foregroundServiceType="specialUse" /> android:foregroundServiceType="specialUse" />
<service
<service android:name=".workers.ShareLocationBackgroundWorker" android:name=".workers.ShareLocationBackgroundWorker"
android:foregroundServiceType="location" /> android:foregroundServiceType="location" />
<receiver <receiver
android:name="com.aldo.apps.familyhelpers.DoerflingerHelpersDeviceAdminReceiver" android:name=".DoerflingerHelpersDeviceAdminReceiver"
android:exported="true" android:exported="true"
android:permission="android.permission.BIND_DEVICE_ADMIN"> android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data <meta-data
android:name="android.app.device_admin" android:name="android.app.device_admin"
android:resource="@xml/device_admin" /> android:resource="@xml/device_admin" />
<intent-filter> <intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.DEVICE_ADMIN_DISABLED" /> <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />

View File

@@ -50,6 +50,11 @@ public class HelperGridActivity extends AppCompatActivity {
*/ */
private HelperGroupTile mShareLocationTile; private HelperGroupTile mShareLocationTile;
/**
* {@link HelperGroupTile} holding the settings.
*/
private HelperGroupTile mSettingsTile;
/** /**
* Instance of the {@link DevicePolicyManagerHelper} to roll out device specific actions. * Instance of the {@link DevicePolicyManagerHelper} to roll out device specific actions.
*/ */
@@ -110,6 +115,7 @@ public class HelperGridActivity extends AppCompatActivity {
mDevicePolicyHelper = DevicePolicyManagerHelper.getInstance(this); mDevicePolicyHelper = DevicePolicyManagerHelper.getInstance(this);
initSleepTimer(); initSleepTimer();
initShareLocation(); initShareLocation();
initSettings();
} }
/** /**
@@ -165,7 +171,21 @@ public class HelperGridActivity extends AppCompatActivity {
}; };
mShareLocationTile.setLogo(R.drawable.ic_location_helper); mShareLocationTile.setLogo(R.drawable.ic_location_helper);
mShareLocationTile.setTitle(R.string.title_share_location); mShareLocationTile.setTitle(R.string.title_share_location);
}
/**
* Helper method to initialize the settings tile.
*/
private void initSettings() {
mSettingsTile = new HelperGroupTile(findViewById(R.id.tile_settings)) {
@Override
public void launchHelper() {
final Intent intent = new Intent(HelperGridActivity.this, SettingsActivity.class);
startActivity(intent);
}
};
mSettingsTile.setTitle(R.string.title_settings);
mSettingsTile.setLogo(R.drawable.ic_settings);
} }
/** /**

View File

@@ -0,0 +1,39 @@
package com.aldo.apps.familyhelpers;
import android.os.Bundle;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceFragmentCompat;
/**
* Simple Settings Activity for some app specific settings.
*/
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
/**
* The actual Settings fragment, containing the settings as defined in R.xml.root_preferences.
*/
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
}

View File

@@ -39,7 +39,6 @@ import io.reactivex.rxjava3.subjects.BehaviorSubject;
/** /**
* Helper class to encapsulate all Location specific calls into one utility class. * Helper class to encapsulate all Location specific calls into one utility class.
* TODO: Change logic to make use of the FusedLocationProvider.
*/ */
public final class LocationHelper { public final class LocationHelper {
@@ -67,6 +66,10 @@ public final class LocationHelper {
*/ */
private final FusedLocationProviderClient mFusedLocationProvider; private final FusedLocationProviderClient mFusedLocationProvider;
/**
* The {@link LocationCallback} to be invoked by the {@link FusedLocationProviderClient} as soon
* as a new {@link LocationResult} was received.
*/
private final LocationCallback mLocationCallback = new LocationCallback() { private final LocationCallback mLocationCallback = new LocationCallback() {
@Override @Override
public void onLocationResult(@NonNull final LocationResult locationResult) { public void onLocationResult(@NonNull final LocationResult locationResult) {
@@ -113,6 +116,11 @@ public final class LocationHelper {
*/ */
private boolean mIsSubscribed; private boolean mIsSubscribed;
/**
* The currently selected frequency.
*/
private int mCurrentFrequency = -1;
/** /**
* The current granularity used. * The current granularity used.
*/ */
@@ -219,8 +227,8 @@ public final class LocationHelper {
*/ */
public boolean startLocationUpdates(final Context context, final int minIntervalMillis, public boolean startLocationUpdates(final Context context, final int minIntervalMillis,
final int minDistance, final int priority) { final int minDistance, final int priority) {
if (priority == mCurrentPriority) { if (priority == mCurrentPriority && mCurrentFrequency == minIntervalMillis) {
Log.d(TAG, "startLocationUpdates: Already subscribed with this granularity, no need to update"); Log.d(TAG, "startLocationUpdates: Already subscribed with this granularity and frequency, no need to update");
return true; return true;
} }
if (mIsSubscribed) { if (mIsSubscribed) {
@@ -230,7 +238,8 @@ public final class LocationHelper {
} }
if (ContextCompat.checkSelfPermission(context, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(context, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mCurrentPriority = priority; mCurrentPriority = priority;
final LocationRequest locationRequest = new LocationRequest.Builder(minIntervalMillis) mCurrentFrequency = minIntervalMillis;
final LocationRequest locationRequest = new LocationRequest.Builder(mCurrentFrequency)
.setGranularity(GRANULARITY_FINE) .setGranularity(GRANULARITY_FINE)
.setMinUpdateDistanceMeters(minDistance) .setMinUpdateDistanceMeters(minDistance)
.setPriority(mCurrentPriority) .setPriority(mCurrentPriority)
@@ -279,6 +288,12 @@ public final class LocationHelper {
return mSharingStateSubject; return mSharingStateSubject;
} }
/**
* Helper method to handle a received location by putting it to the database and inform listeners
* about the new location.
*
* @param location The received {@link Location}.
*/
private void handleReceivedLocation(final Location location) { private void handleReceivedLocation(final Location location) {
final LocationObject locationObject = LocationObject.fromLocation(location); final LocationObject locationObject = LocationObject.fromLocation(location);
Log.d(TAG, "onLocationChanged: Received update with " + locationObject); Log.d(TAG, "onLocationChanged: Received update with " + locationObject);

View File

@@ -17,17 +17,21 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;
import com.aldo.apps.familyhelpers.R;
/** /**
* Service implementation to keep location updates running also in the background. * Service implementation to keep location updates running also in the background.
*/ */
public class ShareLocationBackgroundWorker extends Service { public class ShareLocationBackgroundWorker extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
/** /**
* Tag for debugging purpose. * Tag for debugging purpose.
@@ -49,6 +53,24 @@ public class ShareLocationBackgroundWorker extends Service {
*/ */
private Runnable mShareLocationRunnable; private Runnable mShareLocationRunnable;
/**
* Integer holding the frequency in which updates shall be received. Defaults to
* {@link com.aldo.apps.familyhelpers.utils.GlobalConstants#DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS}
*/
private int mSelectedFrequency;
/**
* Flag indicating whether the subscription priority shall be automatically selected based on
* charging state. Defaults to true.
*/
private boolean mAutoPriority;
/**
* Flag indicatin whether the non-automatically selected priority shall be high accuracy (== true)
* or balanced power consumption (== false). Defaults to false.
*/
private boolean mManualHighAccuracy;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@@ -57,6 +79,11 @@ public class ShareLocationBackgroundWorker extends Service {
batteryFilter.addAction(ACTION_POWER_CONNECTED); batteryFilter.addAction(ACTION_POWER_CONNECTED);
batteryFilter.addAction(ACTION_POWER_DISCONNECTED); batteryFilter.addAction(ACTION_POWER_DISCONNECTED);
registerReceiver(new BatteryStateReceiver(), batteryFilter); registerReceiver(new BatteryStateReceiver(), batteryFilter);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
mSelectedFrequency = preferences.getInt(getString(R.string.pref_key_share_location_freq), DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS);
mAutoPriority = preferences.getBoolean(getString(R.string.pref_key_share_location_auto_acc), true);
mManualHighAccuracy = preferences.getBoolean(getString(R.string.pref_key_share_location_man_acc), false);
preferences.registerOnSharedPreferenceChangeListener(this);
} }
@Override @Override
@@ -71,20 +98,7 @@ public class ShareLocationBackgroundWorker extends Service {
stopSelf(); stopSelf();
return START_NOT_STICKY; return START_NOT_STICKY;
} }
final IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); mShareLocationRunnable = this::triggerLocationSharing;
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, priority);
mHandler.post(mShareLocationRunnable); mHandler.post(mShareLocationRunnable);
startForeground(SLEEP_TIMER_NOTIFICATION_ID, mLocationHelper.buildNotification(this)); startForeground(SLEEP_TIMER_NOTIFICATION_ID, mLocationHelper.buildNotification(this));
return super.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId);
@@ -103,6 +117,53 @@ public class ShareLocationBackgroundWorker extends Service {
super.onDestroy(); super.onDestroy();
} }
/**
* Triggers the location updates based on the preferences set in the application. Will read out the
* currently selected switch values for whether the priority should be selected automatically or not
* and if not it will take the selected priority from the setting. If auto selection is enabled, the
* priority will be selected based on the current charging state.
*/
private void triggerLocationSharing() {
final int priority;
if (mAutoPriority) {
final IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
final Intent batteryStatus = registerReceiver(null, batteryFilter);
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;
}
} else if (mManualHighAccuracy) {
priority = PRIORITY_HIGH_ACCURACY;
} else {
priority = PRIORITY_BALANCED_POWER_ACCURACY;
}
mLocationHelper.startLocationUpdates(ShareLocationBackgroundWorker.this,
mSelectedFrequency,
DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, priority);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, @Nullable final String key) {
if (!mLocationHelper.isCurrentlySharing()) {
Log.d(TAG, "onSharedPreferenceChanged: currently not sharing, nothing to do.");
return;
}
if (getString(R.string.pref_key_share_location_freq).equalsIgnoreCase(key)) {
mSelectedFrequency = sharedPreferences.getInt(key, DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS);
Log.d(TAG, "onSharedPreferenceChanged: Update Frequency changed to [" + mSelectedFrequency + "]");
} else if (getString(R.string.pref_key_share_location_auto_acc).equalsIgnoreCase(key)) {
mAutoPriority = sharedPreferences.getBoolean(key, true);
Log.d(TAG, "onSharedPreferenceChanged: Auto Priority switch changed to [" + mAutoPriority + "]");
} else if (getString(R.string.pref_key_share_location_man_acc).equalsIgnoreCase(key)) {
mManualHighAccuracy = sharedPreferences.getBoolean(key, false);
Log.d(TAG, "onSharedPreferenceChanged: HighPriority switch changed to [" + mManualHighAccuracy + "]");
}
triggerLocationSharing();
}
/** /**
* Base {@link BroadcastReceiver} to listen for the battery state update, listening for whether * Base {@link BroadcastReceiver} to listen for the battery state update, listening for whether
* the device got plugged or unplugged. * the device got plugged or unplugged.
@@ -115,24 +176,14 @@ public class ShareLocationBackgroundWorker extends Service {
Log.w(TAG, "onReceive: Empty intent, return..."); Log.w(TAG, "onReceive: Empty intent, return...");
return; return;
} }
if (ACTION_POWER_CONNECTED.equals(intent.getAction())) { if (!mAutoPriority) {
Log.d(TAG, "onReceive: Phone was plugged in, changing to high accuracy mode"); Log.d(TAG, "onReceive: Automatic priority selection is not selected, no need to update.");
mLocationHelper.startLocationUpdates(context, return;
DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS, }
DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS, final String action = intent.getAction();
PRIORITY_HIGH_ACCURACY); if (ACTION_POWER_CONNECTED.equals(action) || ACTION_POWER_DISCONNECTED.equals(action)) {
} else if (ACTION_POWER_DISCONNECTED.equals(intent.getAction())) { Log.d(TAG, "onReceive: Received [" + action + "], with automatic prio, retrigger");
Log.d(TAG, "onReceive: Phone was unplugged, changing to battery saving mode"); triggerLocationSharing();
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);
} }
} }
} }

View File

@@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="800dp"
android:height="800dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#1C274C"/>
<path
android:pathData="M3.661,10.639C4.134,10.936 4.438,11.442 4.438,12C4.438,12.558 4.134,13.064 3.661,13.361C3.34,13.563 3.132,13.724 2.985,13.916C2.662,14.337 2.52,14.869 2.589,15.395C2.641,15.789 2.874,16.193 3.34,17C3.806,17.807 4.039,18.21 4.354,18.453C4.775,18.775 5.307,18.918 5.833,18.849C6.073,18.817 6.316,18.719 6.652,18.541C7.145,18.28 7.736,18.27 8.219,18.549C8.702,18.828 8.988,19.344 9.009,19.902C9.023,20.281 9.06,20.542 9.152,20.765C9.355,21.255 9.745,21.645 10.235,21.848C10.602,22 11.068,22 12,22C12.932,22 13.398,22 13.765,21.848C14.255,21.645 14.645,21.255 14.848,20.765C14.94,20.542 14.977,20.281 14.991,19.902C15.012,19.344 15.298,18.828 15.781,18.549C16.264,18.27 16.854,18.28 17.348,18.541C17.684,18.719 17.927,18.817 18.167,18.849C18.693,18.918 19.225,18.776 19.646,18.453C19.961,18.211 20.194,17.807 20.66,17C20.868,16.641 21.029,16.361 21.149,16.127M20.339,13.361C19.866,13.064 19.562,12.558 19.562,12C19.562,11.442 19.866,10.936 20.339,10.639C20.66,10.437 20.867,10.276 21.015,10.084C21.338,9.663 21.48,9.131 21.411,8.605C21.359,8.211 21.126,7.807 20.66,7C20.194,6.193 19.961,5.79 19.646,5.547C19.225,5.224 18.693,5.082 18.167,5.151C17.927,5.183 17.684,5.281 17.348,5.459C16.854,5.72 16.264,5.73 15.781,5.451C15.298,5.172 15.012,4.656 14.991,4.098C14.977,3.719 14.94,3.458 14.848,3.235C14.645,2.745 14.255,2.355 13.765,2.152C13.398,2 12.932,2 12,2C11.068,2 10.602,2 10.235,2.152C9.745,2.355 9.355,2.745 9.152,3.235C9.06,3.458 9.023,3.718 9.009,4.098C8.988,4.656 8.702,5.172 8.219,5.451C7.736,5.73 7.145,5.72 6.652,5.459C6.316,5.281 6.073,5.183 5.833,5.151C5.307,5.082 4.775,5.224 4.354,5.547C4.039,5.789 3.806,6.193 3.34,7C3.132,7.359 2.971,7.639 2.851,7.873"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#1C274C"
android:strokeLineCap="round"/>
</vector>

View File

@@ -16,26 +16,33 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
tools:text="@string/welcome_message_test"/> tools:text="@string/welcome_message_test"/>
<LinearLayout <GridLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/tv_welcome_message" app:layout_constraintTop_toBottomOf="@id/tv_welcome_message"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:weightSum="2"> android:columnCount="2">
<include layout="@layout/helper_group_tile_item" <include layout="@layout/helper_group_tile_item"
android:id="@+id/tile_sleep_timer" android:id="@+id/tile_sleep_timer"
android:layout_margin="10dp" android:layout_margin="10dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"/> android:layout_columnWeight="1"/>
<include layout="@layout/helper_group_tile_item" <include layout="@layout/helper_group_tile_item"
android:id="@+id/tile_share_location" android:id="@+id/tile_share_location"
android:layout_margin="10dp" android:layout_margin="10dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"/> android:layout_columnWeight="1"/>
</LinearLayout> <include layout="@layout/helper_group_tile_item"
android:id="@+id/tile_settings"
android:layout_margin="10dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"/>
</GridLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@@ -0,0 +1,2 @@
<resources>
</resources>

View File

@@ -32,5 +32,25 @@
<string name="share_location_info_timestamp">This update was received at: %s</string> <string name="share_location_info_timestamp">This update was received at: %s</string>
<string name="share_location_toggle_button">Share your location</string> <string name="share_location_toggle_button">Share your location</string>
<string name="share_location_background_permission_rationale">In order to share your position also while in the background, please grant the always permission</string> <string name="share_location_background_permission_rationale">In order to share your position also while in the background, please grant the always permission</string>
<string name="title_activity_settings">SettingsActivity</string>
<!-- Settings -->
<string name="title_settings">Settings</string>
<!-- Share Location Preference -->
<string name="pref_share_location_header">Share Location</string>
<string name="pref_share_location_freq_title">Location Update frequency</string>
<string name="pref_share_location_freq_summary">The minimum amount of seconds to wait between two location updates\n<b>Note:</b> The lower the value the higher the battery consumption</string>
<string name="pref_auto_accuracy_title">Automatic accuracy detection</string>
<string name="pref_auto_accuracy_summary_on">Accuracy will be auto selected based on the current charging state</string>
<string name="pref_auto_accuracy_summary_off">Select high accuracy vs. balanced power consumption below</string>
<string name="pref_manual_accuracy_title">Force high accuracy</string>
<string name="pref_manual_accuracy_summary_on">High accuracy for location data, may drain battery faster</string>
<string name="pref_manual_accuracy_summary_off">Lower accuracy for location data, but better battery consumption</string>
<!-- Preference Keys -->
<string name="pref_key_share_location_freq" translatable="false">location_update_freq</string>
<string name="pref_key_share_location_auto_acc" translatable="false">auto_accuracy</string>
<string name="pref_key_share_location_man_acc" translatable="false">manual_accuracy</string>
</resources> </resources>

View File

@@ -0,0 +1,33 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory app:title="@string/pref_share_location_header">
<SeekBarPreference
app:key="@string/pref_key_share_location_freq"
app:title="@string/pref_share_location_freq_title"
app:min="1"
android:max="60"
app:seekBarIncrement="1"
app:showSeekBarValue="true"
app:defaultValue="10"
app:summary="@string/pref_share_location_freq_summary"/>
<SwitchPreferenceCompat
app:key="@string/pref_key_share_location_auto_acc"
app:disableDependentsState="true"
app:defaultValue="true"
app:summaryOff="@string/pref_auto_accuracy_summary_off"
app:summaryOn="@string/pref_auto_accuracy_summary_on"
app:title="@string/pref_auto_accuracy_title" />
<SwitchPreferenceCompat
app:dependency="@string/pref_key_share_location_auto_acc"
app:key="@string/pref_key_share_location_man_acc"
app:summaryOff="@string/pref_manual_accuracy_summary_off"
app:summaryOn="@string/pref_manual_accuracy_summary_on"
app:title="@string/pref_manual_accuracy_title" />
</PreferenceCategory>
</PreferenceScreen>