app_tracking_transparency
app_tracking_transparency copied to clipboard
Authorisation popup is not showing in iOS 16.5
Hi Team,
i am using the latest version of ATT in my flutter app when i published my app to app store they rejected saying:
We're looking forward to completing our review, but we need more information to continue. Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 16.5.
Method:
Future<void> initPlugin() async { // Platform messages may fail, so we use a try/catch PlatformException. try { final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus; setState(() => _authStatus = '$status'); // If the system can show an authorization request dialog if (status == TrackingStatus.notDetermined) { final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization(); setState(() => _authStatus = '$status'); if (status == TrackingStatus.authorized && defaultTargetPlatform == TargetPlatform.iOS) { _webViewController!.evaluateJavascript( source: 'document.getElementById("onetrust-accept-btn-handler").click()', ); } } } on PlatformException { setState(() => _authStatus = 'PlatformException was thrown'); } final uuid = await AppTrackingTransparency.getAdvertisingIdentifier(); if (kDebugMode) { print("UUID: $uuid"); }
Calling:
void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => initPlugin()); }
Can you write in formatted text with three back quote?
Did you try it? https://github.com/deniza/app_tracking_transparency/issues/32
TrackingStatus authorizationStatus =
await AppTrackingTransparency.trackingAuthorizationStatus;
int timeoutCount = 0;
while (authorizationStatus == TrackingStatus.notDetermined &&
timeoutCount < 10) { // Adjust yourself.. maybe up to ~50
authorizationStatus =
await AppTrackingTransparency.requestTrackingAuthorization();
await Future.delayed(const Duration(milliseconds: 200));
timeoutCount++;
}
I have the same issue today. Apple reject since it is not working for iOS 16.5, Did you already find out the solution ? @amitaman
@luminkhant i was facing this same issue. I added bellow code in appDelegate.swift file and Authorisation default alert showing in iOS 16+
func applicationDidBecomeActive(_ application: UIApplication) {
if #available(iOS 14, *) {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
// Tracking authorization dialog was shown
// and we are authorized
print("Authorized")
case .denied:
// Tracking authorization dialog was
// shown and permission is denied
print("Denied")
case .notDetermined:
// Tracking authorization dialog has not been shown
print("Not Determined")
case .restricted:
print("Restricted")
@unknown default:
print("Unknown")
}
}
}
}
hi @Zaveri21
The code you provided is printing current tracking status. Could you please explain what else you did to make it work in your case? Thank you.
I would like to hear more details too @Zaveri21 how you got this fixed, thanks!
Hi @deniza & @JariHuomo Happy coding 😀
My app was approved and live in apple store with the help of above code block.
this swift code will work for iOS 14 or above version. ATTrackingManager.requestTrackingAuthorization
used for ask permission so that default iOS permission alert will open. so I added this code in my applicationDidBecomeActive
method so on app launch/active I am able to prompt alert until package app_tracking_transparency issue resolved. I used this package flutter side to handle App tracking transparency for lower version nothing changed in dart side code.
Thanks for the explanation. I want to present further information and recommend a more flutter friendly approach:
The applicationDidBecomeActive function in iOS is called when your app is brought to the foreground. This can happen when the user taps on your app icon, or the app moved from inactive to active state.
Showing a native dialog in iOS will result in the application switching to the inactive state. This is because the dialog will take focus away from your app, and the system will need to pause your app's execution until the dialog is dismissed.
You can not display ATT dialog when the application is in inactive state. I suspect that your application somehow become inactive during the call to requestTrackingAuthorization function and hence does not work properly. The most common reason for this to happen is that you request some other permission like notification permission, or camera usage permission that also shows a native dialog and sends your app to inactive state.
You can always check that your application is in an active state before calling requestTrackingAuthorization function. In your stateful widget, override didChangeAppLifecycleState function like this:
class _MyWidgetState extends State<MyApp> {
...
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
// App has been brought to the foreground.
// call ATT functionality here. ie: ATTrackingManager.requestTrackingAuthorization
}
}
Below approach is better than calling ATT in a delayed Future call, or in a loop as suggested by other fellow developers. Also you stay in the dart side instead of native code, which may be more preferable.
Please try it if you have any issues and respond this thread if it's working or not working in your use case.
I have the same issue today. Apple reject since it is not working for iOS 16.5, Did you already find out the solution ? @amitaman
Hi @luminkhant My app is also got approved. i used an extra dialog, before showing the actual Authorization dialog.
// Platform messages may fail, so we use a try/catch PlatformException.
try {
final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
setState(() => _authStatus = '$status');
// If the system can show an authorization request dialog
if (status == TrackingStatus.notDetermined) {
// Show a custom explainer dialog before the system dialog
if (await **showCustomTrackingDialog(context)**) {
// Wait for dialog popping animation
await Future.delayed(const Duration(milliseconds: 200));
// Request system's tracking authorization dialog
final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization();
setState(() => _authStatus = '$status');
}
if (status == TrackingStatus.authorized && defaultTargetPlatform == TargetPlatform.iOS) {
//
}
}
} on PlatformException {
setState(() => _authStatus = 'PlatformException was thrown');
}
final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
if (kDebugMode) {
print("UUID: $uuid");
}
}```
```Future<bool> showCustomTrackingDialog(BuildContext context) async =>
await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Dear User'),
content: const Text(
Constants.attMessage,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Continue'),
),
],
),
) ??
false;```
The problem seems on Apple. They rejected my app update with the same reason. But when i installed ios 16.5 on an iPhone and work it, I saw that permission was requested. Somehow i think there is a problem during the review. I sent the screen recording of the application and explained that the request came to the screen as soon as the application was opened and this time they approved it. I think there is no problem with the package.
我的项目是Flutter创建的,iOS端语言使用的是OC,针对该问题我的解决方案如下:
在AppDelegate.m文件中加入以下代码:
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/ASIdentifierManager.h>
- (void)applicationDidBecomeActive:(UIApplication *)application { if (@available(iOS 14, *)) { // iOS14及以上版本先请求权限 [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { // 获取到权限后使用老方法获取idfa if (status == ATTrackingManagerAuthorizationStatusAuthorized) { NSString *idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; NSLog(@"%@",idfa); } else { NSLog(@"请在设置-隐私-跟踪中允许App请求跟踪"); } }]; } else { // iOS14以下版本使用老方法 // 判断在设置-隐私里是否打开了广告跟踪 if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) { NSString *idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; NSLog(@"%@",idfa); } else { NSLog(@"请在设置-隐私-广告中打开广告跟踪功能"); } } }
where i have to access package from app_tracking_transparency ?
HI all, i am facing this issue on IOS 16.6, unable to see the ATT prompt on ios 16.6 whereas it is coming in previous versions. any solution for it, please guide, thanks,
is there package that i have modified ? i want to try it to modify support iOS 16.6
Has anyone found a workaround for this package to work with iOS 16.6 ?
Apple keep rejecting now.
Hi. I tested the package both on ios 16.5 and 16.6 and it seems working fine for me. Please try to call it delayed in a Future.delayed callback, or use an explainer dialog before showing native ATT dialog.
Same issue. Now I changed this plugin to permission_handler. I hope they will approve it. Btw if you want to crate fix for this plugin you can compare this two files (I know, the second one is not Swift):
https://github.com/deniza/app_tracking_transparency/blob/master/ios/Classes/SwiftAppTrackingTransparencyPlugin.swift
https://github.com/Baseflow/flutter-permission-handler/blob/main/permission_handler_apple/ios/Classes/strategies/AppTrackingTransparencyPermissionStrategy.m
This plugin, or any of the att plugins out there do nothing fancy actually. We just check and return ATT status with one function call; ATTrackingManager.trackingAuthorizationStatus, and show ATT dialog by using another api call; ATTrackingManager.requestTrackingAuthorization.
Other then some cosmetic differences both of the implementations are the same; just a basic wrapper around native functionality.
Thank you for your quick reply @deniza!
I missed that example with description: https://github.com/deniza/app_tracking_transparency/blob/a072384e2299ad3021aab2ca5e6031a7bf40079e/example/lib/main.dart#L31C3-L31C89 I hope that now the application will pass Apple's review without any problems.
Today , we got from app reviewer...
I think the request dialog is not reopen when user reject this auth
Hey @deniza thanks for your work and the active contributions. What is your suggested approach of resolving this issue occuring?
calling the ATT dialog in didChangeAppLifecycleState
, or something like awaiting a delayed future?
EDIT: Assuming your example code is already in use, calling the dialog after initialization is comple.
Hi there
I encounter the similar problem. App rejected by Apple "We're looking forward to completing our review, but we need more information to continue. Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 17.3." As I am using XCode 15.2, I can't test with a simulator with an iOS version higher than 17.2 (Thanks Apple for not providing the right tools to test without a real device).
Anyway, here is the code I use
My main widget is a ConsumerStatefulWidget
(from riverpod)
InitState method
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_requestAppTracking();
});
}
_requestAppTracking method
Future<void> _requestAppTracking() async {
Future<void>.delayed(timeout).then((value) async {
final TrackingStatus status =
await AppTrackingTransparency.trackingAuthorizationStatus;
developer.log('Tracking Status Init: $status');
// If the system can show an authorization request dialog
if (status == TrackingStatus.notDetermined) {
// Request system's tracking authorization dialog
final TrackingStatus status =
await AppTrackingTransparency.requestTrackingAuthorization();
developer.log('Tracking Status After Request: $status');
}
ref.read(splashStateProvider.notifier).updateState(SplashState.initGame);
});
}
build method
@override
Widget build(BuildContext context) {
ref.listen<SplashState>(splashStateProvider,
(SplashState? previousState, SplashState newState) async {
switch (newState) {
case SplashState.ready:
Navigator.pushNamed(
context,
"/home",
);
break;
case SplashState.initGame:
await _initApp();
break;
case SplashState.requestAppTransparency:
break;
}
});
...
_initApp method
Future<void> _initApp() async {
//bunch of services initialization. Not relevant here
ref.read(splashStateProvider.notifier).updateState(SplashState.ready);
}
I finally could get my hands on a device with 17.3 installed and indeed the AppTrackingPopup does not show during the startup. What is even weirder is that the app navigates to the "home" screen (as stated in the listen section in build()). This only happens if the await AppTrackingTransparency.requestTrackingAuthorization()
directly returns without waiting for action from the user.
I am a bit lost here. Anyone with similar issue with 17.3 ? Thanks for your help
@G4SD3O I have the same issue today. Apple reject my app since it is not working for iOS 17.3 .
Guideline 2.1 - Information Needed We're looking forward to completing our review, but we need more information to continue. Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 17.3. ~~
It works on the simulator with iOS 17.2 and the release note for iOS 17.3 does not indicate major change in this area so this is very weird. @deniza any thoughts? ;)
To expedite the troubleshooting process, I'd like to suggest testing the plugin with a simplified test code. This is often helpful in isolating potential conflicts or integration issues within your larger app's codebase. Can you please test the plugin in such a test environment?
I have created a simple project to reproduce the issue. Here are my first results:
- it works perfectly using a simulator with iOS 17.2
- I have been testing on a real phone with iOS 17.3 but this one belongs to my daughter who is less than 18 years old so the tracking is automatically disabled (status = TrackingStatus.restricted). That is why the ATT popup never appears. Good to know for future tests
I still need to find a real phone with iOS 17.3 as the latest Xcode version does not allow me to test this version.
Does anyone know an online service (free or very cheap) we can use to do further testing?