diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java index 22f6138..65510ca 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProvider.java @@ -14,7 +14,6 @@ import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationSettingsResponse; import com.google.android.gms.location.LocationSettingsStatusCodes; -import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.yayandroid.locationmanager.constants.FailType; import com.yayandroid.locationmanager.constants.ProcessType; @@ -39,10 +38,8 @@ public class GooglePlayServicesLocationProvider extends LocationProvider impleme @Override public void onResume() { - // not getSourceProvider, because we don't want to connect if it is not already attempt - if (!settingsDialogIsOn && googlePlayServicesLocationSource != null && - (isWaiting() || getConfiguration().keepTracking())) { - onConnected(); + if (!settingsDialogIsOn && (isWaiting() || getConfiguration().keepTracking())) { + requestLocationUpdate(); } } @@ -72,7 +69,17 @@ public void get() { setWaiting(true); if (getContext() != null) { - onConnected(); + LogUtils.logI("Start request location updates."); + + if (getConfiguration().googlePlayServicesConfiguration().ignoreLastKnowLocation()) { + LogUtils.logI("Configuration requires to ignore last know location from GooglePlayServices Api."); + + // Request fresh location + locationRequired(); + } else { + // Try to get last location, if failed then request fresh location + getSourceProvider().requestLastLocation(); + } } else { failed(FailType.VIEW_DETACHED); } @@ -105,21 +112,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } - @Override - public void onConnected() { - LogUtils.logI("Start request location updates."); - - if (getConfiguration().googlePlayServicesConfiguration().ignoreLastKnowLocation()) { - LogUtils.logI("Configuration requires to ignore last know location from GooglePlayServices Api."); - - // Request fresh location - requestLocation(false); - } else { - // Try to get last location, if failed then request fresh location - checkLastKnowLocation(); - } - } - public void onLocationChanged(@NonNull Location location) { if (getListener() != null) { getListener().onLocationChanged(location); @@ -204,43 +196,25 @@ void resolveSettingsApi(@NonNull ResolvableApiException resolvable) { } } - void checkLastKnowLocation() { - getSourceProvider().getLastLocation() - .addOnCompleteListener(new OnCompleteListener() { - @Override - public void onComplete(@NonNull Task task) { - /* - * Returns the best most recent location currently available. - * - * If a location is not available, which should happen very rarely, null will be returned. - * The best accuracy available while respecting the location permissions will be returned. - * - * This method provides a simplified way to get location. - * It is particularly well suited for applications that do not require an accurate location and that do not want to maintain extra logic for location updates. - * - * GPS location can be null if GPS is switched off - */ - if (task.isSuccessful() && task.getResult() != null) { - Location lastKnownLocation = task.getResult(); - - LogUtils.logI("LastKnowLocation is available."); - onLocationChanged(lastKnownLocation); - - requestLocation(true); - } else { - LogUtils.logI("LastKnowLocation is not available."); - - requestLocation(false); - } - } - }); - } + /** + * Task result can be null in certain conditions + * See: https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient#getLastLocation() + */ + @Override + public void onLastKnowLocationTaskReceived(@NonNull Task task) { + if (task.isSuccessful() && task.getResult() != null) { + Location lastKnownLocation = task.getResult(); - void requestLocation(boolean locationIsAlreadyAvailable) { - if (getConfiguration().keepTracking() || !locationIsAlreadyAvailable) { - locationRequired(); + LogUtils.logI("LastKnowLocation is available."); + onLocationChanged(lastKnownLocation); + + if (getConfiguration().keepTracking()) { + LogUtils.logI("Configuration requires keepTracking."); + locationRequired(); + } } else { - LogUtils.logI("We got location, no need to ask for location updates."); + LogUtils.logI("LastKnowLocation is not available."); + locationRequired(); } } diff --git a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java index c438152..ff4c819 100644 --- a/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java +++ b/library/src/main/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationSource.java @@ -17,6 +17,7 @@ import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationSettingsRequest; import com.google.android.gms.location.LocationSettingsResponse; +import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; @@ -29,13 +30,13 @@ class GooglePlayServicesLocationSource extends LocationCallback { private final SourceListener sourceListener; interface SourceListener extends OnSuccessListener, OnFailureListener { - void onConnected(); - void onSuccess(LocationSettingsResponse locationSettingsResponse); void onFailure(@NonNull Exception exception); void onLocationResult(@Nullable LocationResult locationResult); + + void onLastKnowLocationTaskReceived(@NonNull Task task); } GooglePlayServicesLocationSource(Context context, LocationRequest locationRequest, SourceListener sourceListener) { @@ -54,7 +55,8 @@ void checkLocationSettings() { .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(LocationSettingsResponse locationSettingsResponse) { - if (sourceListener != null) sourceListener.onSuccess(locationSettingsResponse); + if (sourceListener != null) + sourceListener.onSuccess(locationSettingsResponse); } }) .addOnFailureListener(new OnFailureListener() { @@ -81,9 +83,15 @@ Task removeLocationUpdates() { } @SuppressWarnings("ResourceType") - @NonNull - Task getLastLocation() { - return fusedLocationProviderClient.getLastLocation(); + void requestLastLocation() { + fusedLocationProviderClient.getLastLocation() + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (sourceListener != null) + sourceListener.onLastKnowLocationTaskReceived(task); + } + }); } @Override diff --git a/library/src/test/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProviderTest.java b/library/src/test/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProviderTest.java index f79c8eb..fe1997b 100644 --- a/library/src/test/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProviderTest.java +++ b/library/src/test/java/com/yayandroid/locationmanager/providers/locationprovider/GooglePlayServicesLocationProviderTest.java @@ -100,15 +100,11 @@ public void onResumeShouldNotRequestLocationUpdateWhenLocationIsAlreadyProvidedA @Test public void onResumeShouldRequestLocationUpdateWhenLocationIsNotYetProvided() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(null); googlePlayServicesLocationProvider.setWaiting(true); - - googlePlayServicesLocationProvider.onResume(); - - getLocationTask.success(null); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); verify(mockedSource).requestLocationUpdate(); } @@ -118,14 +114,8 @@ public void onResumeShouldRequestLocationUpdateWhenLocationIsAlreadyProvidedButR googlePlayServicesLocationProvider.setWaiting(true); when(locationConfiguration.keepTracking()).thenReturn(true); - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - googlePlayServicesLocationProvider.onResume(); - getLocationTask.success(location); - verify(mockedSource).requestLocationUpdate(); } @@ -169,14 +159,8 @@ public void isDialogShownShouldReturnTrueWhenSettingsApiDialogShown() { public void getShouldSetWaitingTrue() { assertThat(googlePlayServicesLocationProvider.isWaiting()).isFalse(); - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - googlePlayServicesLocationProvider.get(); - getLocationTask.success(null); - assertThat(googlePlayServicesLocationProvider.isWaiting()).isTrue(); } @@ -190,132 +174,119 @@ public void getShouldFailWhenThereIsNoContext() { } @Test - public void getShouldRequestLocationUpdate() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - + public void getShouldRequestLastLocation() { googlePlayServicesLocationProvider.get(); - getLocationTask.success(null); - - verify(mockedSource).requestLocationUpdate(); + verify(mockedSource).requestLastLocation(); } @Test - public void cancelShouldRemoveLocationRequestWhenInvokeCancel() { - googlePlayServicesLocationProvider.cancel(); + public void getShouldNotRequestLastLocationWhenIgnore() { + when(googlePlayServicesConfiguration.ignoreLastKnowLocation()).thenReturn(true); - verify(mockedSource).removeLocationUpdates(); + googlePlayServicesLocationProvider.get(); + + verify(mockedSource, never()).requestLastLocation(); } @Test - public void onActivityResultShouldSetDialogShownToFalse() { - makeSettingsDialogIsOnTrue(); - assertThat(googlePlayServicesLocationProvider.isDialogShowing()).isTrue(); + public void onLastKnowLocationTaskReceivedShouldNotCallLocationRequiredWhenLastKnowIsReadyAndNoNeedToKeepTracking() { + when(locationConfiguration.keepTracking()).thenReturn(false); - googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, -1, null); + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(location); - assertThat(googlePlayServicesLocationProvider.isDialogShowing()).isFalse(); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); + + verify(googlePlayServicesLocationProvider, never()).locationRequired(); } @Test - public void onActivityResultShouldRequestLocationUpdateWhenResultIsOk() { - googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, Activity.RESULT_OK, null); + public void onLastKnowLocationTaskReceivedShouldCallRequestLocationUpdateWhenLastLocationIsNull() { + when(locationConfiguration.keepTracking()).thenReturn(false); + when(googlePlayServicesConfiguration.ignoreLastKnowLocation()).thenReturn(false); - verify(googlePlayServicesLocationProvider).requestLocationUpdate(); - } + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(null); - @Test - public void onActivityResultShouldCallSettingsApiFailWhenResultIsNotOk() { - googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, Activity.RESULT_CANCELED, null); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); - verify(googlePlayServicesLocationProvider).settingsApiFail(FailType.GOOGLE_PLAY_SERVICES_SETTINGS_DENIED); + verify(googlePlayServicesLocationProvider).locationRequired(); + verify(googlePlayServicesLocationProvider).requestLocationUpdate(); + assertThat(googlePlayServicesLocationProvider.isWaiting()).isFalse(); } @Test - public void onConnectedShouldNotCheckLastKnowLocationWhenRequirementsIgnore() { - when(googlePlayServicesConfiguration.ignoreLastKnowLocation()).thenReturn(true); + public void onLastKnowLocationTaskReceivedShouldCallLocationRequiredWhenLastKnowIsNotAvailable() { + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(null); - googlePlayServicesLocationProvider.onConnected(); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); - verify(googlePlayServicesLocationProvider, never()).checkLastKnowLocation(); + verify(googlePlayServicesLocationProvider).locationRequired(); } @Test - public void onConnectedShouldCheckLastKnowLocation() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); + public void onLastKnowLocationTaskReceivedShouldNotifyOnLocationChangedWhenLocationIsAvailable() { + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(location); - googlePlayServicesLocationProvider.onConnected(); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); - getLocationTask.success(location); - - verify(googlePlayServicesLocationProvider).checkLastKnowLocation(); + verify(googlePlayServicesLocationProvider).onLocationChanged(location); } @Test - public void onConnectedShouldNotCallLocationRequiredWhenLastKnowIsReadyAndNoNeedToKeepTracking() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - when(locationConfiguration.keepTracking()).thenReturn(false); - - googlePlayServicesLocationProvider.onConnected(); + public void onLastKnowLocationTaskReceivedShouldInvokeLocationRequiredWhenKeepTrackingIsTrue() { + when(locationConfiguration.keepTracking()).thenReturn(true); + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(location); - getLocationTask.success(location); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); - verify(googlePlayServicesLocationProvider, never()).locationRequired(); + verify(googlePlayServicesLocationProvider).onLocationChanged(location); + verify(googlePlayServicesLocationProvider).locationRequired(); } @Test - public void onConnectedShouldCallRequestLocationUpdateWhenLastLocationIsNull() { - // Have first condition false - when(locationConfiguration.keepTracking()).thenReturn(false); - - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - // Have second condition false - when(googlePlayServicesConfiguration.ignoreLastKnowLocation()).thenReturn(false); - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); + public void onLastKnowLocationTaskReceivedShouldInvokeRequestLocationFalseWhenLastKnownLocationIsNull() { + FakeSimpleTask lastLocationTask = new FakeSimpleTask<>(); + lastLocationTask.success(null); - // isWaiting is false on start, onConnected don't changes it - - googlePlayServicesLocationProvider.onConnected(); - - getLocationTask.success(null); + googlePlayServicesLocationProvider.onLastKnowLocationTaskReceived(lastLocationTask); verify(googlePlayServicesLocationProvider).locationRequired(); - verify(googlePlayServicesLocationProvider).requestLocationUpdate(); - assertThat(googlePlayServicesLocationProvider.isWaiting()).isFalse(); } @Test - public void onConnectedShouldCallLocationRequiredWhenLastKnowIsNotAvailable() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); + public void cancelShouldRemoveLocationRequestWhenInvokeCancel() { + googlePlayServicesLocationProvider.cancel(); - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); + verify(mockedSource).removeLocationUpdates(); + } - googlePlayServicesLocationProvider.onConnected(); + @Test + public void onActivityResultShouldSetDialogShownToFalse() { + makeSettingsDialogIsOnTrue(); + assertThat(googlePlayServicesLocationProvider.isDialogShowing()).isTrue(); - getLocationTask.success(null); + googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, -1, null); - verify(googlePlayServicesLocationProvider).locationRequired(); + assertThat(googlePlayServicesLocationProvider.isDialogShowing()).isFalse(); } @Test - public void onConnectedShouldCallLocationRequiredWhenConfigurationRequiresKeepTracking() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - when(locationConfiguration.keepTracking()).thenReturn(true); + public void onActivityResultShouldRequestLocationUpdateWhenResultIsOk() { + googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, Activity.RESULT_OK, null); - googlePlayServicesLocationProvider.onConnected(); + verify(googlePlayServicesLocationProvider).requestLocationUpdate(); + } - getLocationTask.success(location); + @Test + public void onActivityResultShouldCallSettingsApiFailWhenResultIsNotOk() { + googlePlayServicesLocationProvider.onActivityResult(RequestCode.SETTINGS_API, Activity.RESULT_CANCELED, null); - verify(googlePlayServicesLocationProvider).locationRequired(); + verify(googlePlayServicesLocationProvider).settingsApiFail(FailType.GOOGLE_PLAY_SERVICES_SETTINGS_DENIED); } @Test @@ -450,36 +421,6 @@ public void resolveSettingsApiShouldCallSettingsApiFailWhenExceptionThrown() thr verify(googlePlayServicesLocationProvider).settingsApiFail(FailType.GOOGLE_PLAY_SERVICES_SETTINGS_DIALOG); } - @Test - public void checkLastKnowLocationInvokeRequestLocationTrueWhenLocationIsAvailable() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - - googlePlayServicesLocationProvider.checkLastKnowLocation(); - - getLocationTask.success(location); - - verify(mockedSource).getLastLocation(); - - verify(googlePlayServicesLocationProvider).onLocationChanged(location); - verify(googlePlayServicesLocationProvider).requestLocation(true); - } - - @Test - public void checkLastKnowLocationShouldInvokeRequestLocationFalseWhenLastKnownLocationIsNull() { - FakeSimpleTask getLocationTask = new FakeSimpleTask<>(); - - when(mockedSource.getLastLocation()).thenReturn(getLocationTask); - - googlePlayServicesLocationProvider.checkLastKnowLocation(); - - getLocationTask.success(null); - - verify(mockedSource).getLastLocation(); - verify(googlePlayServicesLocationProvider).requestLocation(false); - } - @Test public void locationRequiredShouldCheckLocationSettingsWhenConfigurationAsksForSettingsApi() { when(googlePlayServicesConfiguration.askForSettingsApi()).thenReturn(true);