Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes a bug where iOS location settings, e.g. accuracy and distanceFilter are overridden by different calls #1600

Merged
merged 2 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions geolocator_apple/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.3.8

* Uses different `CLLocationManager` instances, for one time request location and persistent request location.
* Fixes a bug where iOS location settings, e.g. `accuracy` and `distanceFilter` are overridden by different calls.
* Updates minimum deployment target to `iOS 11` as lower is not supported anymore by Xcode.

## 2.3.7

* Adds privacy manifest.
Expand Down
157 changes: 93 additions & 64 deletions geolocator_apple/example/ios/RunnerTests/GeolocationHandlerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ @interface GeolocationHandlerTests : XCTestCase

@implementation GeolocationHandlerTests {
CLLocationManager *_mockLocationManager;
CLLocationManager *_mockOneTimeLocationManager;

GeolocationHandler *_geolocationHandler;
}

- (void)setUp {
_mockLocationManager = OCMClassMock(CLLocationManager.class);
_mockOneTimeLocationManager = OCMClassMock(CLLocationManager.class);

_geolocationHandler = [[GeolocationHandler alloc] init];
[_geolocationHandler setLocationManagerOverride:_mockLocationManager];
[_geolocationHandler setOneTimeLocationManagerOverride:_mockOneTimeLocationManager];
}

#pragma mark - Test requesting current location
Expand All @@ -36,25 +40,25 @@ - (void)testGetCurrentPositionShouldCallStartUpdatingLocation {
resultHandler:^(CLLocation * _Nullable location) {}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {}];

OCMVerify(times(1), [self->_mockLocationManager setDesiredAccuracy:kCLLocationAccuracyBest]);
OCMVerify(times(1), [self->_mockLocationManager startUpdatingLocation]);
OCMVerify(times(1), [self->_mockOneTimeLocationManager setDesiredAccuracy:kCLLocationAccuracyBest]);
OCMVerify(times(1), [self->_mockOneTimeLocationManager startUpdatingLocation]);
}

- (void)testRequestPositionShouldReturnLocationWithinTimeConstraints {
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];

CLLocation *firstLocation = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(54.0, 6.4)
altitude:0.0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[calendar dateByAddingUnit:NSCalendarUnitSecond value:-6 toDate:now options:0]];
CLLocation *secondLocation = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(54.1, 6.4)
altitude:0.0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:now];

altitude:0.0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:now];

XCTestExpectation *expectation = [self expectationWithDescription:@"expect result return third location"];
[_geolocationHandler requestPositionWithDesiredAccuracy:kCLLocationAccuracyBest
Expand All @@ -64,20 +68,20 @@ - (void)testRequestPositionShouldReturnLocationWithinTimeConstraints {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {}];

[_geolocationHandler locationManager:_mockLocationManager didUpdateLocations: @[firstLocation]];
[_geolocationHandler locationManager:_mockLocationManager didUpdateLocations: @[secondLocation]];
[_geolocationHandler locationManager:_mockOneTimeLocationManager didUpdateLocations: @[firstLocation]];
[_geolocationHandler locationManager:_mockOneTimeLocationManager didUpdateLocations: @[secondLocation]];

[self waitForExpectationsWithTimeout:5.0 handler:nil];

OCMVerify(times(1), [self->_mockLocationManager stopUpdatingLocation]);
OCMVerify(times(1), [self->_mockOneTimeLocationManager stopUpdatingLocation]);
}

- (void)testRequestPositionShouldStopListeningOnResult {
CLLocation *location = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(54.1, 6.4)
altitude:0.0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];
altitude:0.0
horizontalAccuracy:0
verticalAccuracy:0
timestamp:[NSDate date]];

XCTestExpectation *expectation = [self expectationWithDescription:@"expect first result return third location"];
[_geolocationHandler requestPositionWithDesiredAccuracy:kCLLocationAccuracyBest
Expand All @@ -88,11 +92,11 @@ - (void)testRequestPositionShouldStopListeningOnResult {

}];

[_geolocationHandler locationManager:_mockLocationManager didUpdateLocations: @[location]];
[_geolocationHandler locationManager:_mockOneTimeLocationManager didUpdateLocations: @[location]];

[self waitForExpectationsWithTimeout:5.0 handler:nil];

OCMVerify(times(1), [self->_mockLocationManager stopUpdatingLocation]);
OCMVerify(times(1), [self->_mockOneTimeLocationManager stopUpdatingLocation]);
}

- (void)testRequestPositionShouldStopListeningOnError {
Expand All @@ -107,11 +111,11 @@ - (void)testRequestPositionShouldStopListeningOnError {

}];

[_geolocationHandler locationManager:_mockLocationManager didFailWithError: error];
[_geolocationHandler locationManager:_mockOneTimeLocationManager didFailWithError: error];

[self waitForExpectationsWithTimeout:5.0 handler:nil];

OCMVerify(times(1), [self->_mockLocationManager stopUpdatingLocation]);
OCMVerify(times(1), [self->_mockOneTimeLocationManager stopUpdatingLocation]);
}

- (void)testRequestPositionShouldNotStopListeningOnErrorDomainAndErrorLocationUnknown {
Expand Down Expand Up @@ -158,7 +162,7 @@ - (void)testStartListeningShouldNotStopListeningWhenListeningToStream {
- (void)testRequestingPositionWhileListeningDoesntStopStream {
CLLocation *mockLocation = [[CLLocation alloc] initWithLatitude:54.0 longitude:6.4];
XCTestExpectation *expectationStream = [self expectationWithDescription:@"expect result return third location"];
XCTestExpectation *expectationForeground = [self expectationWithDescription:@"expect result return third location"];
XCTestExpectation *expectationForeground = [self expectationWithDescription:@"expect result return third location"];
[_geolocationHandler startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
Expand All @@ -172,14 +176,14 @@ - (void)testRequestingPositionWhileListeningDoesntStopStream {
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];

[_geolocationHandler requestPositionWithDesiredAccuracy:kCLLocationAccuracyHundredMeters
resultHandler:^(CLLocation * _Nullable location) {
XCTAssertEqual(location, mockLocation);
[expectationForeground fulfill];
} errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {
}];
XCTAssertEqual(location, mockLocation);
[expectationForeground fulfill];
} errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];
[_geolocationHandler locationManager:_mockLocationManager didUpdateLocations: @[mockLocation]];

[self waitForExpectationsWithTimeout:5.0 handler:nil];
Expand Down Expand Up @@ -236,39 +240,39 @@ - (void)testStartListeningShouldNotReportErrorOnErrorDomainAndErrorLocationUnkno
}

- (void)testListeningBackgroundGeolocationOnlyWhenAllowedAndEnabled {
id geolocationHandlerMock = OCMPartialMock(_geolocationHandler);
[geolocationHandlerMock setLocationManagerOverride:_mockLocationManager];
OCMStub(ClassMethod([geolocationHandlerMock shouldEnableBackgroundLocationUpdates]))._andReturn([NSNumber numberWithBool:YES]);
[geolocationHandlerMock startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:NO
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:YES
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {
}];
OCMVerify([_mockLocationManager setAllowsBackgroundLocationUpdates:YES]);
id geolocationHandlerMock = OCMPartialMock(_geolocationHandler);
[geolocationHandlerMock setLocationManagerOverride:_mockLocationManager];
OCMStub(ClassMethod([geolocationHandlerMock shouldEnableBackgroundLocationUpdates]))._andReturn([NSNumber numberWithBool:YES]);
[geolocationHandlerMock startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:NO
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:YES
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];
OCMVerify([_mockLocationManager setAllowsBackgroundLocationUpdates:YES]);
}

- (void)testNotListeningBackgroundGeolocationWhenNotEnabled {
id geolocationHandlerMock = OCMPartialMock(_geolocationHandler);
[geolocationHandlerMock setLocationManagerOverride:_mockLocationManager];
OCMStub(ClassMethod([geolocationHandlerMock shouldEnableBackgroundLocationUpdates]))._andReturn([NSNumber numberWithBool:YES]);
[geolocationHandlerMock startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:NO
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:NO
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {
}];
OCMVerify(never(), [_mockLocationManager setAllowsBackgroundLocationUpdates:YES]);
id geolocationHandlerMock = OCMPartialMock(_geolocationHandler);
[geolocationHandlerMock setLocationManagerOverride:_mockLocationManager];
OCMStub(ClassMethod([geolocationHandlerMock shouldEnableBackgroundLocationUpdates]))._andReturn([NSNumber numberWithBool:YES]);
[geolocationHandlerMock startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:NO
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:NO
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];
OCMVerify(never(), [_mockLocationManager setAllowsBackgroundLocationUpdates:YES]);
}

- (void)testKeepLocationManagerSettingsWhenRequestingCurrentPosition {
Expand All @@ -283,14 +287,14 @@ - (void)testKeepLocationManagerSettingsWhenRequestingCurrentPosition {
._andReturn([NSNumber numberWithBool:YES]);
}
[geolocationHandlerMock startListeningWithDesiredAccuracy: kCLLocationAccuracyBest
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:YES
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:YES
resultHandler:^(CLLocation * _Nullable location) {
distanceFilter:0
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:YES
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:YES
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];
OCMVerify([_mockLocationManager setAllowsBackgroundLocationUpdates:YES]);
Expand All @@ -306,4 +310,29 @@ - (void)testKeepLocationManagerSettingsWhenRequestingCurrentPosition {
}
}

- (void)testKeepLocationManagerSettingsWhenRequestingCurrentPosition1 {
[_geolocationHandler startListeningWithDesiredAccuracy:kCLLocationAccuracyThreeKilometers
distanceFilter:kCLLocationAccuracyThreeKilometers
pauseLocationUpdatesAutomatically:NO
showBackgroundLocationIndicator:YES
activityType:CLActivityTypeOther
allowBackgroundLocationUpdates:YES
resultHandler:^(CLLocation * _Nullable location) {
}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {

}];
OCMVerify([_mockLocationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers]);
OCMVerify([_mockLocationManager setDistanceFilter:kCLLocationAccuracyThreeKilometers]);

[_geolocationHandler requestPositionWithDesiredAccuracy:kCLLocationAccuracyBest
resultHandler:^(CLLocation * _Nullable location) {}
errorHandler:^(NSString * _Nonnull errorCode, NSString * _Nonnull errorDescription) {}];
OCMVerify([_mockOneTimeLocationManager setDesiredAccuracy:kCLLocationAccuracyBest]);
OCMVerify([_mockOneTimeLocationManager setDistanceFilter:kCLDistanceFilterNone]);

OCMVerify(never(), [_mockLocationManager setDesiredAccuracy:kCLLocationAccuracyBest]);
OCMVerify(never(), [_mockLocationManager setDistanceFilter:kCLDistanceFilterNone]);
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ - (void)testOpenAppSettings {

if (@available(iOS 8, *)) {
id mockApplication = OCMClassMock([UIApplication class]);
OCMStub([mockApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]).andReturn(YES);
OCMStub([(UIApplication *)mockApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]).andReturn(YES);
OCMStub(ClassMethod([mockApplication sharedApplication])).andReturn(mockApplication);


Expand Down Expand Up @@ -394,7 +394,7 @@ - (void)testOpenLocationSettings {

if (@available(iOS 8, *)) {
id mockApplication = OCMClassMock([UIApplication class]);
OCMStub([mockApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]).andReturn(YES);
OCMStub([(UIApplication *)mockApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]).andReturn(YES);
OCMStub(ClassMethod([mockApplication sharedApplication])).andReturn(mockApplication);


Expand Down
Loading