Allow disabling ABRP uploads independently
This commit is contained in:
@@ -4,6 +4,14 @@ All notable changes to this project are documented here. Format follows
|
|||||||
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
||||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.2.34] - 2026-10-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added a separate **Upload telemetry to ABRP** switch. Turning it off keeps background
|
||||||
|
vehicle sampling, consumption history and OTA support running, but stops ABRP network
|
||||||
|
uploads so DiPlay can be the sole live telemetry sender.
|
||||||
|
|
||||||
## [2.2.33] - 2026-10-02
|
## [2.2.33] - 2026-10-02
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
dbd0fcb9579a1bc62c694133066a5b27856e1b46c5a123df4831a5fc75568c1c FatihsMG4-unstable-2.2.34.apk
|
||||||
+2
-2
@@ -34,8 +34,8 @@ android {
|
|||||||
applicationId "com.evsuite.abrp"
|
applicationId "com.evsuite.abrp"
|
||||||
minSdk 27
|
minSdk 27
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 50
|
versionCode 51
|
||||||
versionName "2.2.33"
|
versionName "2.2.34"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ public class AbrpUploadService extends Service {
|
|||||||
// and something else has to. Idempotent, asynchronous, and absent on a car that does
|
// 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.
|
// 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.
|
// Fire the first upload after a short warm-up, then every UPLOAD_INTERVAL_SEC.
|
||||||
// scheduleWithFixedDelay ensures we always get at least 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);
|
mainHandler.post(this::requestLocationUpdates);
|
||||||
Log.i(TAG, "Settings reloaded: interval=" + settings.intervalSec + "s"
|
Log.i(TAG, "Settings reloaded: interval=" + settings.intervalSec + "s"
|
||||||
+ " boostLowSoc=" + settings.boostLowSoc
|
+ " boostLowSoc=" + settings.boostLowSoc
|
||||||
+ " lowSoc=" + settings.lowSocPercent + "%");
|
+ " lowSoc=" + settings.lowSocPercent + "%"
|
||||||
|
+ " abrpUpload=" + settings.abrpUploadEnabled);
|
||||||
}
|
}
|
||||||
// Same watchdog for GPS: requestLocationUpdates used to run once in onCreate,
|
// Same watchdog for GPS: requestLocationUpdates used to run once in onCreate,
|
||||||
// so a provider that was off at start-up — or dropped later — meant
|
// so a provider that was off at start-up — or dropped later — meant
|
||||||
// position-less telemetry for the rest of the session.
|
// position-less telemetry for the rest of the session.
|
||||||
if (!locationUpdatesActive
|
if (settings.abrpUploadEnabled && !locationUpdatesActive
|
||||||
&& System.currentTimeMillis() - lastLocationRequestMs
|
&& System.currentTimeMillis() - lastLocationRequestMs
|
||||||
> LOCATION_RETRY_INTERVAL_SEC * 1000) {
|
> LOCATION_RETRY_INTERVAL_SEC * 1000) {
|
||||||
Log.w(TAG, "Location updates inactive, re-arming");
|
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
|
// 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.
|
// 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);
|
wifi.ensureConnected(false);
|
||||||
}
|
}
|
||||||
doUpload();
|
doUpload();
|
||||||
@@ -323,6 +325,12 @@ public class AbrpUploadService extends Service {
|
|||||||
EnergySnapshot vehicle = energyReader.read(sampleMs);
|
EnergySnapshot vehicle = energyReader.read(sampleMs);
|
||||||
consumptionTracker.sample(vehicle);
|
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 token = securePrefs.getString(SecurePrefs.KEY_TOKEN, "").trim();
|
||||||
String apiKey = securePrefs.getString(SecurePrefs.KEY_API_KEY, "").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) {}
|
try { locationManager.removeUpdates(locationListener); } catch (Exception ignored) {}
|
||||||
locationUpdatesActive = false;
|
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)) {
|
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
||||||
// Match the upload cadence: a 10 s GPS subscription burned power for
|
// Match the upload cadence: a 10 s GPS subscription burned power for
|
||||||
// fixes that were thrown away between uploads.
|
// fixes that were thrown away between uploads.
|
||||||
|
|||||||
@@ -50,8 +50,10 @@ public class BootReceiver extends BroadcastReceiver {
|
|||||||
SharedPreferences secure = SecurePrefs.get(context);
|
SharedPreferences secure = SecurePrefs.get(context);
|
||||||
boolean haveCreds = !secure.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
boolean haveCreds = !secure.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
||||||
&& !secure.getString(SecurePrefs.KEY_API_KEY, "").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
|
Log.i(TAG, action + " ignored (enabled=" + enabled
|
||||||
+ " autostart=" + autostart + " credentials=" + haveCreds + ")");
|
+ " autostart=" + autostart + " credentials=" + haveCreds + ")");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private TextInputLayout tokenLayout;
|
private TextInputLayout tokenLayout;
|
||||||
private TextInputEditText tokenInput;
|
private TextInputEditText tokenInput;
|
||||||
private SwitchMaterial serviceSwitch;
|
private SwitchMaterial serviceSwitch;
|
||||||
|
private SwitchMaterial abrpUploadSwitch;
|
||||||
private SwitchMaterial autostartSwitch;
|
private SwitchMaterial autostartSwitch;
|
||||||
private TextView statusText;
|
private TextView statusText;
|
||||||
private Button testButton;
|
private Button testButton;
|
||||||
@@ -250,6 +251,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
tokenLayout = abrpPane.findViewById(R.id.token_layout);
|
tokenLayout = abrpPane.findViewById(R.id.token_layout);
|
||||||
tokenInput = abrpPane.findViewById(R.id.token_input);
|
tokenInput = abrpPane.findViewById(R.id.token_input);
|
||||||
serviceSwitch = servicePane.findViewById(R.id.service_switch);
|
serviceSwitch = servicePane.findViewById(R.id.service_switch);
|
||||||
|
abrpUploadSwitch = servicePane.findViewById(R.id.abrp_upload_switch);
|
||||||
autostartSwitch = servicePane.findViewById(R.id.autostart_switch);
|
autostartSwitch = servicePane.findViewById(R.id.autostart_switch);
|
||||||
statusText = servicePane.findViewById(R.id.status_text);
|
statusText = servicePane.findViewById(R.id.status_text);
|
||||||
testButton = abrpPane.findViewById(R.id.test_button);
|
testButton = abrpPane.findViewById(R.id.test_button);
|
||||||
@@ -275,6 +277,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
apiKeyInput.setText(savedApiKeyOrDefault());
|
apiKeyInput.setText(savedApiKeyOrDefault());
|
||||||
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
||||||
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
||||||
|
abrpUploadSwitch.setChecked(prefs.getBoolean(
|
||||||
|
UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||||
|
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED));
|
||||||
|
|
||||||
autostartSwitch.setChecked(
|
autostartSwitch.setChecked(
|
||||||
prefs.getBoolean(UploadSettings.KEY_AUTOSTART, UploadSettings.DEFAULT_AUTOSTART));
|
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 enabled = prefs.getBoolean("service_enabled", false);
|
||||||
boolean haveCreds = !securePrefs.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
boolean haveCreds = !securePrefs.getString(SecurePrefs.KEY_TOKEN, "").trim().isEmpty()
|
||||||
&& !securePrefs.getString(SecurePrefs.KEY_API_KEY, "").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`
|
// Asked for first, and deliberately: the service declares the `location`
|
||||||
// foreground type, and since API 34 starting it without the permission behind
|
// 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,
|
// that type is a SecurityException in its own onCreate. Started this way round,
|
||||||
@@ -308,7 +315,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (checked) {
|
if (checked) {
|
||||||
String apiKey = textOf(apiKeyInput);
|
String apiKey = textOf(apiKeyInput);
|
||||||
String token = textOf(tokenInput);
|
String token = textOf(tokenInput);
|
||||||
if (apiKey.isEmpty() || token.isEmpty()) {
|
if (abrpUploadSwitch.isChecked() && (apiKey.isEmpty() || token.isEmpty())) {
|
||||||
serviceSwitch.setChecked(false);
|
serviceSwitch.setChecked(false);
|
||||||
if (apiKey.isEmpty()) apiKeyLayout.setError(getString(R.string.api_key_required));
|
if (apiKey.isEmpty()) apiKeyLayout.setError(getString(R.string.api_key_required));
|
||||||
if (token.isEmpty()) tokenLayout.setError(getString(R.string.token_required));
|
if (token.isEmpty()) tokenLayout.setError(getString(R.string.token_required));
|
||||||
@@ -325,6 +332,22 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
refreshStatus();
|
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() {
|
private void showAbout() {
|
||||||
@@ -362,6 +385,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
apiKeyInput.setText(savedApiKeyOrDefault());
|
apiKeyInput.setText(savedApiKeyOrDefault());
|
||||||
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
tokenInput.setText(securePrefs.getString(SecurePrefs.KEY_TOKEN, ""));
|
||||||
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
serviceSwitch.setChecked(prefs.getBoolean("service_enabled", false));
|
||||||
|
abrpUploadSwitch.setChecked(prefs.getBoolean(
|
||||||
|
UploadSettings.KEY_ABRP_UPLOAD_ENABLED,
|
||||||
|
UploadSettings.DEFAULT_ABRP_UPLOAD_ENABLED));
|
||||||
autostartSwitch.setChecked(
|
autostartSwitch.setChecked(
|
||||||
prefs.getBoolean(UploadSettings.KEY_AUTOSTART, UploadSettings.DEFAULT_AUTOSTART));
|
prefs.getBoolean(UploadSettings.KEY_AUTOSTART, UploadSettings.DEFAULT_AUTOSTART));
|
||||||
// Poll state and log only while the screen is up; onPause cancels it.
|
// 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.
|
// force-kill because onDestroy never ran.
|
||||||
UploadLog.State state = AbrpUploadService.state();
|
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) {
|
switch (state) {
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Derived from the log, not from the last status alone: a single failed
|
// 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_BOOST_LOW_SOC = "boost_low_soc";
|
||||||
static final String KEY_LOW_SOC_PERCENT = "low_soc_percent";
|
static final String KEY_LOW_SOC_PERCENT = "low_soc_percent";
|
||||||
static final String KEY_AUTOSTART = "autostart";
|
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
|
* 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.
|
* service that starts itself must also be switchable off.
|
||||||
*/
|
*/
|
||||||
static final boolean DEFAULT_AUTOSTART = true;
|
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
|
* 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 int intervalSec;
|
||||||
final boolean boostLowSoc;
|
final boolean boostLowSoc;
|
||||||
final int lowSocPercent;
|
final int lowSocPercent;
|
||||||
|
final boolean abrpUploadEnabled;
|
||||||
|
|
||||||
UploadSettings(int intervalSec, boolean boostLowSoc, int lowSocPercent) {
|
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.intervalSec = intervalSec;
|
||||||
this.boostLowSoc = boostLowSoc;
|
this.boostLowSoc = boostLowSoc;
|
||||||
this.lowSocPercent = lowSocPercent;
|
this.lowSocPercent = lowSocPercent;
|
||||||
|
this.abrpUploadEnabled = abrpUploadEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UploadSettings from(SharedPreferences prefs) {
|
static UploadSettings from(SharedPreferences prefs) {
|
||||||
return new UploadSettings(
|
return new UploadSettings(
|
||||||
prefs.getInt(KEY_INTERVAL_SEC, DEFAULT_INTERVAL_SEC),
|
prefs.getInt(KEY_INTERVAL_SEC, DEFAULT_INTERVAL_SEC),
|
||||||
prefs.getBoolean(KEY_BOOST_LOW_SOC, DEFAULT_BOOST_LOW_SOC),
|
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() {
|
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: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" />
|
<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/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" />
|
<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" />
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_autostart" android:textAppearance="@style/Text.EV.Secondary" />
|
||||||
</LinearLayout>
|
</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: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" />
|
<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/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" />
|
<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" />
|
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_autostart" android:textAppearance="@style/Text.EV.Secondary" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -74,7 +74,9 @@
|
|||||||
<string name="token_required">Enter your ABRP token first</string>
|
<string name="token_required">Enter your ABRP token first</string>
|
||||||
|
|
||||||
<string name="card_service">Upload Service</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="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>
|
<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_stopped">Stopped</string>
|
||||||
<string name="state_starting">Starting…</string>
|
<string name="state_starting">Starting…</string>
|
||||||
<string name="state_running">Running</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>
|
<string name="state_error">In error — last %1$d uploads failed</string>
|
||||||
|
|
||||||
<!-- Call log -->
|
<!-- Call log -->
|
||||||
|
|||||||
Reference in New Issue
Block a user