diff --git a/geolocator/CHANGELOG.md b/geolocator/CHANGELOG.md index 1279af486..d67206285 100644 --- a/geolocator/CHANGELOG.md +++ b/geolocator/CHANGELOG.md @@ -1,6 +1,9 @@ ## 13.0.2 - Resolves build error on ./gradlew +- Updates dependency on geolocator_apple to version 2.3.8. +- Migrates Android configuration of example app away from imperative gradle API. + ## 13.0.1 diff --git a/geolocator/example/android/app/build.gradle b/geolocator/example/android/app/build.gradle index 91cfad654..1a5fe61f3 100644 --- a/geolocator/example/android/app/build.gradle +++ b/geolocator/example/android/app/build.gradle @@ -1,3 +1,8 @@ +plugins { + id "com.android.application" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +11,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -27,17 +27,14 @@ project.getTasks().withType(JavaCompile) { options.compilerArgs.addAll(args) } -apply plugin: 'com.android.application' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - android { - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.baseflow.geolocator_example" - minSdkVersion 16 + minSdkVersion flutter.minSdkVersion targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/geolocator/example/android/build.gradle b/geolocator/example/android/build.gradle index e29a4431f..bc157bd1a 100644 --- a/geolocator/example/android/build.gradle +++ b/geolocator/example/android/build.gradle @@ -1,14 +1,3 @@ -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - } -} - allprojects { repositories { google() @@ -24,6 +13,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/geolocator/example/android/settings.gradle b/geolocator/example/android/settings.gradle index 5a2f14fb1..a7f13a03b 100644 --- a/geolocator/example/android/settings.gradle +++ b/geolocator/example/android/settings.gradle @@ -1,15 +1,24 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.1.2" apply false } + +include ":app" \ No newline at end of file diff --git a/geolocator/example/ios/Flutter/AppFrameworkInfo.plist b/geolocator/example/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f78a..4f8d4d245 100644 --- a/geolocator/example/ios/Flutter/AppFrameworkInfo.plist +++ b/geolocator/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 11.0 diff --git a/geolocator/example/ios/Runner.xcodeproj/project.pbxproj b/geolocator/example/ios/Runner.xcodeproj/project.pbxproj index 36aa7366f..191387984 100644 --- a/geolocator/example/ios/Runner.xcodeproj/project.pbxproj +++ b/geolocator/example/ios/Runner.xcodeproj/project.pbxproj @@ -332,7 +332,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -353,6 +353,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -414,7 +415,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -463,7 +464,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -485,6 +486,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -511,6 +513,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/geolocator/pubspec.yaml b/geolocator/pubspec.yaml index 3bb7a9a2a..62e15bb42 100644 --- a/geolocator/pubspec.yaml +++ b/geolocator/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: geolocator_platform_interface: ^4.2.3 geolocator_android: ^4.6.2 - geolocator_apple: ^2.3.7 + geolocator_apple: ^2.3.8 geolocator_web: ^4.1.1 geolocator_windows: ^0.2.3 diff --git a/geolocator_apple/CHANGELOG.md b/geolocator_apple/CHANGELOG.md index 815ecb4bc..a62b2666e 100644 --- a/geolocator_apple/CHANGELOG.md +++ b/geolocator_apple/CHANGELOG.md @@ -1,3 +1,13 @@ +## 2.3.8+1 + +* HOT FIX: Adds back implementation of the `stopListening` method in the `GeolocationHandler.m` file. + +## 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. diff --git a/geolocator_apple/example/ios/Flutter/AppFrameworkInfo.plist b/geolocator_apple/example/ios/Flutter/AppFrameworkInfo.plist index 4f8d4d245..8c6e56146 100644 --- a/geolocator_apple/example/ios/Flutter/AppFrameworkInfo.plist +++ b/geolocator_apple/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/geolocator_apple/example/ios/Podfile b/geolocator_apple/example/ios/Podfile index 87a77d50e..c654fd274 100644 --- a/geolocator_apple/example/ios/Podfile +++ b/geolocator_apple/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -31,7 +31,7 @@ target 'Runner' do flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do - platform :ios, '11.0' + platform :ios, '12.0' inherit! :search_paths # Pods for testing pod 'OCMock', '~> 3.8.1' diff --git a/geolocator_apple/example/ios/Runner.xcodeproj/project.pbxproj b/geolocator_apple/example/ios/Runner.xcodeproj/project.pbxproj index 2608a3854..33880a1c3 100644 --- a/geolocator_apple/example/ios/Runner.xcodeproj/project.pbxproj +++ b/geolocator_apple/example/ios/Runner.xcodeproj/project.pbxproj @@ -192,6 +192,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 591FD69E94FC610DB997784E /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -227,7 +228,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -296,6 +297,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 591FD69E94FC610DB997784E /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 6E879EFB06735EEE96AC22A9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -448,7 +466,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -530,7 +548,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -579,7 +597,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -656,7 +674,7 @@ CURRENT_PROJECT_VERSION = 1; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -683,7 +701,7 @@ CURRENT_PROJECT_VERSION = 1; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.baseflow.geolocatorExample.RunnerTests; @@ -709,7 +727,7 @@ CURRENT_PROJECT_VERSION = 1; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.baseflow.geolocatorExample.RunnerTests; diff --git a/geolocator_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/geolocator_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 4a7e772c9..0d7f6f9e5 100644 --- a/geolocator_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/geolocator_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ _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 @@ -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 @@ -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 { @@ -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 { @@ -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 @@ -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]; @@ -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 { @@ -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]); @@ -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 diff --git a/geolocator_apple/example/ios/RunnerTests/GeolocatorPluginTests.m b/geolocator_apple/example/ios/RunnerTests/GeolocatorPluginTests.m index c4e9cf4a3..72c5cfe11 100644 --- a/geolocator_apple/example/ios/RunnerTests/GeolocatorPluginTests.m +++ b/geolocator_apple/example/ios/RunnerTests/GeolocatorPluginTests.m @@ -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); @@ -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); diff --git a/geolocator_apple/ios/Classes/Handlers/GeolocationHandler.m b/geolocator_apple/ios/Classes/Handlers/GeolocationHandler.m index 0ebc96bd5..e3808f185 100644 --- a/geolocator_apple/ios/Classes/Handlers/GeolocationHandler.m +++ b/geolocator_apple/ios/Classes/Handlers/GeolocationHandler.m @@ -13,12 +13,12 @@ @interface GeolocationHandler() -@property(assign, nonatomic) bool isListeningForPositionUpdates; - @property(strong, nonatomic, nonnull) CLLocationManager *locationManager; - @property(strong, nonatomic) GeolocatorError errorHandler; +@property(strong, nonatomic, nonnull) CLLocationManager *oneTimeLocationManager; +@property(strong, nonatomic) GeolocatorError oneTimeErrorHandler; + @property(strong, nonatomic) GeolocatorResult currentLocationResultHandler; @property(strong, nonatomic) GeolocatorResult listenerResultHandler; @@ -32,8 +32,7 @@ - (id) init { if (!self) { return nil; } - - self.isListeningForPositionUpdates = NO; + return self; } @@ -49,32 +48,42 @@ - (void)setLocationManagerOverride:(CLLocationManager *)locationManager { self.locationManager = locationManager; } -- (CLLocation *)getLastKnownPosition { +- (CLLocationManager *) getOneTimeLocationManager { + if (!self.oneTimeLocationManager) { + self.oneTimeLocationManager = [[CLLocationManager alloc] init]; + self.oneTimeLocationManager.delegate = self; + } + return self.oneTimeLocationManager; +} + +- (void)setOneTimeLocationManagerOverride:(CLLocationManager *)locationManager { + self.oneTimeLocationManager = locationManager; +} + +- (CLLocation *) getLastKnownPosition { CLLocationManager *locationManager = [self getLocationManager]; - return [locationManager location]; + CLLocation *cashedLocation = [locationManager location]; + if (cashedLocation != nil) { + return cashedLocation; + } + CLLocationManager *persistentLocationManager = [self getOneTimeLocationManager]; + return [persistentLocationManager location]; } - (void)requestPositionWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy resultHandler:(GeolocatorResult _Nonnull)resultHandler errorHandler:(GeolocatorError _Nonnull)errorHandler { - self.errorHandler = errorHandler; + self.oneTimeErrorHandler = errorHandler; self.currentLocationResultHandler = resultHandler; - + BOOL showBackgroundLocationIndicator = NO; BOOL allowBackgroundLocationUpdates = NO; - #if TARGET_OS_IOS - if (self.isListeningForPositionUpdates) { - CLLocationManager *locationManager = [self getLocationManager]; - showBackgroundLocationIndicator = locationManager.showsBackgroundLocationIndicator; - allowBackgroundLocationUpdates = locationManager.allowsBackgroundLocationUpdates; - } - #endif [self startUpdatingLocationWithDesiredAccuracy:desiredAccuracy distanceFilter:kCLDistanceFilterNone pauseLocationUpdatesAutomatically:NO activityType:CLActivityTypeOther - isListeningForPositionUpdates:self.isListeningForPositionUpdates + isListeningForPositionUpdates:NO showBackgroundLocationIndicator:showBackgroundLocationIndicator allowBackgroundLocationUpdates:allowBackgroundLocationUpdates]; } @@ -87,10 +96,10 @@ - (void)startListeningWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy allowBackgroundLocationUpdates:(BOOL)allowBackgroundLocationUpdates resultHandler:(GeolocatorResult _Nonnull )resultHandler errorHandler:(GeolocatorError _Nonnull)errorHandler { - + self.errorHandler = errorHandler; self.listenerResultHandler = resultHandler; - + [self startUpdatingLocationWithDesiredAccuracy:desiredAccuracy distanceFilter:distanceFilter pauseLocationUpdatesAutomatically:pauseLocationUpdatesAutomatically @@ -107,60 +116,67 @@ - (void)startUpdatingLocationWithDesiredAccuracy:(CLLocationAccuracy)desiredAccu isListeningForPositionUpdates:(BOOL)isListeningForPositionUpdates showBackgroundLocationIndicator:(BOOL)showBackgroundLocationIndicator allowBackgroundLocationUpdates:(BOOL)allowBackgroundLocationUpdates - { - self.isListeningForPositionUpdates = isListeningForPositionUpdates; - CLLocationManager *locationManager = [self getLocationManager]; - locationManager.desiredAccuracy = desiredAccuracy; - locationManager.distanceFilter = distanceFilter; - if (@available(iOS 6.0, macOS 10.15, *)) { - locationManager.activityType = activityType; - locationManager.pausesLocationUpdatesAutomatically = pauseLocationUpdatesAutomatically; - } +{ + if (isListeningForPositionUpdates) { + CLLocationManager *locationManager = [self getLocationManager]; + locationManager.desiredAccuracy = desiredAccuracy; + locationManager.distanceFilter = distanceFilter; + if (@available(iOS 6.0, macOS 10.15, *)) { + locationManager.activityType = activityType; + locationManager.pausesLocationUpdatesAutomatically = pauseLocationUpdatesAutomatically; + } + #if TARGET_OS_IOS - if (@available(iOS 9.0, macOS 11.0, *)) { locationManager.allowsBackgroundLocationUpdates = allowBackgroundLocationUpdates - && [GeolocationHandler shouldEnableBackgroundLocationUpdates]; - } - if (@available(iOS 11.0, macOS 11.0, *)) { + && [GeolocationHandler shouldEnableBackgroundLocationUpdates]; locationManager.showsBackgroundLocationIndicator = showBackgroundLocationIndicator; - } #endif - - [locationManager startUpdatingLocation]; + [locationManager startUpdatingLocation]; + } else { + CLLocationManager *locationManager = [self getOneTimeLocationManager]; + locationManager.desiredAccuracy = desiredAccuracy; + locationManager.distanceFilter = distanceFilter; + [locationManager startUpdatingLocation]; + } +} + +- (void)stopOneTimeLocationListening { + [[self getOneTimeLocationManager] stopUpdatingLocation]; + self.oneTimeErrorHandler = nil; + self.currentLocationResultHandler = nil; } - (void)stopListening { - [[self getLocationManager] stopUpdatingLocation]; - self.isListeningForPositionUpdates = NO; - self.errorHandler = nil; - self.listenerResultHandler = nil; + [[self getLocationManager] stopUpdatingLocation]; + self.errorHandler = nil; + self.listenerResultHandler = nil; } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { if (!self.listenerResultHandler && !self.currentLocationResultHandler) return; - + CLLocation *mostRecentLocation = [locations lastObject]; NSTimeInterval ageInSeconds = -[mostRecentLocation.timestamp timeIntervalSinceNow]; // If location is older then 5.0 seconds it is likely a cached location which // will be skipped. - if (!self.isListeningForPositionUpdates && ageInSeconds > kMaxLocationLifeTimeInSeconds) { + if (manager == [self getOneTimeLocationManager] && ageInSeconds > kMaxLocationLifeTimeInSeconds) { return; } - + if ([locations lastObject]) { - if (self.currentLocationResultHandler != nil) { - self.currentLocationResultHandler(mostRecentLocation); - } - if (self.listenerResultHandler != nil) { - self.listenerResultHandler(mostRecentLocation); - } + if (self.currentLocationResultHandler != nil) { + self.currentLocationResultHandler(mostRecentLocation); + } + if (self.listenerResultHandler != nil) { + self.listenerResultHandler(mostRecentLocation); + } } - + self.currentLocationResultHandler = nil; - if (!self.isListeningForPositionUpdates) { - [self stopListening]; + if (manager == [self getOneTimeLocationManager]) { + [self stopOneTimeLocationListening]; } } @@ -178,17 +194,16 @@ - (void)locationManager:(CLLocationManager *)manager self.errorHandler(GeolocatorErrorLocationUpdateFailure, error.localizedDescription); } - self.currentLocationResultHandler = nil; - if (!self.isListeningForPositionUpdates) { - [self stopListening]; + if (self.oneTimeErrorHandler) { + self.oneTimeErrorHandler(GeolocatorErrorLocationUpdateFailure, error.localizedDescription); + } + + if (manager == [self getOneTimeLocationManager]) { + [self stopOneTimeLocationListening]; } } + (BOOL) shouldEnableBackgroundLocationUpdates { - if (@available(iOS 9.0, *)) { - return [[NSBundle.mainBundle objectForInfoDictionaryKey:@"UIBackgroundModes"] containsObject: @"location"]; - } else { - return NO; - } + return [[NSBundle.mainBundle objectForInfoDictionaryKey:@"UIBackgroundModes"] containsObject: @"location"]; } @end diff --git a/geolocator_apple/ios/Classes/Handlers/GeolocationHandler_Test.h b/geolocator_apple/ios/Classes/Handlers/GeolocationHandler_Test.h index fed2845de..302b1a7d2 100644 --- a/geolocator_apple/ios/Classes/Handlers/GeolocationHandler_Test.h +++ b/geolocator_apple/ios/Classes/Handlers/GeolocationHandler_Test.h @@ -9,4 +9,8 @@ /// This should only be used for testing purposes. - (void)setLocationManagerOverride:(CLLocationManager *)locationManager; +/// Overrides the CLLocationManager instance used by the GeolocationHandler. +/// This should only be used for testing purposes. +- (void)setOneTimeLocationManagerOverride:(CLLocationManager *)locationManager; + @end diff --git a/geolocator_apple/ios/geolocator_apple.podspec b/geolocator_apple/ios/geolocator_apple.podspec index e2ab47f3a..00c7aace5 100644 --- a/geolocator_apple/ios/geolocator_apple.podspec +++ b/geolocator_apple/ios/geolocator_apple.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.public_header_files = 'Classes/**/*.h' s.module_map = 'Classes/GeolocatorPlugin.modulemap' s.dependency 'Flutter' - s.platform = :ios, '8.0' + s.platform = :ios, '11.0' # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386'} diff --git a/geolocator_apple/pubspec.yaml b/geolocator_apple/pubspec.yaml index f3bbe3e7c..270b13a3e 100644 --- a/geolocator_apple/pubspec.yaml +++ b/geolocator_apple/pubspec.yaml @@ -2,7 +2,7 @@ name: geolocator_apple description: Geolocation Apple plugin for Flutter. This plugin provides the Apple implementation for the geolocator. repository: https://github.com/baseflow/flutter-geolocator/tree/main/geolocator_apple issue_tracker: https://github.com/baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen -version: 2.3.7 +version: 2.3.8+1 environment: sdk: ">=2.15.0 <4.0.0"