Skip to content

Commit 7e74ae6

Browse files
committed
some fixes
1 parent 81714f9 commit 7e74ae6

12 files changed

Lines changed: 299 additions & 12 deletions

File tree

‎README.md‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,72 @@ Community mod for the MG4 EV (AAOS 9, pre-2026 facelift) that replaces the stock
7171
<a href="https://youtu.be/Rzb_Owc_RT0">▶ Full demo on YouTube</a>
7272
</p>
7373

74+
## Quick Guides
75+
76+
<details>
77+
<summary><strong>Indicator Cam</strong></summary>
78+
79+
The indicator camera opens automatically when you activate the left or right turn signal.
80+
81+
To use it:
82+
83+
1. Open `Settings` -> `Signal Camera`.
84+
2. Enable `Overlay on signal`.
85+
3. Optional: enable `Rotate side cameras to driving direction` if you prefer the side cameras to match the direction of travel.
86+
4. Optional: tune `Overlay hide delay` and `Minimum on-time` so the camera does not disappear too abruptly.
87+
5. `Tap to hide` is enabled by default (5 seconds) – one tap dismisses the overlay temporarily, it reappears afterwards if the signal is still active.
88+
89+
Important:
90+
91+
- Disable the OEM SAIC indicator camera popup first, otherwise both systems may compete.
92+
- While the main app is open, the app can route the signal camera into the main preview instead of showing the floating overlay.
93+
94+
</details>
95+
96+
<details>
97+
<summary><strong>Dashcam</strong></summary>
98+
99+
The dashcam records all four factory cameras into one combined clip and can also save dedicated event recordings.
100+
101+
To use it:
102+
103+
1. Open `Settings` -> `Dashcam`.
104+
2. Enable `Dashcam`.
105+
3. Optional: adjust FPS, footer signature, and whether speed should be shown in the recording.
106+
4. Optional: enable OEM coexistence if you want the app to yield camera ownership briefly to the stock 360/reverse system when needed (recommended).
107+
5. Use `Trigger event save` in the app, the hazard-light trigger, or an external broadcast to save an event clip.
108+
109+
Notes:
110+
111+
- One normal rolling clip is 30 seconds long.
112+
- Event saves keep a separate pre/post buffer in the `events/` folder.
113+
- The companion app can trigger an event save externally via `com.drivehub.kamera.action.TRIGGER_DASHCAM_EVENT`.
114+
- If the dashcam is currently off and you still trigger an event, the app can switch into future-only recording so at least the post-trigger window is captured.
115+
116+
</details>
117+
118+
<details>
119+
<summary><strong>Maneuver Mode</strong></summary>
120+
121+
Maneuver Mode is the persistent rear camera overlay, similar to a digital rearview mirror.
122+
123+
To use it:
124+
125+
1. Open `Settings` -> `Maneuver Mode`.
126+
2. Enable `Digital rearview`.
127+
3. The rear camera will stay visible as a floating window when no higher-priority signal overlay is active.
128+
4. You can drag and resize the overlay, and the app restores the last layout automatically.
129+
5. `Tap to temporarily hide` is enabled by default (5 seconds) – one tap dismisses it and it reappears after the set duration.
130+
6. The "X" in the preview will close it permanently until turned back on.
131+
132+
Behavior:
133+
134+
- Reverse gear still has priority and follows the OEM/main-screen flow.
135+
- Turn-signal cameras temporarily override Maneuver Mode and the rearview returns afterwards.
136+
- The digital rearview can also be toggled by the separate companion trigger app.
137+
138+
</details>
139+
74140

75141
## OEM SAIC 360Cam Setup
76142

‎app/build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ android {
1414
applicationId "com.drivehub.kamera"
1515
minSdk 28
1616
targetSdk 36
17-
versionCode 6
17+
versionCode 7
1818
versionName "0.8.4"
1919
buildConfigField "boolean", "IS_BETA", "true"
2020

‎app/src/main/java/com/drivehub/kamera/MainActivity.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ protected void onStop() {
220220
super.onStop();
221221
sMainVisible = false;
222222
sSettingsDialogOpen = false;
223+
// Re-apply signal/rearview overlay state once MainActivity stops blocking it.
224+
SignalService.requestRecheck();
223225
otaController.stop();
224226
try {
225227
unregisterReceiver(cameraRouteReceiver);

‎app/src/main/java/com/drivehub/kamera/camera/OverlayService.java‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,14 @@ public void onScaleEnd(ScaleGestureDetector detector) {
295295
float tapDx = event.getRawX() - initialTouchX;
296296
float tapDy = event.getRawY() - initialTouchY;
297297
boolean isTap = (tapDx * tapDx + tapDy * tapDy) < (float) (dpToPx(12) * dpToPx(12));
298-
if (isTap
299-
&& OVERLAY_REASON_DIGITAL_REARVIEW.equals(overlayReason)
300-
&& uiPrefs != null
301-
&& UiPrefs.isDigitalRearviewTapToHideEnabled(uiPrefs)) {
302-
SignalService.startRearviewTempHide(OverlayService.this);
298+
if (isTap && uiPrefs != null) {
299+
if (OVERLAY_REASON_DIGITAL_REARVIEW.equals(overlayReason)
300+
&& UiPrefs.isDigitalRearviewTapToHideEnabled(uiPrefs)) {
301+
SignalService.startRearviewTempHide(OverlayService.this);
302+
} else if (OVERLAY_REASON_SIGNAL.equals(overlayReason)
303+
&& UiPrefs.isSignalOverlayTapToHideEnabled(uiPrefs)) {
304+
SignalService.startSignalTempHide(OverlayService.this);
305+
}
303306
}
304307
v.performClick();
305308
return true;

‎app/src/main/java/com/drivehub/kamera/camera/TileViewActivity.java‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.drivehub.kamera.R;
55

66
import com.drivehub.kamera.settings.UiPrefs;
7+
import com.drivehub.kamera.signal.SignalService;
78

89
import android.graphics.drawable.GradientDrawable;
910
import android.os.Bundle;
@@ -17,6 +18,12 @@
1718

1819
public class TileViewActivity extends AppCompatActivity {
1920

21+
private static volatile boolean sTileViewVisible = false;
22+
23+
public static boolean isVisible() {
24+
return sTileViewVisible;
25+
}
26+
2027
private static final int[] SURFACE_IDS = { R.id.sfFront, R.id.sfRight, R.id.sfLeft, R.id.sfRear };
2128
private static final int[] TILE_IDS = { R.id.tileFront, R.id.tileRight, R.id.tileLeft, R.id.tileRear };
2229
private static final int[] CAMERA_INDICES = {
@@ -92,12 +99,19 @@ private void applyCornerRadiusToLaidOutViews(View container) {
9299
@Override
93100
protected void onStart() {
94101
super.onStart();
102+
sTileViewVisible = true;
103+
OverlayService.hideOverlay(this);
104+
// Reset SignalService internal state so currentMode doesn't stay at 4
105+
// and the later onStop() recheck can actually re-evaluate.
106+
SignalService.requestRecheck();
95107
prefs.registerOnSharedPreferenceChangeListener(prefListener);
96108
}
97109

98110
@Override
99111
protected void onStop() {
112+
sTileViewVisible = false;
100113
prefs.unregisterOnSharedPreferenceChangeListener(prefListener);
114+
SignalService.requestRecheck();
101115
super.onStop();
102116
}
103117

‎app/src/main/java/com/drivehub/kamera/settings/SettingsDialogController.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ private Views bindViews(SharedPreferences prefs) {
176176
v.etOverlayHideDelayValue = dialog.findViewById(R.id.etOverlayHideDelayValue);
177177
v.seekOverlayMinShow = dialog.findViewById(R.id.seekOverlayMinShow);
178178
v.etOverlayMinShowValue = dialog.findViewById(R.id.etOverlayMinShowValue);
179+
v.swSignalTapToHide = dialog.findViewById(R.id.switchSignalTapToHide);
180+
v.etSignalTapToHideDurationSec = dialog.findViewById(R.id.etSignalTapToHideDurationSec);
179181
v.etDashcamFps = dialog.findViewById(R.id.etDashcamFps);
180182
v.etDashcamSignature = dialog.findViewById(R.id.etDashcamSignature);
181183
v.swDashcamShowSpeed = dialog.findViewById(R.id.switchDashcamShowSpeed);
@@ -286,6 +288,8 @@ private void wireSubControllers(SharedPreferences prefs) {
286288
views.swDigitalRearview,
287289
views.swRearviewTapToHide,
288290
views.etRearviewTapToHideDurationSec,
291+
views.swSignalTapToHide,
292+
views.etSignalTapToHideDurationSec,
289293
views.swRotateToDrivingDirection,
290294
views.seekOverlayHideDelay,
291295
views.etOverlayHideDelayValue,
@@ -354,6 +358,7 @@ private void wireAppearance(SharedPreferences prefs) {
354358
views.swOverlay,
355359
views.swDigitalRearview,
356360
views.swRearviewTapToHide,
361+
views.swSignalTapToHide,
357362
views.swRotateToDrivingDirection,
358363
views.swDashcamEnabled,
359364
views.swDashcamShowSpeed,
@@ -548,6 +553,8 @@ private static final class Views {
548553
Switch swDigitalRearview;
549554
Switch swRearviewTapToHide;
550555
EditText etRearviewTapToHideDurationSec;
556+
Switch swSignalTapToHide;
557+
EditText etSignalTapToHideDurationSec;
551558
Switch swRotateToDrivingDirection;
552559
Switch swDashcamEnabled;
553560
Switch swSafetyWarning;

‎app/src/main/java/com/drivehub/kamera/settings/UiPrefs.java‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ public final class UiPrefs {
1717
public static final String KEY_DIGITAL_REARVIEW_ENABLED = "digitalRearviewEnabled";
1818
public static final String KEY_DIGITAL_REARVIEW_TAP_TO_HIDE_ENABLED = "digitalRearviewTapToHideEnabled";
1919
public static final String KEY_DIGITAL_REARVIEW_TAP_TO_HIDE_DURATION_SEC = "digitalRearviewTapToHideDurationSec";
20-
public static final int DEFAULT_DIGITAL_REARVIEW_TAP_TO_HIDE_DURATION_SEC = 30;
20+
public static final int DEFAULT_DIGITAL_REARVIEW_TAP_TO_HIDE_DURATION_SEC = 5;
2121
public static final int MIN_DIGITAL_REARVIEW_TAP_TO_HIDE_SEC = 5;
2222
public static final int MAX_DIGITAL_REARVIEW_TAP_TO_HIDE_SEC = 300;
23+
public static final String KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_ENABLED = "signalOverlayTapToHideEnabled";
24+
public static final String KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_DURATION_SEC = "signalOverlayTapToHideDurationSec";
25+
public static final int DEFAULT_SIGNAL_OVERLAY_TAP_TO_HIDE_DURATION_SEC = 5;
26+
public static final int MIN_SIGNAL_OVERLAY_TAP_TO_HIDE_SEC = 3;
27+
public static final int MAX_SIGNAL_OVERLAY_TAP_TO_HIDE_SEC = 120;
2328
public static final String KEY_OVERLAY_HIDE_DELAY_MS = "overlayHideDelayMs";
2429
public static final String KEY_OVERLAY_MIN_SHOW_MS = "overlayMinShowMs";
2530
public static final String KEY_DEV_OVERLAY_TOP_INSET_PX = "devOverlayTopInsetPx";
@@ -104,7 +109,7 @@ public static void setDigitalRearviewEnabled(SharedPreferences prefs, boolean en
104109
}
105110

106111
public static boolean isDigitalRearviewTapToHideEnabled(SharedPreferences prefs) {
107-
return prefs.getBoolean(KEY_DIGITAL_REARVIEW_TAP_TO_HIDE_ENABLED, false);
112+
return prefs.getBoolean(KEY_DIGITAL_REARVIEW_TAP_TO_HIDE_ENABLED, true);
108113
}
109114

110115
public static int getDigitalRearviewTapToHideDurationSec(SharedPreferences prefs) {
@@ -118,6 +123,21 @@ public static int clampRearviewTapToHideDurationSec(int value) {
118123
Math.min(MAX_DIGITAL_REARVIEW_TAP_TO_HIDE_SEC, value));
119124
}
120125

126+
public static boolean isSignalOverlayTapToHideEnabled(SharedPreferences prefs) {
127+
return prefs.getBoolean(KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_ENABLED, true);
128+
}
129+
130+
public static int getSignalOverlayTapToHideDurationSec(SharedPreferences prefs) {
131+
return clampSignalTapToHideDurationSec(
132+
prefs.getInt(KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_DURATION_SEC,
133+
DEFAULT_SIGNAL_OVERLAY_TAP_TO_HIDE_DURATION_SEC));
134+
}
135+
136+
public static int clampSignalTapToHideDurationSec(int value) {
137+
return Math.max(MIN_SIGNAL_OVERLAY_TAP_TO_HIDE_SEC,
138+
Math.min(MAX_SIGNAL_OVERLAY_TAP_TO_HIDE_SEC, value));
139+
}
140+
121141
public static boolean isDashcamEnabled(SharedPreferences prefs) {
122142
return prefs.getBoolean(DashcamSettingsController.KEY_ENABLED, false);
123143
}

‎app/src/main/java/com/drivehub/kamera/signal/SignalCameraSettingsController.java‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public void bind(
2626
Switch swDigitalRearview,
2727
Switch swRearviewTapToHide,
2828
EditText etRearviewTapToHideDurationSec,
29+
Switch swSignalTapToHide,
30+
EditText etSignalTapToHideDurationSec,
2931
Switch swRotateToDrivingDirection,
3032
SeekBar seekOverlayHideDelay,
3133
EditText etOverlayHideDelayValue,
@@ -81,6 +83,37 @@ public void afterTextChanged(android.text.Editable s) {
8183
});
8284
}
8385

86+
if (swSignalTapToHide != null) {
87+
swSignalTapToHide.setChecked(UiPrefs.isSignalOverlayTapToHideEnabled(prefs));
88+
swSignalTapToHide.setOnCheckedChangeListener((btn, checked) ->
89+
prefs.edit().putBoolean(UiPrefs.KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_ENABLED, checked).apply());
90+
}
91+
92+
if (etSignalTapToHideDurationSec != null) {
93+
int saved = UiPrefs.getSignalOverlayTapToHideDurationSec(prefs);
94+
etSignalTapToHideDurationSec.setText(String.valueOf(saved));
95+
etSignalTapToHideDurationSec.setSelection(etSignalTapToHideDurationSec.getText().length());
96+
etSignalTapToHideDurationSec.addTextChangedListener(new SimpleTextWatcher() {
97+
@Override
98+
public void afterTextChanged(android.text.Editable s) {
99+
if (s == null) return;
100+
String text = s.toString().trim();
101+
if (text.isEmpty()) return;
102+
try {
103+
int v = UiPrefs.clampSignalTapToHideDurationSec(Integer.parseInt(text));
104+
prefs.edit().putInt(UiPrefs.KEY_SIGNAL_OVERLAY_TAP_TO_HIDE_DURATION_SEC, v).apply();
105+
} catch (NumberFormatException ignored) {
106+
}
107+
}
108+
});
109+
etSignalTapToHideDurationSec.setOnFocusChangeListener((v, hasFocus) -> {
110+
if (hasFocus) return;
111+
int clamped = UiPrefs.getSignalOverlayTapToHideDurationSec(prefs);
112+
etSignalTapToHideDurationSec.setText(String.valueOf(clamped));
113+
etSignalTapToHideDurationSec.setSelection(etSignalTapToHideDurationSec.getText().length());
114+
});
115+
}
116+
84117
if (swRotateToDrivingDirection != null) {
85118
swRotateToDrivingDirection.setChecked(
86119
UiPrefs.isOverlayRotationToDrivingDirectionEnabled(prefs)

0 commit comments

Comments
 (0)