Files
samplez/INSTALL.md
Dylan 0bc42b2e5a Add the Rippr Flutter port: source, history bundle, and installable APK
The port runs on Android and iOS and is feature-complete; the native Android app
is superseded but kept, since it is still the only version that has recorded real
rides.

rippr-flutter-1.0-debug.apk is package com.rippr.port, deliberately different
from the native com.rippr so both install side by side. Recording the same ride
on both at once is the strongest available check that the port is faithful.

Added INSTALL.md covering both platforms. Android is a one-line adb install; iOS
has no APK equivalent and must be built and signed through Xcode with a free
Apple ID, which gives a 7-day profile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 22:37:45 -05:00

5.0 KiB

Installing Rippr

Two platforms, two very different stories. Android takes a minute; iOS needs a Mac and about ten.


Android — install the APK

rippr-flutter-1.0-debug.apk · package com.rippr.port · label Rippr · Android 8.0+

It is debug-signed, so it installs directly and coexists with the native app (com.rippr).

Over USB

adb install -r rippr-flutter-1.0-debug.apk

If you already have it installed and signatures clash:

adb uninstall com.rippr.port && adb install rippr-flutter-1.0-debug.apk

Without a cable

Copy the APK to the phone (Drive, email to yourself, adb push, whatever), open it in Files, and allow the installing app to install unknown apps when prompted.

First launch

  1. Grant location — "While using the app" is enough; the foreground service covers the rest. Rippr never asks for "Allow all the time".
  2. Grant notifications on Android 13+. Not optional in practice: the ongoing notification is what keeps the recording service alive.
  3. On Samsung/Xiaomi/OnePlus, exempt Rippr from battery optimisation, or the OS may kill it mid-ride. Settings → Apps → Rippr → Battery → Unrestricted.

Running both apps at once

This is worth doing deliberately. The two use different application ids so they can record the same ride simultaneously, which is the strongest check that the port is faithful:

adb install -r rippr-2.0.1-debug.apk        # native, com.rippr
adb install -r rippr-flutter-1.0-debug.apk  # port,   com.rippr.port

Start both, ride, stop both, compare distance / max speed / moving time. See rippr-flutter-src/docs/port/REAL-RIDE-CHECKLIST.md.

The debug APK is ~172 MB because it carries every ABI and no code shrinking. A release build would be a fraction of that, but needs a signing key — see below.


iOS — you have to build and sign it yourself

There is no APK equivalent. iOS will not run an app that is not signed by a certificate the device trusts, so an unsigned .app or .ipa cannot simply be copied over. The only routes are the App Store, TestFlight, an Apple Developer account with ad-hoc provisioning, or free personal signing through Xcode — which is what follows.

What you need

  • A Mac with Xcode (already installed)
  • Flutter (already installed)
  • Your iPhone and a Lightning/USB-C cable
  • A free Apple ID — no paid Developer account required

Steps

git clone rippr-flutter-history.bundle rippr-flutter
cd rippr-flutter
flutter pub get
dart run build_runner build      # Drift codegen
open ios/Runner.xcworkspace      # the workspace, NOT the .xcodeproj

In Xcode:

  1. Select the Runner target → Signing & Capabilities
  2. Tick Automatically manage signing
  3. Team → Add an Account… → sign in with your Apple ID → select it as the team
  4. Change the Bundle Identifier to something globally unique, e.g. com.dylan.rippr.port. A free personal team cannot claim an identifier someone else has registered, and com.rippr.port may collide.
  5. Plug in the iPhone and pick it as the run destination
  6. Press Run (⌘R)

On the phone, first launch will refuse with "Untrusted Developer". Go to Settings → General → VPN & Device Management → your Apple ID → Trust, then launch again.

Or from the terminal once signing is configured in Xcode:

flutter devices                       # find your phone's id
flutter run --release -d <device-id>

The catch with free signing

A free Apple ID gives a 7-day provisioning profile. After a week the app refuses to launch and you re-run it from Xcode to refresh. You are also limited to three apps sideloaded at a time.

A paid Developer account ($99/yr) raises that to a year and unlocks TestFlight, which is the sane route if you want the app on a phone for a whole riding season.

First launch on iOS

  1. Grant location. Choose "Allow While Using App" first; iOS will later ask to upgrade to Always once it sees background usage — accept it, or recording stops when the screen locks.
  2. A blue pill appears in the status bar while recording in the background. That is correct and intentional.
  3. iOS gives no equivalent of Android's battery-optimisation exemption. Low Power Mode will affect GPS behaviour — worth testing with it off first.

Known limitations of both builds

  • Neither has ever recorded a real ride. Everything is verified by 175 automated tests and a simulator, and no simulator produces velocity.
  • No notification actions. The native app had Pause/Resume buttons in the shade; the Flutter port does not. Tapping the notification opens the app.
  • The app icon is still the Flutter default.
  • Debug builds. Slower than release and much larger. For Android, a release build needs a keystore:
    keytool -genkey -v -keystore ~/rippr.jks -keyalg RSA -keysize 2048 \
            -validity 10000 -alias rippr
    # then configure signingConfigs in android/app/build.gradle.kts
    flutter build apk --release