Building a Non-Root Android Mock Location Engine with Joystick Control

Architecture Overview

The system decouples location injection from UI interaction using a foreground service (MockLocationService) and a modular joystick subsystem. Core logic resides in app/src/main/java/com/zcshou/service/MockLocationService.java, where mock coordinates are injected via LocationManager.setTestProviderLocation() after validating ADB debugging permissions.

Instead of modifying system binaries or requesting dangerous permissions, GoGoGo leverages Android’s official test provider API. This requires enabling Developer Options and USB Debugging—a lightweight prerequisite compatible with Android 8.0+:

private void initializeMockProvider() {
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (!locationManager.hasTestProvider(LocationManager.GPS_PROVIDER)) {
        locationManager.addTestProvider(
            LocationManager.GPS_PROVIDER,
            false,   // requiresNetwork
            false,   // requiresSatellite
            false,   // requiresCell
            false,   // hasMonetaryCost
            true,    // supportsAltitude
            true,    // supportsSpeed
            true,    // supportsBearing
            Criteria.POWER_HIGH,
            Criteria.ACCURACY_FINE
        );
    }
    locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
}

Adaptive Positioning Modes

The app exposes three configurable positioning strategies—each tuned for distinct testing priorities:

Mode Accuracy Power Use Key Traits
GPS Emulation ±1m High Satellite-like metadata: altitude, speed, bearing; ideal for navigation validation
Network Simulation ±20–50m Low Cell/WiFi triangulation behavior; includes coarse heading and velocity estimates
Passive Relay ±1m (inherited) Negligible Forwards real device location only when available—no active polling or battery drain

Joystick-Controlled Coordinate Streaming

A custom RockerView component (app/src/main/java/com/zcshou/joystick/RockerView.java) handles touch-based directional input. Its output feeds into a smooth interpolation algorithm that converts analog stick displacement in to continuous latitude/longitude deltas:

public class CoordinateStreamer {
    private final double BASE_STEP_DEG = 0.0001;
    private double currentLat = 39.916;
    private double currentLng = 116.397;

    public void updatePosition(float xPercent, float yPercent) {
        currentLat += yPercent * BASE_STEP_DEG;
        currentLng += xPercent * BASE_STEP_DEG;
        injectLocation(currentLat, currentLng);
    }

    private void injectLocation(double lat, double lng) {
        Location mockLoc = new Location(LocationManager.GPS_PROVIDER);
        mockLoc.setLatitude(lat);
        mockLoc.setLongitude(lng);
        mockLoc.setAltitude(45.0);
        mockLoc.setSpeed(2.5f);
        mockLoc.setBearing(180.0f);
        mockLoc.setTime(System.currentTimeMillis());
        mockLoc.setAccuracy(1.0f);
        locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockLoc);
    }
}

Practical Testing Workflows

  • LBS Feature Validation: Simulate entry/exit from geofences across time zones without physical relocation
  • Multi-Region Service Checks: Verify API routing, language fallbacks, and regional content delivery
  • Map Rendering Stress Tests: Rapidly traverse dense point clusters to assess marker rendering performance

Setup & Deployment

  1. Clone the repository:
    git clone https://gitcode.com/GitHub_Trending/go/GoGoGo.git
  2. Import into Android Studio (Kotlin/Java support enabled)
  3. Enable Developer Options + USB Debugging on target device
  4. Grant required runtime permissions:
    • android.permission.ACCESS_FINE_LOCATION
    • android.permission.SYSTEM_ALERT_WINDOW (for overlay joystick)
    • android.permission.READ_EXTERNAL_STORAGE
  5. Launch the app, tap the map to set origin, then drag the joystick to stream movement

Tags: android-debug-bridge baidu-maps-sdk mock-location joystick-control location-testing

Posted on Tue, 27 Oct 2026 16:05:24 +0000 by Louis-Platt