gps - Android mock location on device?


Translate

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.


All Answers
  • Translate

    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.


  • Translate

    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.


  • Translate

    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).


  • Translate

    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);
    

  • Translate

    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
        );      
    }
    

  • Translate

    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.


  • Translate

    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.


  • Translate

    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.


  • Translate

    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..


  • Translate

    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.


  • Translate

    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


  • Translate

    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


  • Translate

    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.


  • Translate

    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


  • Translate

    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


  • Translate

    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.


  • Translate

    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.


  • Translate

    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


  • Translate

    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


  • Translate

    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);