App 2.6.0: floating button to open the app
The MG4's launcher does not list third-party apps, so the app could only be opened by reinstalling it. Now a small round MG-red button floats over the car's screens: tap opens the app, drag moves it (the position is kept and clamped to the screen), and it hides while the app itself is open. A switch in the Upload tab turns it off. The always-on service owns the overlay, so the button is there from boot. It needs the overlay permission (SYSTEM_ALERT_WINDOW), which the car build has through the system UID; without it, or if the window manager refuses, the button stays away and nothing crashes, and the Upload tab offers the system permission screen. Tested on an Android 9 AOSP emulator at the head unit's 1920x1080 / 160 dpi with the car APK (installs as UID 1000): button appears over the home screen, tap opens the app, hidden while open, drag moves it without opening the app, position survives a force-stop, the switch works through the UI. FloatingButtonGeometry has 3 unit tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package com.evsuite.abrp;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/** The floating button's position and tap rules — pure JVM. */
|
||||
public class FloatingButtonGeometryTest {
|
||||
|
||||
@Test
|
||||
public void startsAtTheRightEdgeAboutFortyPercentDown() {
|
||||
// 1920 x 1080 head unit, 64 px button, 16 px margin.
|
||||
assertArrayEquals(new int[]{1840, 432}, FloatingButtonGeometry.defaultPosition(1920, 1080, 64, 16));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staysFullyOnScreen() {
|
||||
assertEquals(0, FloatingButtonGeometry.clamp(-50, 64, 1920));
|
||||
assertEquals(1856, FloatingButtonGeometry.clamp(5000, 64, 1920));
|
||||
assertEquals(700, FloatingButtonGeometry.clamp(700, 64, 1920));
|
||||
// A saved position from a larger screen still lands inside a smaller one.
|
||||
assertEquals(720 - 64, FloatingButtonGeometry.clamp(1000, 64, 720));
|
||||
// A screen smaller than the button pins it to the corner instead of going negative.
|
||||
assertEquals(0, FloatingButtonGeometry.clamp(10, 64, 40));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aTouchWithinTheSlopIsATapAnythingFurtherADrag() {
|
||||
assertTrue(FloatingButtonGeometry.isTap(0, 0, 8));
|
||||
assertTrue(FloatingButtonGeometry.isTap(5, -6, 8)); // 7.8 px
|
||||
assertFalse(FloatingButtonGeometry.isTap(6, 6, 8)); // 8.5 px
|
||||
assertFalse(FloatingButtonGeometry.isTap(0, 40, 8));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user