17

How do you test GPS applications in Android? Can we test it using the Android emulator?

Ollie C
  • 28,313
  • 34
  • 134
  • 217
Bharat Pawar
  • 1,867
  • 3
  • 18
  • 23

6 Answers6

27

Yes.

If you develop using the Eclipse ADT plugin, open the DDMS perspective after launching the emulator and look for the Emulator Control view. There is a location controls section that allows you to send fixed latitude and longitude coordinates, or GPX (GPS Exchange Format) or KML (Keyhole Markup Language) files if you want to send multiple coordinates at regular intervals (to simulate traveling a specific route).

Alternatively, you can simply telnet to the emulator and use the geo command from the command line, which supports fixed latitude and longitude coordinates as well as NMEA data sentences:

telnet localhost 5554
geo fix -82.411629 28.054553
geo nmea $GPGGA,001431.092,0118.2653,N,10351.1359,E,0,00,,-19.6,M,4.1,M,,0000*5B
Jeff Gilfelt
  • 26,131
  • 7
  • 48
  • 47
  • 3
    What about testing on a real device -- how can you set your GEO over adb? – fijiaaron Aug 11 '11 at 21:36
  • Thanks a lot. I did that much investigations, and now I have the answer! – eav Sep 13 '12 at 07:35
  • Hi. I had the same problem, I wanted to test on a real device using "geo fix" command, turns out it's not possible out of the box so I wrote an app that provides that functionality :) [MockGeoFix](https://play.google.com/store/apps/details?id=github.luv.mockgeofix&hl=en) and [source code](https://github.com/luv/mockgeofix/) – luv Jul 25 '16 at 00:19
16

Maybe you want to a use a Unit test, so you can try this:

public class GPSPollingServiceTest extends AndroidTestCase {
    private LocationManager locationManager;

    public void testGPS() {
        LocationManager locationManager = (LocationManager) this.getContext().getSystemService(Context.LOCATION_SERVICE);
        locationManager.addTestProvider("Test", false, false, false, false, false, false, false, Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
        locationManager.setTestProviderEnabled("Test", true);

        // Set up your test

        Location location = new Location("Test");
        location.setLatitude(10.0);
        location.setLongitude(20.0);
        locationManager.setTestProviderLocation("Test", location);

        // Check if your listener reacted the right way

        locationManager.removeTestProvider("Test");
    }
}


For this to work you also need a required permission to the AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
Mallox
  • 1,469
  • 12
  • 13
  • Hi, can you please explain a bit more detailed how this code works. How will the activity which responds to location events be actually tested with this ? – Petar Mar 08 '12 at 16:36
  • 1
    Hi, it's been a while, but let's see if I can get it all together again: With the LocationManager you get the systems GPS location manager that notifies your app about changes in position. In the second line you add a new location provider. Since you will be runnin a unit test, you won't have any other location providers registered. Where I marked the "// Set up your test" comment, you can initalize the components you want to test, which should be listening to changes to positions from the LocationManager. – Mallox Mar 14 '12 at 16:14
  • After that you send a new location to the location manager and your code which you want to test should do something with that information, so that you can check afterwards if it did the right thing. Finally you want to remove the test provider, so that there aren't several location providers for testing, if you write other tests. (even though junit will probably clean that up properly) – Mallox Mar 14 '12 at 16:20
  • So, how would that work if the component that listen to location changes is an Activity ? – Petar Jun 13 '12 at 15:16
  • It gives error about incomplete Location, perhaps you should add code from http://jgrasstechtips.blogspot.it/2012/12/android-incomplete-location-object.html. This worked for me. – dragoon Jun 06 '13 at 09:00
3

Perhaps this test application or this can help you.

leifericf
  • 2,324
  • 3
  • 26
  • 37
2

in addition to Mallox code this is the sulotion for mock location in addition to real gps location : TEST_MOCK_GPS_LOCATION is a string

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    Location location = null;

    List providers = lm.getAllProviders();
    for (Object provider : providers) {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Location loc = lm.getLastKnownLocation((String) provider);
        if  (provider.equals(TEST_MOCK_GPS_LOCATION))  {
            mLastLocation = loc;
        }
    } 

in the test class it is :

public class GPSPollingServiceTest extends AndroidTestCase {
private LocationManager locationManager;

public void testGPS() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    LocationManager locationManager = (LocationManager) this.getContext().getSystemService(Context.LOCATION_SERVICE);
    List providers = locationManager.getAllProviders();
    if(!providers.contains(TEST_MOCK_GPS_LOCATION)) {
        locationManager.addTestProvider(TEST_MOCK_GPS_LOCATION, false, false, false, false, false, false, false, Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
        locationManager.setTestProviderEnabled(TEST_MOCK_GPS_LOCATION, true);
        // Set up your test
        Location location = new Location(TEST_MOCK_GPS_LOCATION);
        location.setLatitude(34.1233400);
        location.setLongitude(15.6777880);
        location.setAccuracy(7);
        location.setTime(8);
        location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());

        locationManager.setTestProviderLocation(TEST_MOCK_GPS_LOCATION, location);

        Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
        if (locationJellyBeanFixMethod != null) {
            locationJellyBeanFixMethod.invoke(location);
        }
    } else {
        // Check if your listener reacted the right way
        locationManager.removeTestProvider(TEST_MOCK_GPS_LOCATION);
    }
}

}

hope it will help you

spring26
  • 21
  • 2
1

In the Extended controls of your emulator (click "..." on the control bar next to your emulator) there is the Location tab, where you can either manually input individual locations (latitude / longitude / altitude) and send them to the virtual device, or setup GPS data playback at a desired speed from a GPX or a KML file you can import.

Edit: it's the default Android Emulator I'm talking about.

0

I suggest that you write test which is sending location object to the listener class you want to test. With this in mind you will need some helper methods that will be able to produce location objects.

E.g.:

First you send a location with fixed coordinates (e.g. center of New York).

// test if everything is OK

Than you send a coordinate which is 100m appart from the first coordinate. You can do this with function I implemented recently: https://stackoverflow.com/a/17545955/322791

// test if everything is OK

It is common that GPS methods are related to time. I suggest that you implement method getNow() on listener class and call it whenever you need current time.

long getNow() {
    if (isUnitTesting) {
         return unitTestTime;
    } else {
         System.getcurrenttimemillis();
    }
}

In unit test environment you simply set the obj.isUnitTesting=true and obj.unitTestTime to any time you want. After that you can send first location to the listener, then you change time (+x seconds) and send another location ...

It will be much easier to test your application that way.

Community
  • 1
  • 1
knagode
  • 5,816
  • 5
  • 49
  • 65