I'm targeting Google API 2.3.3 and have the following test class
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.util.Log;
public class MockLocationManagerTests extends AndroidTestCase implements LocationListener{
private static final String TAG = "MockLocationTests";
private String locationProvider = "TestProvider";
private LocationManager locationManager;
private Location lastLocation;
protected void setUp() throws Exception {
super.setUp();
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
if (Settings.Secure.getInt(getContext().getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
fail("Mock location must be enabled");
}
setupLocationManager();
}
private void setupLocationManager() {
if (locationManager.getProvider(locationProvider) != null) {
locationManager.removeTestProvider(locationProvider);
}
locationManager.addTestProvider(locationProvider,
false,
true,
false,
false,
false,
false,
false,
Criteria.POWER_LOW,
Criteria.ACCURACY_FINE);
locationManager.requestLocationUpdates(locationProvider, 0, 0, this);
locationManager.setTestProviderStatus(locationProvider, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
locationManager.setTestProviderEnabled(locationProvider, true);
}
private Location createLocation(double lat, double lon) {
Location location = new Location(locationProvider);
location.setLatitude(lat);
location.setLongitude(lon);
location.setAltitude(0);
location.setTime(System.currentTimeMillis());
return location;
}
protected void tearDown() throws Exception {
super.tearDown();
}
public final void testCanObserveLocationChanging() throws InterruptedException {
Location l = createLocation(19,-2);
locationManager.setTestProviderLocation(locationProvider,l);
synchronized(this){
wait(5000);
}
Location l2 = createLocation(1,-10);
locationManager.setTestProviderLocation(locationProvider,l2);
synchronized(this){
wait(5000);
}
assertEquals(l,lastLocation);
}
public void onLocationChanged(Location location) {
Log.i(TAG,"location changed");
lastLocation = location;
}
public void onProviderDisabled(String provider) {
Log.i(TAG, provider+" disabled");
}
public void onProviderEnabled(String provider) {
Log.i(TAG, provider+" enabled");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.i(TAG,"status changed: "+provider+" to "+status);
}
}
onLocationChanged is not being called and my google-fu and brain-fu is failing me. Any advice greatly appreciated
UPDATE
none of the log messages are caught so onStatusChanged and onProviderEnabled aren't firing?
If I call getLastKnownLocation()
between calls to setTestProviderLocation()
the locationManager returns the location I've set
ANOTHER UPDATE
If I add the class that utilises this code to my application then onLocationChanged() is called. The only difference being that I'm not using a Mock_Location. So it does seem that setTestProviderLocation() is not causing onLocationChanged() to fire
Behaves same way on Google API 19.
The AndroidTestCase doesn't setup a proper Looper for handling of the update events. You have to run it as a test activity ActivityInstrumentationTestCase2 or add a ThreadLooper to the AndroidTestCase to deal with the update messages.
Looper mLooper;
HandlerThread thread = new HandlerThread("LocationHandlerThread");
thread.start(); // starts the thread.
mLooper = thread.getLooper();
Then use the new Looper in the requestLocationUpdates method:
mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, mLocationListener, mLooper);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With