I'm trying to get mock updates from FusedLocationProviderApi
, but I can't seem to make it work. This my set up method in android instrumentation test:
locationProvider = new LocationProvider(InstrumentationRegistry.getTargetContext().getApplicationContext(), settings);
// Connect first, so that we don't receive 'true' location
locationProvider.googleApiClient.blockingConnect();
// Set mock mode, to receive only mock locations
LocationServices.FusedLocationApi.setMockMode(locationProvider.googleApiClient, true);
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
// Start receiving locations; this call will connect api client, and if it's already connected (or after it connects) it will register for location updates
locationProvider.start();
}
});
// wait until we can request location updates
while (!locationProvider.isReceivingLocationUpdates) {
Thread.sleep(10);
}
After this point I would expect any calls to LocationServices.fusedLocationApi.setMockLocation(apiClient, location)
to set mock location that my listener would receive. Unfortunately this is not the case, and the listener stays silent.
My foolproof (or so I thought) method to set mock location looks like this:
private void setMockLocation(final Location location) throws Exception {
assertTrue(locationProvider.googleApiClient.isConnected());
assertTrue(locationProvider.isReceivingLocationUpdates);
final CountDownLatch countDownLatch = new CountDownLatch(1);
LocationServices.FusedLocationApi.setMockMode(locationProvider.googleApiClient, true)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
assertTrue(status.isSuccess());
LocationServices.FusedLocationApi.setMockLocation(locationProvider.googleApiClient, location)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
assertTrue(status.isSuccess());
countDownLatch.countDown();
}
});
}
});
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
}
Method returns successfully, but no location is received by the listener. I'm really at a loss here. The worst part is sometimes the test would pass, but extremely randomly (to a point when the same code executed several times would pass and fail in subsequent calls). My debug manifest, for completeness, has following permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
I have allowed mock locations in settings.
Simple, battery-efficient location API for Android The fused location provider is a location API in Google Play services that intelligently combines different signals to provide the location information that your app needs.
this us an updated kotlin version. Be aware that you need to pick the app as a mock location provider in development options, and have permissions to do it set in a debug manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
tools:ignore="ProtectedPermissions" />
</manifest>
An activity would have a val with initializer in onCreate
private lateinit var fusedLocationClient: FusedLocationProviderClient
in oncreate()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.setMockMode(BuildConfig.DEBUG)
fusedLocationClient.lastLocation
.addOnSuccessListener { location : android.location.Location? ->
// Got last known location. In some rare situations this can be null.
Toast.makeText(this, location.toString(), Toast.LENGTH_SHORT).show()
}
.addOnFailureListener { Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show() }
and finally a way to mock a location
private fun setMockLocation(location: android.location.Location) {
fusedLocationClient.setMockLocation(location)
.addOnSuccessListener { Log.d(TAG, "location mocked") }
.addOnFailureListener { Log.d(TAG, "mock failed") }
}
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