Use the real Rippr icons instead of the Flutter defaults

Launcher, notification and launch screen on both platforms, all generated from
the native app's design sources rather than redrawn.

Android uses the adaptive icon files verbatim from the native app: foreground,
monochrome and the #101418 background colour. That matters because the adaptive
foreground draws its ring at r=32, the corrected radius that survives the
launcher's circular mask -- the first native version used r=43 and the mask
cropped the ring clean off.

iOS gets the full-bleed r=43 artwork instead, which is right there: iOS applies a
rounded superellipse rather than a circle crop, so the wider ring fits. All 15
sizes rendered from the SVG, and the 1024 verified to have no alpha channel,
which the App Store rejects.

The notification icon is ic_stat_rippr, a white silhouette on transparency.
Android masks status bar icons to a solid shape, so pointing this at the colour
launcher icon would render a featureless white blob.

Launch screens were the generated white, which flashes before a dark app on every
cold start. Both now use the app's own tarmac colour with the route mark centred.

Verified on the Android emulator rather than assumed: the launcher shows the
route mark with its orange accent intact, resource 0x7f07007c resolves to
drawable/ic_stat_rippr, and the notification reads "Rippr is recording" with a
clean silhouette. The run also recorded 23 points into a real trip -- the first
time this port has captured anything on Android.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 01:30:41 -05:00
parent fc6d8f9dba
commit 82f07a2d68
37 changed files with 112 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- The launch window, shown before Flutter has drawn anything.
<!-- You can insert your own image assets here -->
<!-- <item>
Deliberately the app's own tarmac colour rather than the generated white: a white
flash before a dark app is jarring, and it is the first thing seen on every cold
start. -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/ic_launcher_background" />
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
android:src="@drawable/launch_mark" />
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<!-- Track ring. -->
<path
android:pathData="M86.0,54.0 A32.0,32.0 0 1 1 22.0,54.0 A32.0,32.0 0 1 1 86.0,54.0"
android:strokeColor="#66727E"
android:strokeWidth="3.5"
android:strokeAlpha="0.6" />
<!-- Material Symbols `route`, Apache-2.0. Scaled from its 960 box onto the icon canvas. -->
<group
android:translateX="34"
android:translateY="74"
android:scaleX="0.041667"
android:scaleY="0.041667">
<path
android:pathData="M247-167q-47-47-47-113v-327q-35-13-57.5-43.5T120-720q0-50 35-85t85-35q50 0 85 35t35 85q0 39-22.5 69.5T280-607v327q0 33 23.5 56.5T360-200q33 0 56.5-23.5T440-280v-400q0-66 47-113t113-47q66 0 113 47t47 113v327q35 13 57.5 43.5T840-240q0 50-35 85t-85 35q-50 0-85-35t-35-85q0-39 22.5-70t57.5-43v-327q0-33-23.5-56.5T600-760q-33 0-56.5 23.5T520-680v400q0 66-47 113t-113 47q-66 0-113-47Zm-7-513q17 0 28.5-11.5T280-720q0-17-11.5-28.5T240-760q-17 0-28.5 11.5T200-720q0 17 11.5 28.5T240-680Zm480 480q17 0 28.5-11.5T760-240q0-17-11.5-28.5T720-280q-17 0-28.5 11.5T680-240q0 17 11.5 28.5T720-200ZM240-720Zm480 480Z"
android:fillColor="#F2F5F8" />
</group>
<!-- Recording-progress segment: the SVG's dash pattern, cut with trimPath. -->
<path
android:pathData="M86.0,54.0 A32.0,32.0 0 1 1 22.0,54.0 A32.0,32.0 0 1 1 86.0,54.0"
android:strokeColor="#FF5722"
android:strokeWidth="3.5"
android:strokeLineCap="round"
android:trimPathStart="0.3701"
android:trimPathEnd="0.4960" />
</vector>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:pathData="M86.0,54.0 A32.0,32.0 0 1 1 22.0,54.0 A32.0,32.0 0 1 1 86.0,54.0"
android:strokeColor="#FF000000"
android:strokeWidth="3.5" />
<group
android:translateX="34"
android:translateY="74"
android:scaleX="0.041667"
android:scaleY="0.041667">
<path
android:pathData="M247-167q-47-47-47-113v-327q-35-13-57.5-43.5T120-720q0-50 35-85t85-35q50 0 85 35t35 85q0 39-22.5 69.5T280-607v327q0 33 23.5 56.5T360-200q33 0 56.5-23.5T440-280v-400q0-66 47-113t113-47q66 0 113 47t47 113v327q35 13 57.5 43.5T840-240q0 50-35 85t-85 35q-50 0-85-35t-35-85q0-39 22.5-70t57.5-43v-327q0-33-23.5-56.5T600-760q-33 0-56.5 23.5T520-680v400q0 66-47 113t-113 47q-66 0-113-47Zm-7-513q17 0 28.5-11.5T280-720q0-17-11.5-28.5T240-760q-17 0-28.5 11.5T200-720q0 17 11.5 28.5T240-680Zm480 480q17 0 28.5-11.5T760-240q0-17-11.5-28.5T720-280q-17 0-28.5 11.5T680-240q0 17 11.5 28.5T720-200ZM240-720Zm480 480Z"
android:fillColor="#FF000000" />
</group>
</vector>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by design/to_vector_drawable.py — do not edit by hand. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFFFF">
<group
android:translateX="2"
android:translateY="22"
android:scaleX="0.020833"
android:scaleY="0.020833">
<path
android:pathData="M247-167q-47-47-47-113v-327q-35-13-57.5-43.5T120-720q0-50 35-85t85-35q50 0 85 35t35 85q0 39-22.5 69.5T280-607v327q0 33 23.5 56.5T360-200q33 0 56.5-23.5T440-280v-400q0-66 47-113t113-47q66 0 113 47t47 113v327q35 13 57.5 43.5T840-240q0 50-35 85t-85 35q-50 0-85-35t-35-85q0-39 22.5-70t57.5-43v-327q0-33-23.5-56.5T600-760q-33 0-56.5 23.5T520-680v400q0 66-47 113t-113 47q-66 0-113-47Zm-7-513q17 0 28.5-11.5T280-720q0-17-11.5-28.5T240-760q-17 0-28.5 11.5T200-720q0 17 11.5 28.5T240-680Zm480 480q17 0 28.5-11.5T760-240q0-17-11.5-28.5T720-280q-17 0-28.5 11.5T680-240q0 17 11.5 28.5T720-200ZM240-720Zm480 480Z"
android:fillColor="#FFFFFFFF" />
</group>
</vector>

View File

@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- The launch window, shown before Flutter has drawn anything.
<!-- You can insert your own image assets here -->
<!-- <item>
Deliberately the app's own tarmac colour rather than the generated white: a white
flash before a dark app is jarring, and it is the first thing seen on every cold
start. -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/ic_launcher_background" />
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
android:src="@drawable/launch_mark" />
</item>
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- The tarmac ground behind the launcher icon. Matches the app's background. -->
<color name="ic_launcher_background">#101418</color>
</resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 1019 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -19,7 +19,7 @@
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.062745" green="0.078431" blue="0.094118" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>

View File

@@ -100,6 +100,14 @@ class GeolocatorLocationSource implements LocationSource {
notificationTitle: notificationTitle,
notificationText: notificationText,
notificationChannelName: 'Ride recording',
// The status bar wants a white silhouette on transparency, not the full
// colour launcher icon — Android masks it to a solid shape, so a colour icon
// renders as a featureless white blob. `ic_stat_rippr` is the monochrome
// route mark carried over from the native app for exactly this.
notificationIcon: const AndroidResource(
name: 'ic_stat_rippr',
defType: 'drawable',
),
enableWakeLock: true,
setOngoing: true,
),