153

How can I mock my location on a physical device (Nexus One)?

I know you can do this with the emulator in the Emulator Control panel, but this doesn't work for a physical device.

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Isaac Waller
  • 32,709
  • 29
  • 96
  • 107
  • 6
    There are several applications in Market which can emulate GPS location. For example "Location spoofer". – Vlad Dec 03 '10 at 07:32
  • For desktop computers you can create/install drivers that emulate a GPS device/serial port device for the purpose of doing this kind of testing. Perhaps you could create or find something similar for android. – AaronLS Mar 31 '10 at 21:14
  • There is a lot of apps in the store that do this.. You can try this - https://play.google.com/store/apps/details?id=com.yedapps.fakelocation.app.app.fakelocation&hl=en or this - https://play.google.com/store/apps/details?id=com.fakegps.mock&hl=en – Yehuda Aug 06 '15 at 22:19
  • 1
    There is also an app in the store that supports "geo fix" and "geo nmea" commands just like the emulator! https://play.google.com/store/apps/details?id=github.luv.mockgeofix&hl=en – luv Jul 30 '16 at 19:27
  • @Iuv more over it is open source https://github.com/luv/mockgeofix – Vlad Nov 05 '19 at 08:31

21 Answers21

168

It seems the only way to do is to use a mock location provider.

You have to enable mock locations in the development panel in your settings and add

   <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> 

to your manifest.

Now you can go in your code and create your own mock location provider and set the location of this provider.

casperOne
  • 73,706
  • 19
  • 184
  • 253
Janusz
  • 187,060
  • 113
  • 301
  • 369
  • 85
    There is an application on the market called "Fake GPS". If you enable Mock Locations on your device, it offers a nice GUI for setting your location. I realise this isn't a do-it-yourself solution, but certainly a worthy solution for quick testing. – Tim Green Aug 30 '11 at 22:16
  • 2
    [this](http://pedroassuncao.com/2009/11/android-location-provider-mock/) might be the link - same date, and relevant content. – DefenestrationDay Apr 18 '12 at 22:40
  • Actually the "fake gps" application is not the best because it can only set locations and randomly move around. Their new version can route but it only iterates over way points so huge jumps in the location. Janusz answer is indeed correct that you need to create your own mock provider. We recently did that and if anyone needs it or if this question still needs help, I'll post the code. – vkinra Jun 11 '13 at 15:50
  • 7
    The statement "go in your code and create your own mock location provider" should be explained in more detail. – Dims Feb 16 '17 at 10:35
  • Now, Studio Android 2.3.2 appear msg :"Mock locations should only be requested in a test or debug-specific manifest file (typically src/debug/AndroidManifest.xml)" --> Anyone, how to build it with release mode? – Huỳnh Ngọc Bang Jun 08 '17 at 00:46
102

If you use this phone only in development lab, there is a chance you can solder away GPS chip and feed serial port directly with NMEA sequences from other device.

tomash
  • 12,742
  • 15
  • 64
  • 81
  • 12
    If you have trouble figuring out how to generate realistic NMEA sequences into your unsoldered device, there's an awesome option: solder there an actual external GPS device and move the whole development lab on an actual track, on top of a team of runners/bikers/cars/planes/whatever depending on the speed you want to simulate. Don't forget to open a hole in the roof of the development lab so that the device can receive radio signals from satellites. You're welcome. ;-) – Stéphane Gourichon Jun 08 '16 at 08:42
  • @StéphaneGourichon better yet, solder them all together into one unholy ball of metal and use it as an antenna for your phone's gps. It is bound to pick up some gps signals. – nurettin Jun 19 '16 at 06:27
  • 2
    Such a shame this is often the same IC as the GSM/HSPA/EDGE/LTE/CDMA. A reason to hate SOC design ;) – ewanm89 Jul 13 '16 at 21:59
  • 4
    If you are not able to unsolder the chip, you could always build yourself a drone squadron equipped with radios tuned at the same frequency as the GPS satellites, emitting with high power in order to jam the real signals, then trivially calculate the time offset to fake depending on the desired mocked location. Mind that every drone has to emit in the same 3 channels as your closest sateillites, and that those channels change with your position. Also,be aware that airspace restrictions may apply in your area. – rupps Jul 21 '16 at 00:16
32

I wish I had my cable handy. I know you can telnet to the emulator to change its location

$ telnet localhost 5554
Android Console: type 'help' for a list of commands
OK
geo fix -82.411629 28.054553
OK

I cannot remember if you can telnet to your device, but I think you can. I hope this helps.

You'll need adb (android debugging bridge) for this (CLI).

AndiDog
  • 68,631
  • 21
  • 159
  • 205
Tim Green
  • 2,028
  • 1
  • 17
  • 19
  • you get a permission denied to everything you send as a command to the console of your device. Maybe it is possible with a terminal application but I think that requires root access – Janusz Apr 06 '10 at 18:49
  • Just so we're on the same page: you're not talking about "adb shell" are you? What I'm talking about is different, this is something setup that allows you to set android-specific parameters. I know, for example, you can setup port forwarding (i.e. localhost:1234 goes to phone:1234) without root access, so you can setup a SOCKS proxy and tunnel via a cable w/o root. – Tim Green Apr 06 '10 at 18:58
  • You can use adb forward tcp:6000 tcp:23 to forwward port 6000 on your machine to port 23 on the device but I wasn't able to connect even if the port is shown as open. Using a telnet client on the device and connecting to localhost also fails – Janusz Apr 06 '10 at 19:28
  • Was looking for the way invoke this geo fix from command line, adb emu doesnt work, have you been luckier? – kirhgoff Mar 21 '12 at 16:47
  • 17
    This works fine for the emulator but doesn't work for an actual device. So it doesn't answer OP's question at all :( – Matthew Gilliard Nov 28 '13 at 00:25
  • 4
    @TimGreen Your solution is only for emulator. The question was about real device. – IgorGanapolsky Jan 22 '15 at 21:23
  • if this really adresses the emulator, then this answer is irrelevant because the question was how to do this on a physical device. – axd Dec 12 '16 at 15:58
  • You can use the MockGeoFix app to enable mocking via telnet on a real device. Works very well for me. https://play.google.com/store/apps/details?id=github.luv.mockgeofix – Gert Hengeveld Jan 11 '17 at 14:03
29

You can use the Location Services permission to mock location...

"android.permission.ACCESS_MOCK_LOCATION"

and then in your java code,

// Set location by setting the latitude, longitude and may be the altitude...
String[] MockLoc = str.split(",");
Location location = new Location(mocLocationProvider);            
Double lat = Double.valueOf(MockLoc[0]);
location.setLatitude(lat);
Double longi = Double.valueOf(MockLoc[1]);
location.setLongitude(longi);
Double alti = Double.valueOf(MockLoc[2]);
location.setAltitude(alti);
Vishwanath
  • 1,012
  • 8
  • 9
25

I've had success with the following code. Albeit it got me a single lock for some reason (even if I've tried different LatLng pairs), it worked for me. mLocationManager is a LocationManager which is hooked up to a LocationListener:

private void getMockLocation()
{
    mLocationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
    mLocationManager.addTestProvider
    (
      LocationManager.GPS_PROVIDER,
      "requiresNetwork" == "",
      "requiresSatellite" == "",
      "requiresCell" == "",
      "hasMonetaryCost" == "",
      "supportsAltitude" == "",
      "supportsSpeed" == "",
      "supportsBearing" == "",

      android.location.Criteria.POWER_LOW,
      android.location.Criteria.ACCURACY_FINE
    );      

    Location newLocation = new Location(LocationManager.GPS_PROVIDER);

    newLocation.setLatitude (/* TODO: Set Some Lat */);
    newLocation.setLongitude(/* TODO: Set Some Lng */);

    newLocation.setAccuracy(500);

    mLocationManager.setTestProviderEnabled
    (
      LocationManager.GPS_PROVIDER, 
      true
    );

    mLocationManager.setTestProviderStatus
    (
       LocationManager.GPS_PROVIDER,
       LocationProvider.AVAILABLE,
       null,
       System.currentTimeMillis()
    );      

    mLocationManager.setTestProviderLocation
    (
      LocationManager.GPS_PROVIDER, 
      newLocation
    );      
}
Dr1Ku
  • 2,875
  • 3
  • 47
  • 56
  • As far as I remember, `setTestProviderStatus` is used here to notify/post to/schedule an event with the LocationManager that the GPS provider has found a fix "now" so that processing of the said event can occur. – Dr1Ku Apr 10 '15 at 21:36
  • What is the meaning of "`mLocationManager` is a `LocationManager` which is hooked up to a LocationListener"? how can I do this? Thank you.. – Yehuda Jul 25 '15 at 18:36
  • Here's one article explaining how to check for a location change using the `LocationManager` service and a `LocationListener`: http://blog.doityourselfandroid.com/2010/12/25/understanding-locationlistener-android/ – Dr1Ku Jul 28 '15 at 06:49
  • 2
    plus 1 for the way you represented the true(s) and false(s) in the method addTestProvider – A.Alqadomi Dec 19 '16 at 09:27
16

What Dr1Ku posted works. Used the code today but needed to add more locs. So here are some improvements:

Optional: Instead of using the LocationManager.GPS_PROVIDER String, you might want to define your own constat PROVIDER_NAME and use it. When registering for location updates, pick a provider via criteria instead of directly specifying it in as a string.

First: Instead of calling removeTestProvider, first check if there is a provider to be removed (to avoid IllegalArgumentException):

if (mLocationManager.getProvider(PROVIDER_NAME) != null) {
  mLocationManager.removeTestProvider(PROVIDER_NAME);
}

Second: To publish more than one location, you have to set the time for the location:

newLocation.setTime(System.currentTimeMillis());
...
mLocationManager.setTestProviderLocation(PROVIDER_NAME, newLocation);

There also seems to be a google Test that uses MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java

Another good working example can be found at: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/

Another good article is: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 You'll also find some code that actually works for me on the emulator.

Tianyang Li
  • 1,755
  • 5
  • 26
  • 42
icyerasor
  • 4,973
  • 1
  • 43
  • 52
  • Cool suggestion about defining your own Provider, the thing with using the GPS_PROVIDER is that you (apparently) cannot get rid of the mock provider (more exactly, you cannot switch to normal GPS) until rebooting. Awesome post as well, I'll check out the references ! – Dr1Ku Jan 26 '11 at 16:55
  • @Dr1KU Is it still the case that you cannot switch back to normal GPS? Is that specified somewhere? – Kaz Dragon Nov 21 '13 at 10:24
  • @KazDragon That was the case back then. From what I can recall, after turning the `Mock Provider` on, the normal GPS wouldn't work, I couldn't get a fix (I was testing directly on a device). This may not be the case since a lot has happened in Android since. – Dr1Ku Nov 22 '13 at 10:10
  • @Dr1Ku Ah, well, I'm doing something very similar now and receiving similar results to those you described. I was hoping to know whether this was a restriction built into the platform or that I was just missing a function call somewhere. I should probably make a question out of this. – Kaz Dragon Nov 22 '13 at 10:13
9

There are apps available in the Android Market that allow you to specify a "Mock GPS Location" for your device.

I searched https://market.android.com and found an app called "My Fake Location" that works for me.

The Mock GPS Provider mentioned by Paul above (at http://www.cowlumbus.nl/forum/MockGpsProvider.zip) is another example that includes source code -- although I wasn't able to install the provided APK (it says Failure [INSTALL_FAILED_OLDER_SDK] and may just need a recompile)

In order to use GPS mock locations you need to enable it in your device settings. Go to Settings -> Applications -> Development and check "Allow mock locations"

You can then use an app like the ones described above to set GPS coordinates and Google maps and other apps will use the mock GPS location you specify.

fijiaaron
  • 5,015
  • 3
  • 35
  • 28
8

This worked for me (Android Studio):

Disable GPS and WiFi tracking on the phone. On Android 5.1.1 and below, select "enable mock locations" in Developer Options.

Make a copy of your manifest in the src/debug directory. Add the following to it (outside of the "application" tag):

uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"

Set up a map Fragment called "map". Include the following code in onCreate():

lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
if (lm.getProvider("Test") == null) {
    lm.addTestProvider("Test", false, false, false, false, false, false, false, 0, 1);
}
lm.setTestProviderEnabled("Test", true);
lm.requestLocationUpdates("Test", 0, 0, ll);

map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    @Override
    public void onMapClick(LatLng l) {
        Location loc = new Location("Test");
        loc.setLatitude(l.latitude);
        loc.setLongitude(l.longitude);
        loc.setAltitude(0); 
        loc.setAccuracy(10f);
        loc.setElapsedRealtimeNanos(System.nanoTime());
        loc.setTime(System.currentTimeMillis()); 
        lm.setTestProviderLocation("Test", loc);
    }
};

Note that you may have to temporarily increase "minSdkVersion" in your module gradle file to 17 in order to use the "setElapsedRealtimeNanos" method.

Include the following code inside the main activity class:

private class MyLocationListener implements LocationListener {
    @Override
    public void onLocationChanged(Location location) {
        // do whatever you want, scroll the map, etc.
    }
}

Run your app with AS. On Android 6.0 and above you will get a security exception. Now go to Developer Options in Settings and select "Select mock location app". Select your app from the list.

Now when you tap on the map, onLocationChanged() will fire with the coordinates of your tap.

I just figured this out so now I don't have to tramp around the neighborhood with phones in hand.

Chris B
  • 401
  • 6
  • 10
8

I've created a simple Handler simulating a moving position from an initial position.

Start it in your connection callback :

private final GoogleApiClient.ConnectionCallbacks mConnectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
    @Override
    public void onConnected(Bundle bundle) {
        if (BuildConfig.USE_MOCK_LOCATION) {
            LocationServices.FusedLocationApi.setMockMode(mGoogleApiClient, true);
            new MockLocationMovingHandler(mGoogleApiClient).start(48.873399, 2.342911);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }
};

The Handler class :

   private static class MockLocationMovingHandler extends Handler {

    private final static int SET_MOCK_LOCATION = 0x000001;
    private final static double STEP_LATITUDE =  -0.00005;
    private final static double STEP_LONGITUDE = 0.00002;
    private final static long FREQUENCY_MS = 1000;
    private GoogleApiClient mGoogleApiClient;
    private double mLatitude;
    private double mLongitude;

    public MockLocationMovingHandler(final GoogleApiClient googleApiClient) {
        super(Looper.getMainLooper());
        mGoogleApiClient = googleApiClient;
    }

    public void start(final double initLatitude, final double initLongitude) {
        if (hasMessages(SET_MOCK_LOCATION)) {
            removeMessages(SET_MOCK_LOCATION);
        }
        mLatitude = initLatitude;
        mLongitude = initLongitude;
        sendEmptyMessage(SET_MOCK_LOCATION);
    }

    public void stop() {
        if (hasMessages(SET_MOCK_LOCATION)) {
            removeMessages(SET_MOCK_LOCATION);
        }
    }

    @Override
    public void handleMessage(Message message) {
        switch (message.what) {
            case SET_MOCK_LOCATION:
                Location location = new Location("network");
                location.setLatitude(mLatitude);
                location.setLongitude(mLongitude);
                location.setTime(System.currentTimeMillis());
                location.setAccuracy(3.0f);
                location.setElapsedRealtimeNanos(System.nanoTime());
                LocationServices.FusedLocationApi.setMockLocation(mGoogleApiClient, location);

                mLatitude += STEP_LATITUDE;
                mLongitude += STEP_LONGITUDE;
                sendEmptyMessageDelayed(SET_MOCK_LOCATION, FREQUENCY_MS);
                break;
        }
    }
}

Hope it can help..

smora
  • 717
  • 5
  • 18
7

Add to your manifest

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
    tools:ignore="MockLocation,ProtectedPermissions" />

Mock location function

void setMockLocation() {
    LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false,
            false, false, true, true, true, 0, 5);
    locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);

    Location mockLocation = new Location(LocationManager.GPS_PROVIDER);
    mockLocation.setLatitude(-33.852);  // Sydney
    mockLocation.setLongitude(151.211);
    mockLocation.setAltitude(10);
    mockLocation.setAccuracy(5);
    mockLocation.setTime(System.currentTimeMillis());
    mockLocation.setElapsedRealtimeNanos(System.nanoTime());
    locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockLocation);
}

You'll also need to enable mock locations in your devices developer settings. If that's not available, set the "mock location application" to your application once the above has been implemented.

Ian M
  • 355
  • 3
  • 9
6

The solution mentioned by icyerasor and provided by Pedro at http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/ worked very well for me. However, it does not offer support for properly starting, stopping and restarting the mock GPS provider.

I have changed his code a bit and rewritten the class to be an AsyncTask instead of a Thread. This allows us to communicate with the UI Thread, so we can restart the provider at the point where we were when we stopped it. This comes in handy when the screen orientation changes.

The code, along with a sample project for Eclipse, can be found on GitHub: https://github.com/paulhoux/Android-MockProviderGPS

All credit should go to Pedro for doing most of the hard work.

Paul Houx
  • 1,984
  • 1
  • 14
  • 16
4

The above solutions did not work for me because I was testing on an Android device with the latest Google Play Services version which utilizes the FusedLocationProviderClient. After setting the mock location permission in the app manifest and the app as the specified mock location app in the developer settings (as mentioned in the previous answers), I then added the Kotlin code below which successfully mocked the location.

locationProvider = FusedLocationProviderClient(context)
locationProvider.setMockMode(true)

val loc = Location(providerName)
val mockLocation = Location(providerName) // a string
mockLocation.latitude = latitude  // double
mockLocation.longitude = longitude
mockLocation.altitude = loc.altitude
mockLocation.time = System.currentTimeMillis()
mockLocation.accuracy = 1f
mockLocation.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    mockLocation.bearingAccuracyDegrees = 0.1f
    mockLocation.verticalAccuracyMeters = 0.1f
    mockLocation.speedAccuracyMetersPerSecond = 0.01f
}
//        locationManager.setTestProviderLocation(providerName, mockLocation)
locationProvider.setMockLocation(mockLocation)
John A Qualls
  • 739
  • 1
  • 6
  • 17
  • Where did you place this code? I just placed it in my MainActivity's `onCreate` but it didn't work... I added all the needed permissions and selected my app as mock location in Settings. –  Jan 20 '23 at 19:30
3

Fake GPS app from google play did the trick for me. Just make sure you read all the directions in the app description. You have to disable other location services as well as start your app after you enable "Fake GPS". Worked great for what I needed.

Here is the link to the app on GooglePlay: Fake GPS

Igor
  • 1,212
  • 12
  • 23
2

The Google tutorial for doing this can be found here, it provides code examples and explains the process.

http://developer.android.com/training/location/location-testing.html#SendMockLocations

Nik Pardoe
  • 31
  • 3
2

I wrote an App that runs a WebServer (REST-Like) on your Android Phone, so you can set the GPS position remotely. The website provides an Map on which you can click to set a new position, or use the "wasd" keys to move in any direction. The app was a quick solution so there is nearly no UI nor Documentation, but the implementation is straight forward and you can look everything up in the (only four) classes.

Project repository: https://github.com/juliusmh/RemoteGeoFix

juliusmh
  • 457
  • 3
  • 12
1

If your device is plugged into your computer and your trying to changed send GPS cords Via the Emulator control, it will not work.
This is an EMULATOR control for a reason.
Just set it up to update you on GPS change.

lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);  

    ll = new LocationListener() {        
        public void onLocationChanged(Location location) {  
          // Called when a new location is found by the network location provider.  
            onGPSLocationChanged(location); 
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {       
            bigInfo.setText("Changed "+ status);  
        }

        public void onProviderEnabled(String provider) {
            bigInfo.setText("Enabled "+ provider);
        }

        public void onProviderDisabled(String provider) {
            bigInfo.setText("Disabled "+ provider);
        }
      };

When GPS is updated rewrite the following method to do what you want it to;

public void onGPSLocationChanged(Location location){  
if(location != null){  
    double pLong = location.getLongitude();  
    double pLat = location.getLatitude();  
    textLat.setText(Double.toString(pLat));  
    textLong.setText(Double.toString(pLong));  
    if(autoSave){  
        saveGPS();  
        }
    }
}

Dont forget to put these in the manifest
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Shadoath
  • 720
  • 1
  • 15
  • 31
1

Install Fake GPS app https://play.google.com/store/apps/details?id=com.incorporateapps.fakegps.fre&hl=en

Developer options -> Select mock location app(It's mean, Fake location app selected).

Fake GPS app:

Double tab on the map to add -> click the play button -> Show the toast "Fake location stopped"

finally check with google map apps.

Manikandan K
  • 911
  • 9
  • 21
0

Maybe it's not 'programmer' approach, but if you want save your time and get working solution instant try one of the apps which are dedicated to mock location available in Google Play:

Fake GPS Location Spoofer

Mock Locations

Fake GPS location

klimat
  • 24,711
  • 7
  • 63
  • 70
0

Use this permission in manifest file

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION">

android studio will recommend that "Mock location should only be requested in a test or debug-specific manifest file (typically src/debug/AndroidManifest.xml)" just disable the inspection

Now make sure you have checked the "Allow mock locations" in developer setting of your phone

Use LocationManager

locationManager.addTestProvider(mocLocationProvider, false, false,
                false, false, true, true, true, 0, 5);
locationManager.setTestProviderEnabled(mocLocationProvider, true);

Now set the location wherever you want

Location mockLocation = new Location(mocLocationProvider); 
mockLocation.setLatitude(lat); 
mockLocation.setLongitude(lng); 
mockLocation.setAltitude(alt); 
mockLocation.setTime(System.currentTimeMillis()); 
locationManager.setTestProviderLocation( mocLocationProvider, mockLocation); 
Yu Yenkan
  • 745
  • 1
  • 9
  • 32
0

Make use of the very convenient and free interactive location simulator for Android phones and tablets (named CATLES). It mocks the GPS-location on a system-wide level (even within the Google Maps or Facebook apps) and it works on physical as well as virtual devices:

Website: http://ubicom.snet.tu-berlin.de/catles/index.html

Video: https://www.youtube.com/watch?v=0WSwH5gK7yg

Sandro
  • 1
0

I wonder if you need the elaborate Mock Location setup. In my case once I got a fix location I was calling a function to do something with that new location. In a timer create a mock location. And call the function with that location instead. Knowing all along that in a short while GPS would come up with a real current location. Which is OK. If you have the update time set sufficiently long.

yalcin
  • 11
  • 1