Automating Mock GPS Location Changes with ADB, Tasker, and MacroDroid
August 16, 2026 · The Devs Tools Team
Automating mock GPS location changes on Android is the process of programmatically injecting simulated geographic coordinates (latitude, longitude, altitude, accuracy, timestamp) into the operating system's LocationProvider subsystem using shell broadcasts, intent receivers, or on-device automation engines without human manual intervention. Rather than manually tapping a graphical map interface on a test workstation, automated location switching enables continuous integration (CI) runners, terminal scripts, and automated testing suites (such as Appium, Espresso, or Maestro) to dispatch non-interactive commands directly through the Android Debug Bridge (adb shell am broadcast) or local intent triggers like Tasker and MacroDroid. This automation approach ensures that end-to-end regression suites can reliably evaluate regional content restrictions, geofence transitions, localized payment flows, and telematics logic deterministically across emulators and physical hardware farms.
[!TIP] Want to mock location movement on your test device right now? Try Feint to plan routes, mirror screens, and automate GPS mock coordinates completely offline.
Why GUI-Based GPS Mocking Breaks CI/CD Pipelines
Interactive map interfaces and desktop GUI companion tools work well for ad-hoc manual verification during local development. However, graphical workflows introduce critical failure points when scaling QA infrastructure:
- Lack of Headless Execution: Standard CI runners (such as GitHub Actions, GitLab CI, or headless Jenkins agents) operate in environments without connected displays or GUI interaction layers.
- Flaky End-to-End Orchestrations: Emulating manual screen taps via coordinate clicks on a simulated map introduces race conditions, frame drops, and latency overhead into test executions.
- Fragmented Hardware Automation: Coordinating multiple physical Android devices simultaneously across distributed testing racks becomes unmaintainable when each unit requires individual graphical mapping sessions.
Eliminating these points of failure requires decoupling the mock location provider from user interfaces, exposing direct inter-process communication (IPC) channels via native Android broadcast intents.
The Core ADB Broadcast Interface: SET_LOCATION and CLEAR_LOCATION
Feint's automated mocking engine exposes headless intent listeners built directly on top of Android's BroadcastReceiver architecture. Once Feint is designated as the active mock location app in Android Developer Options, the host computer or CI runner can update device coordinates instantly via terminal commands without opening the application's UI.
┌────────────────────────────────────────┐
│ CI Runner / Test Script (Host) │
└───────────────────┬────────────────────┘
│
(adb shell am broadcast)
│
▼
┌────────────────────────────────────────┐
│ Android OS Binder / IPC │
└───────────────────┬────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Feint Intent Broadcast Receiver │
│ - Action: SET_LOCATION │
│ - Action: CLEAR_LOCATION │
└───────────────────┬────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ LocationManager.setTestProviderLocation()
└────────────────────────────────────────┘
1. The SET_LOCATION Intent Broadcast
To inject a new set of coordinates, invoke the SET_LOCATION broadcast action and supply latitude, longitude, and optional telemetry parameters (such as altitude, accuracy radius in meters, speed, and bearing) as intent extras:
# Inject coordinates for San Francisco Financial District
adb shell am broadcast \
-a com.thedevstools.feint.SET_LOCATION \
--ef lat 37.792275 \
--ef lng -122.401146 \
--ef alt 15.5 \
--ef acc 3.0 \
--ef speed 0.0 \
--ef bearing 180.0
Intent Extra Parameter Reference
--ef lat <float>: Target latitude in decimal degrees (Required, -90.0 to 90.0).--ef lng <float>: Target longitude in decimal degrees (Required, -180.0 to 180.0).--ef alt <float>: Simulated altitude in meters above the WGS 84 reference ellipsoid (Optional).--ef acc <float>: Horizontal accuracy radius in meters (+/- meters) (Optional, defaults to 1.0).--ef speed <float>: ground speed in meters per second (Optional).--ef bearing <float>: Trajectory direction in degrees (0.0 to 360.0) (Optional).
2. The CLEAR_LOCATION Intent Broadcast
When a test case concludes or when your test script needs to evaluate how the application handles loss of GPS coverage, dispatch the CLEAR_LOCATION broadcast to remove the test provider location from the OS registry:
# Clear active mock provider and disable coordinate injection
adb shell am broadcast -a com.thedevstools.feint.CLEAR_LOCATION
Integrating Location Changes into CI/CD and Test Frameworks
Exposing coordinate injection over plain shell commands allows test automation suites to manipulate geographic state dynamically between test assertions.
Bash Automation Script Example
The following script iterates through a series of discrete delivery checkpoints, waiting for the application under test (AUT) to process order handoffs at each point:
#!/usr/bin/env bash
set -euo pipefail
# Grant mock location permissions to Feint
adb shell appops set com.thedevstools.feint android:mock_location allow
# Array of test checkpoints: "lat lng name"
CHECKPOINTS=(
"37.774929 -122.419416 Warehouse_A"
"37.779500 -122.415000 Transit_Hub"
"37.783333 -122.416667 Destination"
)
for point in "${CHECKPOINTS[@]}"; do
read -r lat lng name <<< "$point"
echo "==> Routing device to: $name ($lat, $lng)"
adb shell am broadcast \
-a com.thedevstools.feint.SET_LOCATION \
--ef lat "$lat" \
--ef lng "$lng" \
--ef acc 2.5
# Execute test assertion or wait for app geofence trigger
sleep 5
done
echo "==> Run complete. Clearing mock status."
adb shell am broadcast -a com.thedevstools.feint.CLEAR_LOCATION
Appium Integration Pattern (Python)
In mobile automation frameworks like Appium, execute the broadcast directly through the underlying driver bridge:
from appium import webdriver
from appium.options.android import UiAutomator2Options
import time
options = UiAutomator2Options()
options.platform_name = "Android"
options.automation_name = "UiAutomator2"
options.app_package = "com.example.courierapp"
options.app_activity = ".MainActivity"
driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
def update_mock_location(lat: float, lng: float):
broadcast_cmd = (
f"am broadcast -a com.thedevstools.feint.SET_LOCATION "
f"--ef lat {lat} --ef lng {lng} --ef acc 1.5"
)
driver.execute_script("mobile: shell", {
"command": broadcast_cmd
})
# Step 1: Simulate user at restaurant
update_mock_location(37.7749, -122.4194)
time.sleep(3)
# Step 2: Validate pickup state in UI
order_status = driver.find_element("id", "com.example.courierapp:id/status_text").text
assert "Near Store" in order_status
# Step 3: Simulate arrival at customer dropoff
update_mock_location(37.7833, -122.4167)
time.sleep(3)
driver.quit()
On-Device Automation: Tasker and MacroDroid
Automated testing does not always originate from a host computer or CI runner. Hardware field tests, endurance monitoring, and localized device demonstrations often require the Android device to change its own mock location dynamically based on internal system triggers:
- Time-Based Transitions: Automatically switching home and work coordinates based on operating schedules.
- Application Triggers: Injecting specific geolocations whenever a particular application (e.g., a regional retail catalog) launches into the foreground.
- Notification Events: Adjusting coordinates in response to incoming push notifications or webhook payloads received by local automation listeners.
Because Tasker and MacroDroid support standard Android intent dispatching, you can configure them to trigger Feint's SET_LOCATION action without writing custom native code.
[ Trigger Event (App Opened / Time / Webhook) ]
│
▼
[ Tasker / MacroDroid Intent Action ]
- Action: com.thedevstools.feint.SET_LOCATION
- Extras: lat:37.7749, lng:-122.4194
│
▼
[ Feint Headless Location Engine ]
Tasker Action Configuration
- Open Tasker and create a new Task.
- Tap
+to add an action and select System -> Send Intent. - Configure the following fields:
- Action:
com.thedevstools.feint.SET_LOCATION - Extra 1:
lat:37.774929 - Extra 2:
lng:-122.419416 - Extra 3:
acc:2.0 - Target:
Broadcast Receiver
- Action:
- Bind this task to your desired Profile trigger (e.g., App Launch, Time State, or NFC Tag).
MacroDroid Action Configuration
- In MacroDroid, add a new Action -> Connectivity -> Send Intent.
- Set Target to Broadcast.
- Set Action to
com.thedevstools.feint.SET_LOCATION. - Add parameter keys under Extra Variables:
lat(Float) ->37.774929lng(Float) ->-122.419416
- Save the macro and assign your operational triggers.
State Persistence: Resume-on-Boot Architecture
A common vulnerability in automated test benches is hardware reboots. Automated battery profiling, kernel updates, or watchdog crashes can trigger sudden device restarts. Under vanilla Android behavior, a device reboot purges in-memory test provider states, reverting the phone to its physical hardware GPS fix.
Feint implements an optional Resume-on-Boot background service:
- Persistent State Caching: Every valid coordinate injected via ADB or on-device intents is serialized to encrypted local storage (
EncryptedSharedPreferences). - Boot Receiver Listening: Upon receiving the
android.intent.action.BOOT_COMPLETEDsystem broadcast, Feint's background daemon checks whether active mocking was enabled prior to shutdown. - Automatic Provider Re-Registration: The service initializes the LocationManager mock provider hook and re-injects the last-known coordinate before background applications attempt to bind to location services.
This ensures prolonged soak tests and continuous regression environments maintain state consistency without requiring manual reconnection after unexpected power cycles.
Complete Standalone Architecture: Zero Host Dependency
A critical engineering advantage of Feint's automation layer is that it operates 100% standalone on the Android target device.
| Feature | Requires Mac Companion? | Execution Layer |
|---|---|---|
| Route Planning & Road Snapping | Yes (Desktop UI) | Host Mac / Desktop App |
| Screen Mirroring & Input Relay | Yes (Desktop UI) | Host Mac / USB Stream |
| ADB Broadcast Intents | No | Standalone Android Device |
| Tasker & MacroDroid Automation | No | Standalone Android Device |
| Resume-on-Boot Persistence | No | Standalone Android Service |
While the Mac companion app provides graphical route building, multi-stop road snapping, and live telemetry dashboards, automation scripts never route through the desktop client. You can deploy standalone APK binaries across remote Android emulators, cloud testing providers (such as AWS Device Farm or Firebase Test Lab), or physical hardware racks without installing or launching desktop helper tools.
Summary
Automating GPS coordinate injection eliminates the friction and flakiness of manual UI testing. By leveraging headless ADB broadcast intents, on-device Tasker/MacroDroid triggers, and standalone boot persistence, engineering teams can seamlessly embed deterministic location simulation into CI/CD pipelines, regression matrices, and automated QA workflows.
