EXT-229 Defer ATT request until app becomes active - #93
Conversation
21f0c92 to
db9fa3c
Compare
There was a problem hiding this comment.
Pull request overview
Defers the iOS App Tracking Transparency (ATT) authorization request until the application is active, avoiding calling ATTrackingManager.requestTrackingAuthorization during inactive/background states.
Changes:
- Routes
requestTrackingAuthorizationthrough a newrequestTrackingAuthorizationWhenActivehelper on iOS 14+. - Adds an
applicationStatecheck and defers the request via adidBecomeActiveobserver when the app isn’t active. - Ensures the observer is removed before completing with a final status.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if UIApplication.shared.applicationState != .active { | ||
| addObserver(result: result) | ||
| return | ||
| } | ||
|
|
||
| removeObserver() | ||
| ATTrackingManager.requestTrackingAuthorization { [weak self] status in | ||
| if status == .denied && ATTrackingManager.trackingAuthorizationStatus == .notDetermined { | ||
| self?.addObserver(result: result) | ||
| return | ||
| } | ||
|
|
||
| self?.removeObserver() | ||
| result(Int(status.rawValue)) | ||
| } |
| if UIApplication.shared.applicationState != .active { | ||
| addObserver(result: result) | ||
| return |
|
Claude finished @JakubMrozek's task in 1m 15s —— View job Code ReviewThe approach is sound — deferring ATT until the app is active is the correct fix. The logic flows well, but there are a few issues to address before merging: 1. Thread safety (echoing Copilot's comment)
@available(iOS 14, *)
private func requestTrackingAuthorizationWhenActive(result: @escaping FlutterResult) {
DispatchQueue.main.async {
if UIApplication.shared.applicationState != .active {
self.addObserver(result: result)
return
}
// ... rest of the logic
}
}2. Pending result is silently dropped on concurrent callsWhen a second Two reasonable options:
3. Active-path
|
| Severity | |
|---|---|
| Thread safety (#1) | Medium — safe in practice today, but fragile |
| Silent result drop on concurrent calls (#2, #3) | High — causes Flutter-side hangs |
Redundant removeObserver in callback (#4) |
Low — cosmetic |
Overall the deferral logic is correct. The concurrent-call handling is the main issue to fix before shipping.
#1 - I would not treat this as a required fix. The plugin uses the default FlutterMethodChannel registration, and Flutter’s docs say handlers run on the platform main thread unless you opt into a background task queue. Sources: Flutter platform channels and Flutter iOS embedder docs. Wrapping this in DispatchQueue.main.async is defensive, not necessary for current behavior. |
No description provided.