Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[Connectivity] add a method to request location on iOS (for iOS 13) #1999

Merged
merged 19 commits into from
Aug 29, 2019

Conversation

cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Aug 21, 2019

Description

Starting from iOS 13. Certain apps need to have user authorized location service to get WIFI information using CNCopyCurrentNetworkInfo. Detailed in flutter/flutter#37804

We add a helper method for the plugin users to request or get location service authorization.
Also updated the REAMDE to explain the iOS 13 changes.

Related Issues

flutter/flutter#37804

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@cyanglaz cyanglaz changed the title Connectivity add a method to request location on iOS (for iOS 13) [Connectivity] add a method to request location on iOS (for iOS 13) Aug 21, 2019
@collinjackson collinjackson self-requested a review August 23, 2019 20:19
Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long term I'm hoping this will move to a shared plugin, so I'm fine with whatever you want to do here.

However, it feels like we're conflating requesting permission and checking what the current status is. I'm wondering if there should be separate APIs for each. What do you think?

Compare with the React Native implementation

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Location service</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>locaiton service in use</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo, also I think you should put an English sentence here

@@ -22,6 +22,10 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Location service</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should put an appropriate English sentence here since it's an example app.


You can follow issue [#37804](https://github.com/flutter/flutter/issues/37804) for the changes required to return valid SSID and BSSID values with iOS 13.
* `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s location information all the time (foreground and background). _Privacy - Location Always and When In Use Usage Description_ in the visual editor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s location information all the time (foreground and background). _Privacy - Location Always and When In Use Usage Description_ in the visual editor.
* `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s location information all the time (foreground and background). This is called _Privacy - Location Always Usage Description_ in the visual editor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be wrong here but I think it should just be Privacy - Location Always Usage Description

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add "This is called" from my suggestion above?

CLAuthorizationStatus status = CLLocationManager.authorizationStatus;
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
self.result = result;
Copy link
Contributor

@collinjackson collinjackson Aug 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a race condition here where two calls to requestLocationServiceAuthorizationIfUndetermined in quick succession could lead to result being clobbered before being invoked. Consider returning an error if self.result != null or handling the case gracefully.

}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
[self requestLocationServiceAuthorizationIfUndetermined:self.result always:nil];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably set self.result to nil here so we don't accidentally notify it more than once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new class FLTConnectivityLocationHandler to handle all the location related stuff so now the result is inline.
FLTConnectivityLocationHandler handles the race condition that you mentioned by returning notDetermined if a request is in process.

@cyanglaz
Copy link
Contributor Author

However, it feels like we're conflating requesting permission and checking what the current status is. I'm wondering if there should be separate APIs for each. What do you think?

Sure. My initial implementation did actually have these separated. I can add it back.

Chris Yang and others added 10 commits August 26, 2019 13:32
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
Co-Authored-By: Collin Jackson <jackson@google.com>
@cyanglaz
Copy link
Contributor Author

@collinjackson It is ready for another review.

Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with some minor nits.

Might want to integration test the default value of getLocationServiceAuthorization even if the infrastructure's not quite there yet to do requestLocationServiceAuthorization yet.


You can follow issue [#37804](https://github.com/flutter/flutter/issues/37804) for the changes required to return valid SSID and BSSID values with iOS 13.
* `NSLocationAlwaysAndWhenInUseUsageDescription` - describe why the app needs access to the user’s location information all the time (foreground and background). _Privacy - Location Always and When In Use Usage Description_ in the visual editor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add "This is called" from my suggestion above?

@@ -22,6 +22,10 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app requires accessing your location information all the time to get WIFI information.</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check caps on WIFI, consider wi-fi

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app requires accessing your location information all the time to get WIFI information.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires accessing your location information when the app is in foreground to get WIFI information.</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check caps on WIFI, consider wi-fi

status == LocationAuthorizationStatus.authorizedWhenInUse) {
wifiName = await _connectivity.getWifiName();
} else {
print(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not thrilled about this print statement, it seems like it could clutter the logs. Do you think it's necessary?

}

if (self.completion) {
// If a request is still in process, immdediately return.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If a request is still in process, immdediately return.
// If a request is still in process, immediately return.

///
/// Returns a [LocationAuthorizationStatus] after user authorized or denied the location on this request.
///
/// if the location information needs to be accessible all the time, set `requestAlwaysLocationUsage` to true. If user has
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// if the location information needs to be accessible all the time, set `requestAlwaysLocationUsage` to true. If user has
/// If the location information needs to be accessible all the time, set `requestAlwaysLocationUsage` to `true`. If user has

///
/// See also [requestLocationServiceAuthorization] for requesting a location service authorization.
Future<LocationAuthorizationStatus> getLocationServiceAuthorization() async {
//Just `assert(Platform.isIOS)` will disable us to do dart side unit testing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Just `assert(Platform.isIOS)` will disable us to do dart side unit testing.
// Just `assert(Platform.isIOS)` will prevent us from doing Dart side unit testing.

@@ -93,6 +94,125 @@ class Connectivity {
Future<String> getWifiIP() async {
return await methodChannel.invokeMethod<String>('wifiIPAddress');
}

/// Request to authorize the location service. Only on iOS.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Request to authorize the location service. Only on iOS.
/// Request to authorize the location service (only on iOS).

I think Dartdoc comments are supposed to have tight first sentence with no other sentences on the first line. https://dart.dev/guides/language/effective-dart/documentation

return _convertLocationStatusString(result);
}

/// Get the current location service authorization. Only on iOS.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Get the current location service authorization. Only on iOS.
/// Get the current location service authorization (only on iOS).

@cyanglaz
Copy link
Contributor Author

@collinjackson Thanks for the review. I updated the code with your review suggests; also added a driver test to test the getLocationServiceAuthorization. The other method requestLocationServiceAuthorization is probably not testable as it for now since it will show a pop up and I'm not sure if there is a way to handle system pop ups from flutter driver.
Im going to merge this on green if you don't have any objections.

@collinjackson collinjackson self-requested a review August 28, 2019 22:47
Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you have some test failures but I'm LGTM on this once you've resolved them.

@cyanglaz cyanglaz merged commit 90aaca8 into flutter:master Aug 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants