- Foreground notification handler in App.tsx (iOS shows banners while active) - requestNotificationPermissions() called on app mount - GPS task tracks running distance per recording session (module-level state) - Fires immediate notification at each km crossed, gated on kmNotifications setting
bincio-rec
GPS activity recorder for cycling, running, hiking, and walking. Records GPS tracks + BLE sensor data (HR, power, cadence) and saves them as GPX files. Part of the bincio ecosystem.
Prerequisites
All platforms
| Tool | Version | Notes |
|---|---|---|
| Node.js | 22+ | nodejs.org |
| npm | 10+ | Comes with Node |
| Expo CLI | latest | npm install -g expo-cli (optional, npx expo works too) |
Android
| Tool | Notes |
|---|---|
| Android Studio | developer.android.com/studio |
| Android SDK | Install via Android Studio SDK Manager |
| JDK 17 | Bundled with Android Studio, or install separately |
ANDROID_HOME env var |
Set to your SDK path, e.g. ~/Library/Android/sdk |
Minimum supported Android version: API 26 (Android 8.0).
iOS (macOS only)
| Tool | Notes |
|---|---|
| Xcode 16+ | Install from the Mac App Store |
| Xcode Command Line Tools | xcode-select --install |
| CocoaPods | sudo gem install cocoapods |
| Apple Developer account | Free account works for device sideloading |
Minimum supported iOS version: 16.4.
Setup
# 1. Install JS dependencies
npm install
# 2. Prebuild was already run — android/ and ios/ directories exist.
# Re-run only when you add/remove native modules:
npx expo prebuild --clean
Running in development
Android
# Start Metro bundler + launch on a connected device or emulator
npm run android
# Or target a specific device
npx expo run:android --device
Android emulator setup: In Android Studio → Device Manager, create an AVD with API 34+, x86_64 image. Start it before running the command above.
Physical device: Enable Developer Options → USB Debugging, then connect via USB.
Battery optimization: On first launch, the app will prompt you to whitelist it in battery settings. This is required for background GPS recording to survive on Xiaomi / Samsung / Huawei devices.
iOS
# Install CocoaPods dependencies (first time and after native changes)
cd ios && pod install && cd ..
# Start Metro bundler + launch on a connected device or simulator
npm run ios
# Or target a specific simulator
npx expo run:ios --simulator "iPhone 16"
# Or target a physical device (requires Apple Developer account)
npx expo run:ios --device
Location permission: iOS will prompt for location access. Choose Always Allow — background GPS recording requires it.
Building release APK / IPA
Android — local release APK
cd android
./gradlew assembleRelease
# Output: android/app/build/outputs/apk/release/app-release.apk
To build a release AAB (required for Play Store):
./gradlew bundleRelease
# Output: android/app/build/outputs/bundle/release/app-release.aab
Signing: Create a keystore and configure android/app/build.gradle with your signing config before a production release. See React Native signing docs.
iOS — local release archive
Open Xcode:
open ios/binciorec.xcworkspace
- Select your device or Any iOS Device (arm64) as the target.
- Set your Team in Signing & Capabilities.
- Product → Archive.
- In the Organizer window, click Distribute App.
Building with EAS Build (recommended for CI / TestFlight)
EAS Build runs in Expo's cloud so you don't need Android Studio or Xcode locally.
# Install EAS CLI
npm install -g eas-cli
# Log in to your Expo account
eas login
# Configure the project (first time only — creates eas.json)
eas build:configure
# Build Android APK for local testing
eas build --platform android --profile preview
# Build Android AAB for Play Store
eas build --platform android --profile production
# Build iOS IPA for TestFlight / App Store
eas build --platform ios --profile production
Builds appear at expo.dev and a download link is printed when done.
Project structure
bincio-rec/
├── App.tsx # Entry point
├── app.json # Expo config (permissions, plugins, bundle IDs)
├── android/ # Generated Android project (do not edit manually)
├── ios/ # Generated iOS project (do not edit manually)
└── src/
├── types/index.ts # Shared TypeScript types
├── store/recording.ts # Zustand recording state + haversine stats
├── services/
│ ├── gps.ts # Background GPS via expo-location + expo-task-manager
│ ├── ble.ts # BLE scan / connect / HR + power subscriptions
│ ├── gpx.ts # GPX file builder (Garmin trackpoint extensions)
│ ├── upload.ts # Upload GPX to bincio-activity /api/upload/raw
│ └── db.ts # SQLite CRUD for saved recordings list
├── screens/
│ ├── RecordingScreen.tsx
│ ├── PostRecordingScreen.tsx
│ ├── SensorPairingScreen.tsx
│ ├── SavedRecordingsScreen.tsx
│ └── SettingsScreen.tsx
└── navigation/
└── AppNavigator.tsx # Root stack + bottom tabs
Ecosystem
bincio-rec → writes GPX files to device storage
bincio-autarchive → imports GPX, stores locally, syncs to server
bincio-activity → server: parses GPX, stores activities, serves API
bincio-auth → auth service: issues JWTs for all bincio apps
Configure your bincio instance URL and API token in Settings to enable direct upload from the app.
Adding native modules
Any new Expo or React Native library with native code requires a prebuild + reinstall cycle:
npx expo install <package-name>
npx expo prebuild --clean # regenerates android/ and ios/
cd ios && pod install && cd ..