feat(train): record a ride indoors, without GPS (ADR 0030, D66)

A home trainer's or an exercise bike's ride had no place: Cycling waits
for GPS and pauses by speed. Cycling indoors needs no GPS, route or
device: the time, then whichever strap, speed and cadence sensor or
power meter there is. It goes to Health Connect as stationary biking,
and another app's stationary ride comes in as one.

With no GPS, steps or device the recorder has no foreground service
type, which Android 14 on doesn't allow, so it asks for the physical
activity permission and doesn't start without it.

Whats-New: Record a ride on a home trainer or exercise bike with Cycling indoors, without GPS.
Whats-New-De: Zeichne eine Fahrt auf dem Heimtrainer mit Radfahren drinnen auf, ganz ohne GPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-05 16:47:23 +01:00
commit 3bd49920db
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -2175,6 +2175,26 @@ void main() {
});
});
testWidgets('a ride indoors offers the sensors and the strap, but neither '
'auto-pause nor a route, and starts without GPS (D66)', (tester) async {
await withClock(Clock(() => at), () async {
await startRecording(tester);
await tester.scrollUntilVisible(startFor('Cycling indoors'), 100);
await tester.tap(startFor('Cycling indoors'));
await tester.pumpAndSettle();
expect(find.text('Speed and cadence sensor'), findsOneWidget);
expect(find.text('Heart rate'), findsOneWidget);
expect(find.text('Pause by itself'), findsNothing);
expect(find.text('Route'), findsNothing);
await tester.tap(sheetStart);
await pass(tester, 2);
expect(platform.started.single.activity, Activity.indoorCycling);
expect(find.text('Waiting for GPS'), findsNothing);
});
});
testWidgets('a recording started opens its screen once; its '
'notification tapped opens it again from any tab', (tester) async {
await withClock(Clock(() => at), () async {