GPSSimulator

Raw GPS spoofing is easy. Making it look like a real person ran that route is the hard part. GPSSimulator tackles that problem through realistic route shaping, natural pace variation, and a clean setup flow that makes simulation repeatable without friction.

GPSSimulator

GPSSimulator

A GPS movement simulator for Android that produces human-like running behavior, not robotic coordinate jumps.

Raw GPS spoofing is easy. Making it look like a real person ran that route is the hard part. GPSSimulator tackles that problem through realistic route shaping, natural pace variation, and a clean setup flow that makes simulation repeatable without friction.


Why This Exists

I am a runner, and I have a strange relationship with running: I like it, but I also hate it at the same time. I am also the kind of person who likes to test systems, bend them, and figure out where they break. That mindset shaped this app.

The real trigger was a challenge in my running community: 1000 km in 100 days. I could realistically run or walk only three or four days a week, but the challenge kept moving every day. Keeping up with all seven days was hard. That pressure pushed me to build something that could make a fitness app think I was still moving in the background.

The first version was built around 2022. It had no real UI. It ran in the background and moved the location, which proved the idea was possible, but the result was rough. The movement was not accurate, the path looked robotic, and the speed sometimes changed in unrealistic ways. It worked just enough to prove the concept, but not well enough to feel believable.

In 2023, I kept improving it. Development got faster as AI tools became more useful, and I started rebuilding the project with a better interface and cleaner flow. The app became easier to understand and easier to use, but the core simulation still had problems. The location changes were inconsistent, the pace logic was unreliable, and the movement still did not look natural enough.

In 2026, I finally brought those older ideas together into something much closer to what I originally wanted. The map layer was improved and brought directly into the UI so movement could be seen clearly on the dashboard. The location system was reworked to be as accurate as possible. Pace control became adjustable from the interface. Distance setup became simpler. Route selection became easier to change and control. Most importantly, the movement itself became more human by changing slightly every few meters instead of following a perfectly straight line for long stretches.

The goal was never just to move GPS coordinates. The goal was to produce movement that looks and feels like a real person ran that route: natural drift, breathing pace variation, and a route shape that does not scream “generated by an algorithm.”


What It Does

GPSSimulator feeds mock GPS updates to Android through a foreground service, simulating a run along a generated or user-defined route. The simulation includes:

  • Route drift: slight left/right lateral deviations so the path does not follow a mathematically perfect line.
  • Pace variation: timing per segment floats around a user-defined base pace rather than locking every kilometer to the same speed.
  • Three route modes: random generation, map pin placement, or freehand drawing.
  • A staged setup flow: distance, pace, route type, and review, each on its own focused screen.
  • A live process screen: shows the rendered route, live progress, and pause/stop controls.
  • Run history: completed and incomplete runs stored locally with metadata for later review.

Build Journey

This project took shape across several iterations:

  • 2022: the first prototype worked in the background without a real UI. It could move location data, but accuracy was weak and the motion looked artificial.
  • 2023: the app got a better interface and became easier to use, but the simulation logic still needed serious work, especially around pace consistency and believable movement.
  • 2026: the major problems were finally addressed through better map presentation, improved location handling, adjustable pace input, cleaner distance setup, more flexible route control, and route drift that makes the movement look more human.

The biggest fixes were practical:

  • Map quality: the map experience was upgraded so the route and live movement are visible directly in the interface.
  • Location accuracy: the location update path was improved to make simulation output as accurate and stable as possible.
  • Pace control: speed and pace input were made adjustable from the dashboard, with movement timing handled in smaller intervals for more believable behavior.
  • Distance setup: kilometer input became more direct and easier to configure.
  • Route control: route selection became easier to change, making the app more flexible and more user-friendly.
  • Human-like movement: instead of moving in an unnaturally straight line for long distances, the route shifts slightly every few meters to create a more natural zig-zag pattern.

How It Works

  1. The user sets a target distance, a base pace, and a route mode.
  2. MainViewModel passes the request to RouteGenerator.
  3. For random and pinned routes, the app fetches a route from OSRM and decodes the polyline.
  4. WalkingPathEnhancer perturbs the route by adding sidewalk-style offsets and lateral drift.
  5. LocationSimulationService starts a foreground service and steps through the route via RouteEngine.
  6. PaceEngine adjusts timing per segment, then the service pushes mock locations through Google Play Services and the Android test provider.
  7. Room stores route metadata so every run, finished or not, appears in history.

Realism In Detail

Route Shape

A perfectly straight GPS trace is an immediate giveaway. WalkingPathEnhancer addresses this by:

  • Applying a sidewalk-style lateral offset from the route centerline.
  • Introducing small directional drift changes every few meters.
  • Switching sides on out-and-back segments so the return path does not retrace the outbound line exactly.

The result is a route that looks like someone actually ran it rather than a line renderer produced it.

Pace Behavior

Constant speed across a full run is equally suspicious. PaceEngine uses the user’s base pace as a center point and varies each segment within a realistic window:

ParameterValue
Base paceUser defined
Fastest paceBase - 30 seconds/km
Slowest paceBase + 30 seconds/km
Runtime behaviorRandom drift with smooth segment-to-segment adaptation

The run breathes. It speeds up a little, slows a little, and never locks into mechanical uniformity.

Interface Design

Realism is not only about movement output. A confusing or error-prone setup flow breaks the experience before simulation even starts. The interface moved from a single crowded screen to a staged flow:

  • Main screen: distance selection as the first and only focus.
  • Pace screen: base pace input without distraction.
  • Route screen: mode selection with map interaction.
  • Review screen: summary before committing to the simulation.
  • Process screen: active run with full map view, progress bar, pause, and stop.
  • History screen: past runs with route type, distance, pace, and completion status.

Screenshots

Setup Flow

Distance screen Pace screen Route screen

Simulation And History

Progress screen History screen

UI Evolution

The original interface crammed all controls onto one screen. It worked, but setup felt dense and easy to misconfigure.

Old interface

The redesign spread setup across dedicated steps, making each decision clearer and the overall flow easier to follow.


Technical Stack

LayerTechnology
LanguageKotlin
PlatformAndroid (Min SDK 24, Compile SDK 34)
MappingOSMDroid / OpenStreetMap
RoutingOSRM via Retrofit
PersistenceRoom
AsyncKotlin Coroutines
ArchitectureActivity + ViewModel + Foreground Service

Key Components

ComponentResponsibility
RouteGeneratorFetches and decodes OSRM routes
WalkingPathEnhancerApplies lateral drift and sidewalk offsets
PaceEngineManages per-segment timing variation
RouteEngineSteps through route waypoints
LocationSimulationServiceRuns the foreground simulation and injects mock locations

Installation

Prerequisites

  • Android Studio with Android SDK 34
  • A physical device or emulator with mock location support
  • Developer Options enabled
  • The app set as the active mock location app in Developer Options

Steps

1
2
3
4
5
6
# 1. Clone the repository
git clone https://github.com/your-username/GPSSimulator.git

# 2. Open the project in Android Studio
# 3. Let Gradle sync
# 4. Build and run the app module on your device or emulator

Before starting a simulation, go to Developer Options -> Select mock location app and choose GPSSimulator.


Usage

  1. Launch the app and grant location permissions.
  2. Select a distance: 5 km, 10 km, or a custom value.
  3. Set a base pace in min/km.
  4. Choose a route mode:
    • Random: generates a route from your current location.
    • Pin Map: place waypoints manually on the map.
    • Draw Map: sketch the route freehand.
  5. Review the summary and start the simulation.
  6. Watch the process screen for live progress. Pause or stop any time.
  7. Open History to review completed and incomplete runs.

Responsible Use

GPSSimulator is intended for development, UI prototyping, location testing, and movement simulation research. Do not use it to misrepresent physical activity where accuracy, trust, or compliance matters.


What Comes Next

  • AI-based motion modeling trained on real runner behavior.
  • Elevation simulation, traffic light pauses, and stride-level timing variance.
  • Deeper integration with fitness ecosystems for testing and prototyping.
  • Adaptive profiles that adjust behavior to the user’s preferred pace and style.
  • Richer animations across the setup and progress experience.

This post is licensed under CC BY 4.0 by the author.