Allow disabling ABRP uploads independently
This commit is contained in:
@@ -202,7 +202,7 @@ public class AbrpUploadService extends Service {
|
||||
// and something else has to. Idempotent, asynchronous, and absent on a car that does
|
||||
// not have the map stack — in which case ext_temp simply stays unreported.
|
||||
|
||||
requestLocationUpdates();
|
||||
if (settings.abrpUploadEnabled) requestLocationUpdates();
|
||||
|
||||
// Fire the first upload after a short warm-up, then every UPLOAD_INTERVAL_SEC.
|
||||
// scheduleWithFixedDelay ensures we always get at least UPLOAD_INTERVAL_SEC
|
||||
@@ -293,12 +293,13 @@ public class AbrpUploadService extends Service {
|
||||
mainHandler.post(this::requestLocationUpdates);
|
||||
Log.i(TAG, "Settings reloaded: interval=" + settings.intervalSec + "s"
|
||||
+ " boostLowSoc=" + settings.boostLowSoc
|
||||
+ " lowSoc=" + settings.lowSocPercent + "%");
|
||||
+ " lowSoc=" + settings.lowSocPercent + "%"
|
||||
+ " abrpUpload=" + settings.abrpUploadEnabled);
|
||||
}
|
||||
// Same watchdog for GPS: requestLocationUpdates used to run once in onCreate,
|
||||
// so a provider that was off at start-up — or dropped later — meant
|
||||
// position-less telemetry for the rest of the session.
|
||||
if (!locationUpdatesActive
|
||||
if (settings.abrpUploadEnabled && !locationUpdatesActive
|
||||
&& System.currentTimeMillis() - lastLocationRequestMs
|
||||
> LOCATION_RETRY_INTERVAL_SEC * 1000) {
|
||||
Log.w(TAG, "Location updates inactive, re-arming");
|
||||
@@ -306,7 +307,8 @@ public class AbrpUploadService extends Service {
|
||||
}
|
||||
// Before the upload, not after: an upload that fails for want of a network is
|
||||
// the thing this is here to prevent. Cheap and rate-limited when already on.
|
||||
if (wifi != null && prefs.getBoolean(MainActivity.WIFI_AUTO_KEY, true)) {
|
||||
if (settings.abrpUploadEnabled && wifi != null
|
||||
&& prefs.getBoolean(MainActivity.WIFI_AUTO_KEY, true)) {
|
||||
wifi.ensureConnected(false);
|
||||
}
|
||||
doUpload();
|
||||
@@ -323,6 +325,12 @@ public class AbrpUploadService extends Service {
|
||||
EnergySnapshot vehicle = energyReader.read(sampleMs);
|
||||
consumptionTracker.sample(vehicle);
|
||||
|
||||
// Keep local consumption history alive while another app owns the ABRP feed.
|
||||
if (!settings.abrpUploadEnabled) {
|
||||
updateNotification(getString(R.string.notif_tracking_locally));
|
||||
return;
|
||||
}
|
||||
|
||||
String token = securePrefs.getString(SecurePrefs.KEY_TOKEN, "").trim();
|
||||
String apiKey = securePrefs.getString(SecurePrefs.KEY_API_KEY, "").trim();
|
||||
|
||||
@@ -663,6 +671,12 @@ public class AbrpUploadService extends Service {
|
||||
try { locationManager.removeUpdates(locationListener); } catch (Exception ignored) {}
|
||||
locationUpdatesActive = false;
|
||||
|
||||
if (!settings.abrpUploadEnabled) {
|
||||
lastLocation = null;
|
||||
Log.i(TAG, "GPS updates stopped while ABRP upload is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
||||
// Match the upload cadence: a 10 s GPS subscription burned power for
|
||||
// fixes that were thrown away between uploads.
|
||||
|
||||
@@ -50,8 +50,10 @@ public class BootReceiver extends BroadcastReceiver {
|
||||
SharedPreferences secure = SecurePrefs.get(context);
|
||||
boolean haveCreds = !secure.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
||||
&& !secure.getString(SecurePrefs.KEY_API_KEY, "").trim().isEmpty();
|
||||
boolean uploadEnabled = prefs.getBoolean(UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED);
|
||||
|
||||
if (!enabled || !autostart || !haveCreds) {
|
||||
if (!enabled || !autostart || (uploadEnabled && !haveCreds)) {
|
||||
Log.i(TAG, action + " ignored (enabled=" + enabled
|
||||
+ " autostart=" + autostart + " credentials=" + haveCreds + ")");
|
||||
return;
|
||||
|
||||
@@ -70,6 +70,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
private TextInputLayout tokenLayout;
|
||||
private TextInputEditText tokenInput;
|
||||
private SwitchMaterial serviceSwitch;
|
||||
private SwitchMaterial abrpUploadSwitch;
|
||||
private SwitchMaterial autostartSwitch;
|
||||
private TextView statusText;
|
||||
private Button testButton;
|
||||
@@ -250,6 +251,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
tokenLayout = abrpPane.findViewById(R.id.token_layout);
|
||||
tokenInput = abrpPane.findViewById(R.id.token_input);
|
||||
serviceSwitch = servicePane.findViewById(R.id.service_switch);
|
||||
abrpUploadSwitch = servicePane.findViewById(R.id.abrp_upload_switch);
|
||||
autostartSwitch = servicePane.findViewById(R.id.autostart_switch);
|
||||
statusText = servicePane.findViewById(R.id.status_text);
|
||||
testButton = abrpPane.findViewById(R.id.test_button);
|
||||
@@ -275,6 +277,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
apiKeyInput.setText(savedApiKeyOrDefault());
|
||||
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
||||
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
||||
abrpUploadSwitch.setChecked(prefs.getBoolean(
|
||||
UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED));
|
||||
|
||||
autostartSwitch.setChecked(
|
||||
prefs.getBoolean(UploadSettings.KEY_AUTOSTART, UploadSettings.DEFAULT_AUTOSTART));
|
||||
@@ -290,7 +295,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
boolean enabled = prefs.getBoolean("service_enabled", false);
|
||||
boolean haveCreds = !securePrefs.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
||||
&& !securePrefs.getString(SecurePrefs.KEY_API_KEY, "").trim().isEmpty();
|
||||
if (enabled && haveCreds) {
|
||||
boolean uploadEnabled = prefs.getBoolean(UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED);
|
||||
if (enabled && (!uploadEnabled || haveCreds)) {
|
||||
// Asked for first, and deliberately: the service declares the `location`
|
||||
// foreground type, and since API 34 starting it without the permission behind
|
||||
// that type is a SecurityException in its own onCreate. Started this way round,
|
||||
@@ -308,7 +315,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (checked) {
|
||||
String apiKey = textOf(apiKeyInput);
|
||||
String token = textOf(tokenInput);
|
||||
if (apiKey.isEmpty() || token.isEmpty()) {
|
||||
if (abrpUploadSwitch.isChecked() && (apiKey.isEmpty() || token.isEmpty())) {
|
||||
serviceSwitch.setChecked(false);
|
||||
if (apiKey.isEmpty()) apiKeyLayout.setError(getString(R.string.api_key_required));
|
||||
if (token.isEmpty()) tokenLayout.setError(getString(R.string.token_required));
|
||||
@@ -325,6 +332,22 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
refreshStatus();
|
||||
});
|
||||
|
||||
abrpUploadSwitch.setOnCheckedChangeListener((btn, checked) -> {
|
||||
if (checked) {
|
||||
String apiKey = textOf(apiKeyInput);
|
||||
String token = textOf(tokenInput);
|
||||
if (apiKey.isEmpty() || token.isEmpty()) {
|
||||
abrpUploadSwitch.setChecked(false);
|
||||
if (apiKey.isEmpty()) apiKeyLayout.setError(getString(R.string.api_key_required));
|
||||
if (token.isEmpty()) tokenLayout.setError(getString(R.string.token_required));
|
||||
return;
|
||||
}
|
||||
}
|
||||
prefs.edit().putBoolean(UploadSettings.KEY_ABRP_UPLOAD_ENABLED, checked).apply();
|
||||
AbrpUploadService.reloadSettings();
|
||||
refreshStatus();
|
||||
});
|
||||
}
|
||||
|
||||
private void showAbout() {
|
||||
@@ -362,6 +385,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
apiKeyInput.setText(savedApiKeyOrDefault());
|
||||
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
||||
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
||||
abrpUploadSwitch.setChecked(prefs.getBoolean(
|
||||
UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED));
|
||||
autostartSwitch.setChecked(
|
||||
prefs.getBoolean(UploadSettings.KEY_AUTOSTART, UploadSettings.DEFAULT_AUTOSTART));
|
||||
// Poll state and log only while the screen is up; onPause cancels it.
|
||||
@@ -1070,6 +1096,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
// force-kill because onDestroy never ran.
|
||||
UploadLog.State state = AbrpUploadService.state();
|
||||
|
||||
if (AbrpUploadService.isRunning() && !prefs.getBoolean(
|
||||
UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED)) {
|
||||
statusText.setText(R.string.state_tracking_locally);
|
||||
statusText.setTextColor(COLOR_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case ERROR:
|
||||
// Derived from the log, not from the last status alone: a single failed
|
||||
|
||||
@@ -15,6 +15,7 @@ final class UploadSettings {
|
||||
static final String KEY_BOOST_LOW_SOC = "boost_low_soc";
|
||||
static final String KEY_LOW_SOC_PERCENT = "low_soc_percent";
|
||||
static final String KEY_AUTOSTART = "autostart";
|
||||
static final String KEY_ABRP_UPLOAD_ENABLED = "abrp_upload_enabled";
|
||||
|
||||
/**
|
||||
* On by default: an ABRP plan is only useful if it is fed from the moment the drive
|
||||
@@ -22,6 +23,7 @@ final class UploadSettings {
|
||||
* service that starts itself must also be switchable off.
|
||||
*/
|
||||
static final boolean DEFAULT_AUTOSTART = true;
|
||||
static final boolean DEFAULT_ABRP_UPLOAD_ENABLED = true;
|
||||
|
||||
/**
|
||||
* Default cadence while driving. 60 s is roughly 1.5 km between points at motorway
|
||||
@@ -44,18 +46,26 @@ final class UploadSettings {
|
||||
final int intervalSec;
|
||||
final boolean boostLowSoc;
|
||||
final int lowSocPercent;
|
||||
final boolean abrpUploadEnabled;
|
||||
|
||||
UploadSettings(int intervalSec, boolean boostLowSoc, int lowSocPercent) {
|
||||
this(intervalSec, boostLowSoc, lowSocPercent, DEFAULT_ABRP_UPLOAD_ENABLED);
|
||||
}
|
||||
|
||||
UploadSettings(int intervalSec, boolean boostLowSoc, int lowSocPercent,
|
||||
boolean abrpUploadEnabled) {
|
||||
this.intervalSec = intervalSec;
|
||||
this.boostLowSoc = boostLowSoc;
|
||||
this.lowSocPercent = lowSocPercent;
|
||||
this.abrpUploadEnabled = abrpUploadEnabled;
|
||||
}
|
||||
|
||||
static UploadSettings from(SharedPreferences prefs) {
|
||||
return new UploadSettings(
|
||||
prefs.getInt(KEY_INTERVAL_SEC, DEFAULT_INTERVAL_SEC),
|
||||
prefs.getBoolean(KEY_BOOST_LOW_SOC, DEFAULT_BOOST_LOW_SOC),
|
||||
prefs.getInt(KEY_LOW_SOC_PERCENT, DEFAULT_LOW_SOC_PERCENT));
|
||||
prefs.getInt(KEY_LOW_SOC_PERCENT, DEFAULT_LOW_SOC_PERCENT),
|
||||
prefs.getBoolean(KEY_ABRP_UPLOAD_ENABLED, DEFAULT_ABRP_UPLOAD_ENABLED));
|
||||
}
|
||||
|
||||
static UploadSettings defaults() {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_service_controls" android:textAppearance="@style/Text.EV.Eyebrow" />
|
||||
<TextView android:id="@+id/status_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_input_panel" android:padding="16dp" android:layout_marginTop="20dp" android:layout_marginBottom="12dp" android:text="@string/status_stopped" android:textAppearance="@style/Text.EV.Body" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/service_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_upload_enabled" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/abrp_upload_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_abrp_upload_enabled" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_abrp_upload_enabled" android:textAppearance="@style/Text.EV.Secondary" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/autostart_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_autostart" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_autostart" android:textAppearance="@style/Text.EV.Secondary" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_service_controls" android:textAppearance="@style/Text.EV.Eyebrow" />
|
||||
<TextView android:id="@+id/status_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_input_panel" android:padding="16dp" android:layout_marginTop="20dp" android:layout_marginBottom="12dp" android:text="@string/status_stopped" android:textAppearance="@style/Text.EV.Body" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/service_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_upload_enabled" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/abrp_upload_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_abrp_upload_enabled" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_abrp_upload_enabled" android:textAppearance="@style/Text.EV.Secondary" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/autostart_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_autostart" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
|
||||
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_autostart" android:textAppearance="@style/Text.EV.Secondary" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -74,7 +74,9 @@
|
||||
<string name="token_required">Enter your ABRP token first</string>
|
||||
|
||||
<string name="card_service">Upload Service</string>
|
||||
<string name="label_upload_enabled">Enable background uploading</string>
|
||||
<string name="label_upload_enabled">Enable background telemetry</string>
|
||||
<string name="label_abrp_upload_enabled">Upload telemetry to ABRP</string>
|
||||
<string name="hint_abrp_upload_enabled">Turn this off when DiPlay sends ABRP data. Local consumption tracking and background telemetry keep running.</string>
|
||||
<string name="label_autostart">Start automatically with the car</string>
|
||||
<string name="hint_autostart">Uploading resumes on its own when the head unit powers up. Turn this off to start it by hand from this screen.</string>
|
||||
|
||||
@@ -98,6 +100,8 @@
|
||||
<string name="state_stopped">Stopped</string>
|
||||
<string name="state_starting">Starting…</string>
|
||||
<string name="state_running">Running</string>
|
||||
<string name="state_tracking_locally">Tracking locally — ABRP upload off</string>
|
||||
<string name="notif_tracking_locally">Tracking locally — ABRP upload off</string>
|
||||
<string name="state_error">In error — last %1$d uploads failed</string>
|
||||
|
||||
<!-- Call log -->
|
||||
|
||||
Reference in New Issue
Block a user