App 2.17.1: tidier Settings and Logs

- Settings: the Wi-Fi and saved-networks cards are gone, and the rest
  sits in three columns (display and steering wheel | battery |
  charging price and app) instead of one tall column. The background
  Wi-Fi auto-connect stays on, without a switch.
- Logs: only the upload log. The steering-key reports, the car-colour
  probe and the screen line answered their questions and are removed,
  with their code (CarColorProbe, the key-report log) and strings.
- README lists the current tabs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
2026-10-18 20:32:01 +02:00
co-authored by Claude Opus 5.5
parent 8d3eb80f66
commit 851a4a34d4
14 changed files with 24 additions and 298 deletions
+2 -2
View File
@@ -34,8 +34,8 @@ android {
applicationId "com.stinnesbeck.nilsmg4"
minSdk 27
targetSdk 36
versionCode 89
versionName "2.17.0"
versionCode 90
versionName "2.17.1"
// Nothing about the server ships in the APK: its URL and ingest token are entered in
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
@@ -1,59 +0,0 @@
package com.evsuite.abrp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Looks for the car's paint colour among the head unit's system properties, for the Logs tab.
*
* The MG launcher draws the car in its own colour, so the head unit knows it somewhere; where is
* not documented. This lists every property whose name or value mentions a colour or paint, so
* a photo of the Logs tab shows whether (and how) it can be read. Read-only: it runs the
* platform's own getprop, which only reads.
*/
final class CarColorProbe {
private static final Pattern LINE = Pattern.compile("^\\[([^\\]]*)\\]: \\[(.*)\\]$");
private static final Pattern INTERESTING = Pattern.compile(
"(?i)colou?r|paint|body_?col|exterior|car_?model|vehicle_?(config|type|model)");
private CarColorProbe() { }
/** getprop's output, filtered; at most {@code max} lines. Never throws. */
static List<String> run(int max) {
try {
Process p = new ProcessBuilder("getprop").redirectErrorStream(true).start();
StringBuilder out = new StringBuilder();
try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = r.readLine()) != null && out.length() < 512 * 1024) out.append(line).append('\n');
}
p.waitFor();
return filter(out.toString(), max);
} catch (Exception e) {
List<String> failed = new ArrayList<>();
failed.add("getprop failed: " + e.getClass().getSimpleName());
return failed;
}
}
/** The "name = value" lines whose name or value looks colour- or model-related. Pure. */
static List<String> filter(String getpropOutput, int max) {
List<String> found = new ArrayList<>();
for (String line : getpropOutput.split("\n")) {
Matcher m = LINE.matcher(line.trim());
if (!m.matches()) continue;
String name = m.group(1), value = m.group(2);
if (INTERESTING.matcher(name).find() || INTERESTING.matcher(value).find()) {
found.add(name + " = " + value);
if (found.size() >= max) break;
}
}
return found;
}
}
@@ -35,7 +35,11 @@ import com.evsuite.hardware.telemetry.EnergyTelemetryReader;
public class MainActivity extends AppCompatActivity {
/** Shared with {@link AbrpUploadService}, which reads it on every tick. */
/**
* Rejoin a saved network (the phone hotspot) in the background; read by
* {@link AbrpUploadService} on every tick. On by default; the Wi-Fi card with its switch was
* removed from Settings (2.17.1), so it now stays on.
*/
static final String WIFI_AUTO_KEY = "wifi_auto_connect";
private static final String REPOSITORY_URL = "https://git.stinnesbeck.com/nils/mg4";
@@ -76,9 +80,6 @@ public class MainActivity extends AppCompatActivity {
/** The pages in navigation order. Parallel to {@link #TAB_IDS}. */
private View[] panes;
/** Wi-Fi page. The helper is the same one the upload service uses on its own tick. */
private WifiAutoConnect wifi;
private TextView wifiSsid, wifiState, wifiSavedList;
/**
* Value cells of the Vehicle page, looked up once and refreshed on the UI tick.
@@ -126,7 +127,6 @@ public class MainActivity extends AppCompatActivity {
/** Upload page: live telemetry switch and cadence. */
private SwitchMaterial liveTelemetrySwitch, boostSwitch, voiceKeySwitch, fullScreenSwitch;
private TextView steeringKeysText;
private com.google.android.material.textfield.MaterialAutoCompleteTextView intervalChoices;
private TextInputLayout lowSocLayout;
private TextInputEditText lowSocInput;
@@ -215,10 +215,8 @@ public class MainActivity extends AppCompatActivity {
@Override public void run() {
refreshStatus();
refreshCallLog();
refreshSteeringKeys();
sampleTrackers();
refreshConsumption();
refreshWifi();
uiHandler.postDelayed(this, 2_000L);
}
};
@@ -254,22 +252,12 @@ public class MainActivity extends AppCompatActivity {
bindVehiclePane();
bindConsumptionPane();
bindChargingPane();
bindWifiPane();
bindServerPane();
bindServicePane();
requestLocationPermissionIfNeeded();
statusText = servicePane.findViewById(R.id.status_text);
callLogText = logPane.findViewById(R.id.call_log_text);
steeringKeysText = logPane.findViewById(R.id.steering_keys_text);
TextView carColorText = logPane.findViewById(R.id.car_color_text);
showScreenInfo(logPane.findViewById(R.id.screen_text));
logPane.findViewById(R.id.car_color_button).setOnClickListener(v -> new Thread(() -> {
java.util.List<String> found = CarColorProbe.run(60);
String shown = found.isEmpty() ? getString(R.string.car_color_none)
: android.text.TextUtils.join("\n", found);
runOnUiThread(() -> carColorText.setText(shown));
}, "car-color-probe").start());
logPane.findViewById(R.id.flush_now_button).setOnClickListener(v -> manualFlush());
setUpPager();
@@ -292,21 +280,6 @@ public class MainActivity extends AppCompatActivity {
startForegroundService(new Intent(this, AbrpUploadService.class));
}
/**
* What the head unit reports about its screen, for the Logs tab: the panel in pixels and its
* density, and this app's window in pixels and in dp, which is what layouts are chosen by.
* Sources disagree on the MG4's numbers (1920×720, 1280×480, a 1778×720 window).
*/
@SuppressWarnings("deprecation") // getRealMetrics: the WindowMetrics API starts at 30; this is 28
private void showScreenInfo(TextView view) {
android.util.DisplayMetrics panel = new android.util.DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(panel);
android.util.DisplayMetrics window = getResources().getDisplayMetrics();
android.content.res.Configuration config = getResources().getConfiguration();
view.setText(getString(R.string.screen_info, panel.widthPixels, panel.heightPixels, panel.densityDpi,
window.widthPixels, window.heightPixels, config.screenWidthDp, config.screenHeightDp));
}
/**
* Shows a dialog without bringing the car's bars back. A dialog is a window of its own, and
* the system shows the bars when a window without the full-screen flags takes focus. So it
@@ -1224,45 +1197,6 @@ public class MainActivity extends AppCompatActivity {
}
}
// ---------- Wi-Fi page ----------
private void bindWifiPane() {
wifi = new WifiAutoConnect(getApplicationContext());
wifiSsid = settingsPane.findViewById(R.id.wifi_ssid);
wifiState = settingsPane.findViewById(R.id.wifi_state);
wifiSavedList = settingsPane.findViewById(R.id.wifi_saved_list);
SwitchMaterial auto = settingsPane.findViewById(R.id.wifi_auto_switch);
auto.setChecked(prefs.getBoolean(WIFI_AUTO_KEY, true));
auto.setOnCheckedChangeListener((btn, checked) ->
prefs.edit().putBoolean(WIFI_AUTO_KEY, checked).apply());
settingsPane.findViewById(R.id.wifi_connect_button).setOnClickListener(v -> {
// force: the driver is asking now, so the rate limit does not apply.
WifiAutoConnect.Result r = wifi.ensureConnected(true);
wifiState.setText(r.message);
refreshWifi();
});
}
private void refreshWifi() {
if (wifi == null) return;
String ssid = wifi.currentSsid();
wifiSsid.setText(ssid == null ? getString(R.string.wifi_not_connected) : ssid);
if (ssid != null) {
wifiState.setText(R.string.wifi_connected);
} else if (!wifi.isWifiEnabled()) {
wifiState.setText(R.string.wifi_off);
}
// Left alone otherwise: a message the button just set says more about what is
// happening than "not connected" would.
java.util.List<String> saved = wifi.savedNetworkNames();
wifiSavedList.setText(saved.isEmpty()
? getString(R.string.wifi_saved_empty)
: android.text.TextUtils.join("\n", saved));
}
// ---------- Vehicle page ----------
/** Looks up the value cells once; the labels are static and never touched from code. */
@@ -1752,15 +1686,6 @@ public class MainActivity extends AppCompatActivity {
}, "cloud-refresh").start();
}
/** What the car's steering-wheel key broadcasts looked like, newest first. */
private void refreshSteeringKeys() {
if (steeringKeysText == null) return;
java.util.List<String> keys = SteeringKeyListener.recent();
String text = keys.isEmpty() ? getString(R.string.steering_keys_empty)
: android.text.TextUtils.join("\n", keys);
if (!text.contentEquals(steeringKeysText.getText())) steeringKeysText.setText(text);
}
private void refreshCallLog() {
java.util.List<UploadLog.Entry> entries = AbrpUploadService.log().recent();
if (entries.isEmpty()) {
@@ -9,20 +9,12 @@ import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* Opens the app on a double press of the steering wheel's voice key.
*
* The head unit reports steering-wheel keys as the broadcast {@link #ACTION}; code 287 is the
* voice key (see EVHardware's PhysicalButtonEventDecoder). The extras' format was read off the
* car (see {@link SteeringKeyReport}); every report is still kept raw for the Logs tab, in case
* another firmware sends them differently.
* car (see {@link SteeringKeyReport}).
*
* Registered by the always-on service on the main thread; never throws into the head unit.
*/
@@ -31,9 +23,6 @@ final class SteeringKeyListener {
static final String ACTION = "com.saic.keyevent.hardkey.report";
static final int VOICE_KEY = 287;
private static final String TAG = "NilsMG4.SteeringKey";
private static final int MAX_LOG = 20;
private static final ArrayDeque<String> RECENT = new ArrayDeque<>();
private final Context context;
private final SharedPreferences prefs;
@@ -79,18 +68,6 @@ final class SteeringKeyListener {
registered = false;
}
/** The last broadcasts, newest first, for the Logs tab. */
static synchronized List<String> recent() {
List<String> out = new ArrayList<>(RECENT);
java.util.Collections.reverse(out);
return out;
}
private static synchronized void remember(String line) {
if (RECENT.size() >= MAX_LOG) RECENT.removeFirst();
RECENT.addLast(line);
}
private void handle(Intent intent) {
Bundle extras = intent.getExtras();
SteeringKeyReport key = read(extras);
@@ -98,11 +75,6 @@ final class SteeringKeyListener {
if (key.code != null && UploadSettings.voiceKeyOpensApp(prefs)) {
opens = detector.accept(key.code, key.down, key.longPress, android.os.SystemClock.elapsedRealtime());
}
remember(new SimpleDateFormat("HH:mm:ss.SSS", Locale.US).format(new Date())
+ " " + describe(extras)
+ "\n -> code " + (key.code == null ? "?" : key.code)
+ ", down " + (key.down == null ? "?" : key.down)
+ ", long " + key.longPress + (opens ? " OPENS APP" : ""));
if (opens) {
try {
context.startActivity(new Intent(context, MainActivity.class)
@@ -129,17 +101,4 @@ final class SteeringKeyListener {
}
return SteeringKeyReport.parse(values);
}
/** All extras as name=value(type), so the Logs tab shows the real format. */
static String describe(Bundle extras) {
if (extras == null || extras.isEmpty()) return "(no extras)";
StringBuilder sb = new StringBuilder();
for (String k : extras.keySet()) {
Object v = extras.get(k);
if (sb.length() > 0) sb.append(", ");
sb.append(k).append('=').append(v).append(" (")
.append(v == null ? "null" : v.getClass().getSimpleName()).append(')');
}
return sb.toString();
}
}
@@ -58,34 +58,6 @@ final class WifiAutoConnect {
}
}
boolean isWifiEnabled() {
try {
return wifi != null && wifi.isWifiEnabled();
} catch (Throwable t) {
return false;
}
}
/** Saved network names, for the UI to show what it can reach. Empty if the OS refuses. */
List<String> savedNetworkNames() {
java.util.List<String> names = new java.util.ArrayList<>();
try {
if (wifi == null) return names;
List<WifiConfiguration> saved = wifi.getConfiguredNetworks();
if (saved == null) return names;
for (WifiConfiguration c : saved) {
if (c == null || c.SSID == null) continue;
String name = c.SSID.replace("\"", "").trim();
if (!name.isEmpty() && !names.contains(name)) names.add(name);
}
} catch (SecurityException e) {
Log.w(TAG, "Saved networks unavailable: permission denied");
} catch (Throwable t) {
Log.w(TAG, "getConfiguredNetworks refused: " + t.getMessage());
}
return names;
}
/**
* One attempt to get onto a saved network, rate-limited.
*
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<com.evsuite.abrp.StableScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:clipToPadding="false">
<!-- Three columns: display and steering wheel | battery | charging price and the app. -->
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="24dp" android:baselineAligned="false">
<LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginEnd="16dp">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass">
@@ -17,7 +18,9 @@
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/accent_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
</LinearLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginEnd="16dp">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_battery_settings_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/consumption_soh_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="@string/settings_manual_soh" app:suffixText="@string/unit_percent">
<com.google.android.material.textfield.TextInputEditText android:id="@+id/consumption_soh_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="5" android:minHeight="72dp"/>
@@ -30,7 +33,9 @@
<com.google.android.material.button.MaterialButton android:id="@+id/usable_capacity_save" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="72dp" android:layout_marginTop="8dp" android:text="@string/btn_save_capacity"/>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/helper_usable_capacity" android:textAppearance="@style/Text.EV.Secondary"/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
</LinearLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_price_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/charge_price_layout" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="@string/settings_unit_price" app:suffixText="@string/unit_eur_per_kwh">
<com.google.android.material.textfield.TextInputEditText android:id="@+id/charge_price_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:maxLength="10" android:minHeight="72dp"/>
@@ -39,20 +44,6 @@
<com.google.android.material.button.MaterialButton android:id="@+id/settings_phone_button" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/btn_phone_settings" android:layout_marginTop="8dp" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/hint_phone_settings" android:textAppearance="@style/Text.EV.Secondary" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_card_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/wifi_ssid" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/no_value" android:textAppearance="@style/Text.EV.Metric" android:layout_marginTop="20dp" />
<TextView android:id="@+id/wifi_state" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/no_value" android:textAppearance="@style/Text.EV.Secondary" android:layout_marginTop="12dp" />
<com.google.android.material.button.MaterialButton android:id="@+id/wifi_connect_button" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_connect_now" android:layout_marginTop="24dp" />
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/wifi_auto_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/wifi_auto_label" 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/wifi_auto_hint" android:textAppearance="@style/Text.EV.Secondary" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_saved_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/wifi_saved_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:textAppearance="@style/Text.EV.Body" android:lineSpacingExtra="16dp" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_app_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/settings_version" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:textAppearance="@style/Text.EV.Body" />
-9
View File
@@ -4,14 +4,5 @@
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_call_log" android:textAppearance="@style/Text.EV.Eyebrow" />
<com.google.android.material.button.MaterialButton android:id="@+id/flush_now_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/btn_flush_now" app:icon="@drawable/ic_refresh" app:iconGravity="textStart" style="@style/Widget.EV.Button.Outlined" xmlns:app="http://schemas.android.com/apk/res-auto" />
<TextView android:id="@+id/call_log_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:minHeight="180dp" android:text="@string/call_log_empty" android:textAppearance="@style/Text.EV.Body" android:fontFamily="monospace" android:textSize="17sp" android:lineSpacingExtra="12dp" android:textIsSelectable="true" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/label_steering_keys" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/hint_steering_keys" android:textAppearance="@style/Text.EV.Secondary" />
<TextView android:id="@+id/steering_keys_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="@string/steering_keys_empty" android:textAppearance="@style/Text.EV.Body" android:fontFamily="monospace" android:textSize="14sp" android:lineSpacingExtra="4dp" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/label_car_color" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/hint_car_color" android:textAppearance="@style/Text.EV.Secondary" />
<com.google.android.material.button.MaterialButton android:id="@+id/car_color_button" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="@string/btn_car_color" />
<TextView android:id="@+id/car_color_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:textAppearance="@style/Text.EV.Body" android:fontFamily="monospace" android:textSize="14sp" android:lineSpacingExtra="4dp" android:textIsSelectable="true" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/label_screen" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/screen_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/no_value" android:textAppearance="@style/Text.EV.Body" android:fontFamily="monospace" android:textSize="14sp" android:textIsSelectable="true" />
</LinearLayout>
</com.evsuite.abrp.StableScrollView>
-12
View File
@@ -38,18 +38,6 @@
<com.google.android.material.button.MaterialButton android:id="@+id/settings_phone_button" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/btn_phone_settings" android:layout_marginTop="8dp" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/hint_phone_settings" android:textAppearance="@style/Text.EV.Secondary" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_card_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/wifi_ssid" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/no_value" android:textAppearance="@style/Text.EV.Metric" android:layout_marginTop="20dp" />
<TextView android:id="@+id/wifi_state" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/no_value" android:textAppearance="@style/Text.EV.Secondary" android:layout_marginTop="12dp" />
<com.google.android.material.button.MaterialButton android:id="@+id/wifi_connect_button" style="@style/Widget.EV.Button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_connect_now" android:layout_marginTop="24dp" />
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/wifi_auto_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/wifi_auto_label" 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/wifi_auto_hint" android:textAppearance="@style/Text.EV.Secondary" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/wifi_saved_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/wifi_saved_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:textAppearance="@style/Text.EV.Body" android:lineSpacingExtra="16dp" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_app_title" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:id="@+id/settings_version" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:textAppearance="@style/Text.EV.Body" />
-21
View File
@@ -14,16 +14,6 @@
<string name="tab_settings">Settings</string>
<string name="tab_log">Logs</string>
<!-- Wi-Fi page -->
<string name="wifi_card_title">WI-FI</string>
<string name="wifi_current">Connected network</string>
<string name="wifi_state">Status</string>
<string name="wifi_connect_now">Connect Now</string>
<string name="wifi_auto_label">Auto-connect in the background</string>
<string name="wifi_auto_hint">While the upload service is running, it tries to reconnect to saved networks on its own when the connection drops.</string>
<string name="wifi_saved_title">SAVED NETWORKS</string>
<string name="wifi_saved_empty">Could not read saved networks</string>
<string name="wifi_not_connected">Not connected</string>
<!-- Vehicle page -->
<string name="vehicle_live_data">Live Vehicle Data</string>
@@ -40,12 +30,6 @@
<string name="power_waiting">needs a minute of data</string>
<string name="label_tire_unit">Tyre pressure unit</string>
<string name="label_accent">Accent colour</string>
<string name="label_screen">SCREEN</string>
<string name="screen_info">Panel %1$d × %2$d px at %3$d dpi\nApp window %4$d × %5$d px = %6$d × %7$d dp</string>
<string name="label_car_color">CAR COLOUR</string>
<string name="hint_car_color">Lists the head unit\'s settings that mention a colour, paint or car model, to find out whether the car\'s colour can be read. A photo of this list helps.</string>
<string name="btn_car_color">Look for the car colour</string>
<string name="car_color_none">Nothing colour-related found</string>
<string name="energy_kwh">%1$.1f kWh</string>
<string name="energy_trip_note">net, after recuperation</string>
<string name="energy_trip_waiting">once the car is on</string>
@@ -134,9 +118,6 @@
<string name="hint_full_screen">Hides the car\'s top and bottom bars while this app is open. Swipe in from the top or bottom edge to show them briefly, e.g. for the climate controls.</string>
<string name="label_voice_key">Double-press the voice key to open this app</string>
<string name="hint_voice_key">Press the voice key on the steering wheel twice quickly. The voice assistant may still react to the presses.</string>
<string name="label_steering_keys">Steering-wheel keys</string>
<string name="hint_steering_keys">The last key reports the car sent, newest first. If double-pressing the voice key does not open the app, a photo of this list shows how the car reports it.</string>
<string name="steering_keys_empty">No key reports received yet. Press a steering-wheel key.</string>
<string name="label_abrp_upload_enabled">Send live data</string>
<string name="hint_abrp_upload_enabled">To your server, which stores it, and straight to ABRP when the ABRP credentials below are set. Consumption and charging tracking keep running when this is off.</string>
<string name="hint_abrp_direct">The car sends live data to ABRP itself with your ABRP API key and user token. Without them, ABRP gets no live data; your server only stores it.</string>
@@ -260,8 +241,6 @@
<string name="settings_unit_price">Unit price</string>
<string name="unit_eur_per_kwh">€/kWh</string>
<string name="settings_save_price">Save price</string>
<string name="wifi_connected">Connected ♥</string>
<string name="wifi_off">Wi-Fi off</string>
<string name="trip_reset_title">Reset %1$s?</string>
<string name="trip_reset_message">This counter\'s recorded consumption history will be permanently deleted.</string>
<string name="trip_reset_confirm">Reset</string>
+1 -1
View File
@@ -12,7 +12,7 @@
<string name="design_service_title">Live data.</string>
<string name="design_service_subtitle">Where your car\'s live data goes, and how often.</string>
<string name="design_settings_title">Settings.</string>
<string name="design_settings_subtitle">Display, battery, charging price, Wi-Fi and updates.</string>
<string name="design_settings_subtitle">Display, battery, charging price and updates.</string>
<string name="design_log_title">Every upload, right here.</string>
<string name="design_log_subtitle">Status and details of recent uploads.</string>
<string name="design_battery">BATTERY</string>
@@ -1,24 +0,0 @@
package com.evsuite.abrp;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import org.junit.Test;
/** Picking colour-related system properties out of getprop's output — pure JVM. */
public class CarColorProbeTest {
@Test
public void onlyColourOrModelRelatedPropertiesAreListed() {
String getprop = "[ro.build.version.sdk]: [28]\n"
+ "[persist.saic.vehicle.color]: [3]\n"
+ "[ro.product.model]: [EH32]\n"
+ "[persist.car.bodyCol]: [RED]\n"
+ "[sys.launcher.car_model]: [mg4_red.glb]\n"
+ "garbage line\n";
assertEquals(Arrays.asList("persist.saic.vehicle.color = 3", "persist.car.bodyCol = RED",
"sys.launcher.car_model = mg4_red.glb"), CarColorProbe.filter(getprop, 50));
assertEquals(1, CarColorProbe.filter(getprop, 1).size());
}
}