Pedro Assunção

Android location provider mock

So, yeah, I resumed playing around with android, this time version 2.0.

I’m really tempted to buy the new Motorola Milestone that should come out in Europe sometime between… now… and early next year, so I wanna be ready to create all the crazy stuff I have in mind for it :)

One of the things I noticed was that it’s not that straightforward to provide sample GPS data. Somehow the emulator’s GPX and KMZ functionality is not working fine for me and, even if it was, I don’t want to load the file everytime (i.e. I’m lazy).

So, after some googling around, here’s my solution to read points from a file and feed them 1 per second to the location manager, so I can finally work with them in my app:

My main activity implements LocationListener, so it can be passed to the LocationManager to receive GPS events. Here’s what I do when creating my activity:

public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		((TextView) this.findViewById(R.id.textView)).setText("Something else");

		// LocationManager locationManager = (LocationManager)
		// getSystemService(Context.LOCATION_SERVICE);
		// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
		// 0, 0, this);

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

		String mocLocationProvider = LocationManager.GPS_PROVIDER;
		locationManager.addTestProvider(mocLocationProvider, false, false,
				false, false, true, true, true, 0, 5);
		locationManager.setTestProviderEnabled(mocLocationProvider, true);
		locationManager.requestLocationUpdates(mocLocationProvider, 0, 0, this);

		try {

			List data = new ArrayList();
			InputStream is = getAssets().open("data.txt");
			BufferedReader reader = new BufferedReader(new InputStreamReader(is));
			String line = null;
			while ((line = reader.readLine()) != null) {

				data.add(line);
			}
			Log.e(LOG_TAG, data.size() + " lines");

			new MockLocationProvider(locationManager, mocLocationProvider, data).start();

		} catch (IOException e) {

			e.printStackTrace();
		}
	}

This will basically setup the test location provider and read the points into a list. Then I feed that stuff to my mock location provider (just a normal thread) that will read them 1 per second and trigger the new location back to this activity. Here’s the code for MockLocationProvider:

public class MockLocationProvider extends Thread {

    private List data;

    private LocationManager locationManager;

    private String mocLocationProvider;

    private String LOG_TAG = "faren";

    public MockLocationProvider(LocationManager locationManager,
            String mocLocationProvider, List data) throws IOException {

        this.locationManager = locationManager;
        this.mocLocationProvider = mocLocationProvider;
        this.data = data;
    }

    @Override
    public void run() {

        for (String str : data) {

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();
            }

            // Set one position
            String[] parts = str.split(",");
            Double latitude = Double.valueOf(parts[0]);
            Double longitude = Double.valueOf(parts[1]);
            Double altitude = Double.valueOf(parts[2]);
            Location location = new Location(mocLocationProvider);
            location.setLatitude(latitude);
            location.setLongitude(longitude);
            location.setAltitude(altitude);

            Log.e(LOG_TAG, location.toString());

            // set the time in the location. If the time on this location
            // matches the time on the one in the previous set call, it will be
            // ignored
            location.setTime(System.currentTimeMillis());

            locationManager.setTestProviderLocation(mocLocationProvider,
                    location);
        }
    }
}

Notice the location.setTime() call. Read the comment why it is necessary. Took me forever to find this one in google :D

Peace and great Androiding ;)

Related:

  1. Double click/tap detection on android’s MapView If there is a cleaner way to do it, please...
  2. Double click/tap detection on android’s MapView   If there is a cleaner way to do it,...


Categorised as: code snipplets, computers, software development, tips


21 Comments

  1. Lily says:

    Hello I had disactived all GPS provider on my google phone but I have this error when I launch the MockGpsProvider:
    "disable the GPS receiver in this device to use the mock gps provier"

    Any ideas?
    Thanks

    Lily

  2. Paul says:

    Hey,

    thanks for sharing this code. It was a great solution to test my GPS enabled Android app, because the emulator isn't working well for me (my application uses rather big digital maps in Bitmap format and the emulator keeps crashing).

    I rewrote the code to make better use of the AsyncTask class. It provides a better way to control the Thread once it is started and also provides support for orientation changes (savedInstanceState).

    You can download the code here: http://www.cowlumbus.nl/forum/MockGpsProvider.zip

    Probably the easiest way to compile it is to extract the ZIP and then use the 'Import > General > Exisiting Projects into Workspace' Eclipse function. Browse to the folder and click Finish.

    Paul

    • pbc says:

      Nocivus & Paul,
      Thanks for sharing.
      I am working a project where I am trying to use mock locations to simulate a driving route in Google's Navigation application. Do you guys have experience with anything similar? I can get the mock location to show up on the map but the Nav app will not recalculate the route without the GPS signal. Just wondering if anyone had any thoughts on how to fake the application into thinking that the mock location is the GPS signal. I'm using
      String mocLocationProvider = LocationManager.GPS_PROVIDER;
      locationManager.addTestProvider(mocLocationProvider, false, false,
      false, false, true, true, true, 0, 5);
      locationManager.setTestProviderEnabled(mocLocationProvider, true);
      locationManager.requestLocationUpdates(mocLocationProvider, 0, 0, this);
      but still no luck. Any help would be appreciated. Thanks.

  3. Beefheart says:

    Thanks for that code. It just saved me hours.

  4. sridhar says:

    Hi I followed ur steps..

    but i dnt know where i am wrong..can u please mail me the full souce code…my id(lokeshbooks@gmail.com).. I am need of it friend..thanks in advance.

    • nocivus says:

      Hi Sridhar,

      keep in mind that this is old code (don't recall if android 1.6 or 2.0) so it's very likely that it has changed in the meantime.

      That being said, what i posted is pretty much all the code. The rest is just wiring that you should be able to put together from any simple android project tutorial.

  5. nocivus says:

    The file is a comma-separated file containing one triplet per line (latitude, longitude, altitude). You put in that file the values you want the mock to simulate :)

    • sridhar says:

      i used following code instead of reading from file i set the latitude and logitude directly..But it didnt worked for me(in google maps i didnt see any blinking)..

      public class GpsLocation extends Activity implements LocationListener {
      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      //((TextView) this.findViewById(R.id.textView)).setText("Something else");

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

      String mocLocationProvider = LocationManager.GPS_PROVIDER;
      locationManager.addTestProvider(mocLocationProvider, false, false,
      false, false, true, true, true, 0, 5);
      locationManager.setTestProviderEnabled(mocLocationProvider, true);
      locationManager.requestLocationUpdates(mocLocationProvider, 0, 0,this);

      new MockLocationProvider(locationManager, mocLocationProvider).start();

      }

      }

      • sridhar says:

        public class MockLocationProvider extends Thread {
        private LocationManager locationManager;
        private String mocLocationProvider;
        public MockLocationProvider(LocationManager locationManager,
        String mocLocationProvider) {
        this.locationManager = locationManager;
        this.mocLocationProvider = mocLocationProvider;
        }

        @Override
        public void run() {

        Double latitude = 17.408305;
        Double longitude = 78.465729;
        Location location = new Location(mocLocationProvider);
        location.setLatitude(latitude);
        location.setLongitude(longitude);
        location.setTime(System.currentTimeMillis());

        locationManager.setTestProviderLocation(mocLocationProvider,
        location);
        }
        }

  6. sridhar says:

    please can anyone say wats that file in assests

  7. Syb says:

    I used this tutorial and the only thing i changed was the name of the locationprovider. I changed it to test. And now some other applications of mine that use GPS use the test location provider as well, how can i properly delete the locatoinprovider in order to not use the test provider in other applications?

  8. Natasha says:

    Thanks so much for your reply, Pedro. I implemented the tutorial but LocMgr.addTestLocProvider may have changed from what I was able to gather on the forum. It seems you just need to provide route file pushed onto data/misc/location and it will get pick up by a default mock loc provider. This seems to be only on the emulator. The Adroid Applicatios Settings allow for Mock Loc Provider. So, I am not how to simulate a travel via LocMgr and mock loc provider. I ended up using Handler.postDelay to update loc overlay

  9. natasha says:

    I am not able to get location updates on my listener. My thread runs forever with locMgr.setTestLoc to no avail. I provided perm to MOCK_LOC_UPDDATE. I am using sdk 7. Am I missing a configuration req?

    • Hi Natasha, i haven’t looked into this in a while now. Maybe the latest updates changed something that makes it not work anymore. I would suggest looking at the release change logs for the SDK since version 2.0 and see if something changed that could affect this :(

      Sorry for not being able to help, but i’m full of work right now :(

  10. Dave says:

    Nice code! Worked great for me,
    thanks a lot for sharing it here!

    Dave

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>