diff --git a/gradle.properties b/gradle.properties index 2af75a4..2132bbc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,3 +14,5 @@ POM_LICENCE_DIST=repo POM_DEVELOPER_ID=Mapzen POM_DEVELOPER_NAME=Mapzen + +org.gradle.jvmargs=-Xmx1536m diff --git a/lost-sample/src/main/java/com/example/lost/MultipleLocationListenerMultipleClientsActivity.java b/lost-sample/src/main/java/com/example/lost/MultipleLocationListenerMultipleClientsActivity.java index 795afaf..eb69592 100644 --- a/lost-sample/src/main/java/com/example/lost/MultipleLocationListenerMultipleClientsActivity.java +++ b/lost-sample/src/main/java/com/example/lost/MultipleLocationListenerMultipleClientsActivity.java @@ -73,7 +73,6 @@ public void onConnectionSuspended() { super.onStop(); LocationServices.FusedLocationApi.removeLocationUpdates(lostApiClient, MultipleLocationListenerMultipleClientsActivity.this); - fragment.removeLocationUpdates(); lostApiClient.disconnect(); } @@ -145,12 +144,9 @@ public void onConnectionSuspended() { fragmentClient.connect(); } - public void removeLocationUpdates() { - LocationServices.FusedLocationApi.removeLocationUpdates(fragmentClient, this); - } - @Override public void onStop() { super.onStop(); + LocationServices.FusedLocationApi.removeLocationUpdates(fragmentClient, this); fragmentClient.disconnect(); } diff --git a/lost/src/main/java/com/mapzen/android/lost/api/FusedLocationProviderApi.java b/lost/src/main/java/com/mapzen/android/lost/api/FusedLocationProviderApi.java index 4b82ab0..f843e88 100644 --- a/lost/src/main/java/com/mapzen/android/lost/api/FusedLocationProviderApi.java +++ b/lost/src/main/java/com/mapzen/android/lost/api/FusedLocationProviderApi.java @@ -25,6 +25,7 @@ public interface FusedLocationProviderApi { * The best accuracy available while respecting the location permissions will be returned. * @param client The client to return location for. * @return The best, most recent location available. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) Location getLastLocation(LostApiClient client); @@ -40,6 +41,7 @@ public interface FusedLocationProviderApi { * * @param client The client to return availability for. * @return The availability of location data. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) LocationAvailability getLocationAvailability(LostApiClient client); @@ -57,6 +59,7 @@ public interface FusedLocationProviderApi { * @param request Specifies desired location accuracy, update interval, etc. * @param listener Listener to make calls on when location becomes available. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, @@ -76,6 +79,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param listener Listener to make calls on when location becomes available. * @param looper Looper to implement the listener callbacks on. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, @@ -95,6 +99,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param callback Callback to make calls on when location becomes available. * @param looper Looper to implement the listener callbacks on. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, @@ -119,6 +124,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param request Specifies desired location accuracy, update interval, etc. * @param callbackIntent Intent to be sent for each location update. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, @@ -127,27 +133,33 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque /** * Removes location updates for the {@link LocationListener} * - * @param client Client which registered the listener. + * @param client Client which registered the listener. The client must be connected at the time + * of this call. * @param listener Listener to remove updates for. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult removeLocationUpdates(LostApiClient client, LocationListener listener); /** * Removes location updates for the {@link PendingIntent} * - * @param client Client which registered the listener. + * @param client Client which registered the pending intent. The client must be connected at the + * time of this call. * @param callbackIntent Intent to remove updates for. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult removeLocationUpdates(LostApiClient client, PendingIntent callbackIntent); /** * Remove location updates for the {@link LocationCallback} * - * @param client Client which registered the listener. + * @param client Client which registered the location callback. The client must be connected at + * the time of this call. * @param callback Callback to remove updates for. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult removeLocationUpdates(LostApiClient client, LocationCallback callback); @@ -162,6 +174,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param client Connected client. * @param isMockMode Whether mock mode should be enabled or not. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult setMockMode(LostApiClient client, boolean isMockMode); @@ -173,6 +186,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param client Connected client. * @param mockLocation Location to be set for the location provider. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult setMockLocation(LostApiClient client, Location mockLocation); @@ -184,6 +198,7 @@ PendingResult requestLocationUpdates(LostApiClient client, LocationReque * @param client Connected client. * @param file GPX file to be used to report location. * @return a {@link PendingResult} for the call to check whether call was successful. + * @throws IllegalStateException if the client is not connected at the time of this call. */ PendingResult setMockTrace(LostApiClient client, final File file); diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java index 671ea61..d3da9b3 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java @@ -97,15 +97,18 @@ public boolean isConnected() { } @Override public Location getLastLocation(LostApiClient client) { + throwIfNotConnected(client); return service.getLastLocation(client); } @Override public LocationAvailability getLocationAvailability(LostApiClient client) { + throwIfNotConnected(client); return service.getLocationAvailability(client); } @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, LocationListener listener) { + throwIfNotConnected(client); return service.requestLocationUpdates(client, request, listener); } @@ -116,40 +119,48 @@ public boolean isConnected() { @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, LocationCallback callback, Looper looper) { + throwIfNotConnected(client); return service.requestLocationUpdates(client, request, callback, looper); } @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, PendingIntent callbackIntent) { + throwIfNotConnected(client); return service.requestLocationUpdates(client, request, callbackIntent); } @Override public PendingResult removeLocationUpdates(LostApiClient client, LocationListener listener) { + throwIfNotConnected(client); return service.removeLocationUpdates(client, listener); } @Override public PendingResult removeLocationUpdates(LostApiClient client, PendingIntent callbackIntent) { + throwIfNotConnected(client); return service.removeLocationUpdates(client, callbackIntent); } @Override public PendingResult removeLocationUpdates(LostApiClient client, LocationCallback callback) { + throwIfNotConnected(client); return service.removeLocationUpdates(client, callback); } @Override public PendingResult setMockMode(LostApiClient client, boolean isMockMode) { + throwIfNotConnected(client); return service.setMockMode(client, isMockMode); } @Override public PendingResult setMockLocation(LostApiClient client, Location mockLocation) { + throwIfNotConnected(client); return service.setMockLocation(client, mockLocation); } @Override public PendingResult setMockTrace(LostApiClient client, File file) { + throwIfNotConnected(client); return service.setMockTrace(client, file); } @@ -172,4 +183,10 @@ void removeConnectionCallbacks(LostApiClient.ConnectionCallbacks callbacks) { FusedLocationServiceConnectionManager getServiceConnectionManager() { return serviceConnectionManager; } + + private void throwIfNotConnected(LostApiClient client) { + if (!client.isConnected()) { + throw new IllegalStateException("LostApiClient is not connected."); + } + } } diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java index 3f0bc45..ef1160f 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java @@ -107,71 +107,233 @@ private void mockService() { verify(connectionManager).isConnected(); } - @Test public void getLastLocation_shouldCallService() { + @Test(expected = IllegalStateException.class) + public void getLastLocation_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); api.getLastLocation(client); - verify(service).getLastLocation(client); } - @Test public void getLocationAvailability_shouldCallService() { + @Test public void getLastLocation_shouldCallService() { + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + api.getLastLocation(client); + verify(service).getLastLocation(client); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); + } + + @Test(expected = IllegalStateException.class) + public void getLocationAvailability_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); api.getLocationAvailability(client); - verify(service).getLocationAvailability(client); + } + + @Test public void getLocationAvailability_shouldCallService() { + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + api.getLocationAvailability(client); + verify(service).getLocationAvailability(client); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); + } + + @Test(expected = IllegalStateException.class) + public void requestLocationUpdates_listener_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.requestLocationUpdates(client, LocationRequest.create(), new TestLocationListener()); + } + + @Test(expected = IllegalStateException.class) + public void requestLocationUpdates_pendingIntent_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.requestLocationUpdates(client, LocationRequest.create(), mock(PendingIntent.class)); + } + + @Test(expected = IllegalStateException.class) + public void requestLocationUpdates_callback_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.requestLocationUpdates(client, LocationRequest.create(), new TestLocationCallback(), + Looper.myLooper()); } @Test public void requestLocationUpdates_listener_shouldCallService() { - LocationRequest request = LocationRequest.create(); - LocationListener listener = new TestLocationListener(); - api.requestLocationUpdates(client, request, listener); - verify(service).requestLocationUpdates(client, request, listener); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + LocationRequest request = LocationRequest.create(); + LocationListener listener = new TestLocationListener(); + api.requestLocationUpdates(client, request, listener); + verify(service).requestLocationUpdates(client, request, listener); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); + } + + @Test public void requestLocationUpdates_pendingIntent_shouldCallService() { + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + LocationRequest request = LocationRequest.create(); + PendingIntent pendingIntent = mock(PendingIntent.class); + api.requestLocationUpdates(client, request, pendingIntent); + verify(service).requestLocationUpdates(client, request, pendingIntent); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); + } + + @Test public void requestLocationUpdates_callback_shouldCallService() { + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + LocationRequest request = LocationRequest.create(); + TestLocationCallback callback = new TestLocationCallback(); + Looper looper = Looper.myLooper(); + api.requestLocationUpdates(client, request, callback, looper); + verify(service).requestLocationUpdates(client, request, callback, looper); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test(expected = RuntimeException.class) - public void requestLocationUpdates_shouldThrowException() { + public void requestLocationUpdates_listenerWithLooper_shouldThrowExceptionIfNotYetImplemented() { LocationRequest request = LocationRequest.create(); TestLocationListener listener = new TestLocationListener(); api.requestLocationUpdates(client, request, listener, null); } - @Test public void requestLocationUpdates_callback_shouldCallService() { - LocationRequest request = LocationRequest.create(); - TestLocationCallback callback = new TestLocationCallback(); - Looper looper = Looper.myLooper(); - api.requestLocationUpdates(client, request, callback, looper); - verify(service).requestLocationUpdates(client, request, callback, looper); + @Test(expected = IllegalStateException.class) + public void removeLocationUpdates_listener_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.removeLocationUpdates(client, new TestLocationListener()); + } + + @Test(expected = IllegalStateException.class) + public void removeLocationUpdates_pendingIntent_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.removeLocationUpdates(client, mock(PendingIntent.class)); + } + + @Test(expected = IllegalStateException.class) + public void removeLocationUpdates_callback_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.removeLocationUpdates(client, new TestLocationCallback()); } @Test public void removeLocationUpdates_listener_shouldCallService() { - LocationListener listener = new TestLocationListener(); - api.removeLocationUpdates(client, listener); - verify(service).removeLocationUpdates(client, listener); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + LocationListener listener = new TestLocationListener(); + api.removeLocationUpdates(client, listener); + verify(service).removeLocationUpdates(client, listener); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test public void removeLocationUpdates_pendingIntent_shouldCallService() { - PendingIntent callbackIntent = mock(PendingIntent.class); - api.removeLocationUpdates(client, callbackIntent); - verify(service).removeLocationUpdates(client, callbackIntent); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + PendingIntent callbackIntent = mock(PendingIntent.class); + api.removeLocationUpdates(client, callbackIntent); + verify(service).removeLocationUpdates(client, callbackIntent); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test public void removeLocationUpdates_callback_shouldCallService() { - TestLocationCallback callback = new TestLocationCallback(); - service.removeLocationUpdates(client, callback); - verify(service).removeLocationUpdates(client, callback); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + TestLocationCallback callback = new TestLocationCallback(); + api.removeLocationUpdates(client, callback); + verify(service).removeLocationUpdates(client, callback); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } - @Test public void setMockMode_shouldCallService() { + @Test(expected = IllegalStateException.class) + public void setMockMode_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); api.setMockMode(client, true); - verify(service).setMockMode(client, true); + } + + @Test(expected = IllegalStateException.class) + public void setMockLocation_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.setMockLocation(client, new Location("test")); + } + + @Test(expected = IllegalStateException.class) + public void setMockTrace_shouldThrowIfNotConnected() throws Exception { + client.disconnect(); + api.setMockTrace(client, new File("path", "name")); + } + + @Test public void setMockMode_shouldCallService() { + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + api.setMockMode(client, true); + verify(service).setMockMode(client, true); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test public void setMockLocation_shouldCallService() { - Location location = new Location("test"); - api.setMockLocation(client, location); - verify(service).setMockLocation(client, location); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + Location location = new Location("test"); + api.setMockLocation(client, location); + verify(service).setMockLocation(client, location); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test public void setMockTrace_shouldCallService() { - File file = new File("path", "name"); - api.setMockTrace(client, file); - verify(service).setMockTrace(client, file); + new LostApiClient.Builder(mock(Context.class)) + .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks() { + @Override public void onConnected() { + File file = new File("path", "name"); + api.setMockTrace(client, file); + verify(service).setMockTrace(client, file); + } + + @Override public void onConnectionSuspended() { + } + }).build().connect(); } @Test public void isProviderEnabled_shouldCallService() { diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/LostApiClientImplTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/LostApiClientImplTest.java index 3873cea..dd35eaf 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/LostApiClientImplTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/LostApiClientImplTest.java @@ -44,6 +44,10 @@ public class LostApiClientImplTest extends BaseRobolectricTest { @After public void tearDown() throws Exception { client.disconnect(); + ((FusedLocationProviderApiImpl) LocationServices.FusedLocationApi) + .getServiceConnectionManager() + .getConnectionCallbacks() + .clear(); } @Test public void connect_shouldConnectFusedLocationProviderApiImpl() throws Exception {