deniza / app_tracking_transparency

A Flutter plugin to show ios 14+ tracking authorization dialog.
https://pub.dev/packages/app_tracking_transparency/
MIT License
83 stars 28 forks source link

ATT is not showing in iOS 17.0.1 (Rejected by team) #47

Closed blk-raffy closed 9 months ago

blk-raffy commented 9 months ago

Hi, I am using the latest version of app_tracking_transparency in my flutter app. The team rejected my app caused by:

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.0.1.
void main() async {

  WidgetsFlutterBinding.ensureInitialized()
      .addPostFrameCallback((_) => initPlugin());

  // rest of my app ...
}

Future<void> initPlugin() async {
  if (Platform.isIOS &&
      int.parse(Platform.operatingSystemVersion.split(' ')[1].split('.')[0]) >=
          14) {
    final TrackingStatus status =
        await AppTrackingTransparency.trackingAuthorizationStatus;
    // If the system can show an authorization request dialog
    if (status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
    }
  }
}
deniza commented 9 months ago

I recommend initializing/using plugin after your main user interface is initialized, and also after a slight delay by using in a Future.delayed call. You may also check the sample implementation in pub.dev example.

blk-raffy commented 9 months ago

Same for me, I tried to change the code following literally the example on pub.dev as suggested by @deniza and my app still getting regjected, Two weeks ago I didn't have this issue, I think something changed on the ATT swift library.

Xcode does not provide any error log so I don't know how to fix It

clairtonluz commented 9 months ago

I have the same issue, some one resolved this problem?

jostney commented 9 months ago

Not only this library, also native ways producing same error

clairtonluz commented 9 months ago

Testing here I noticed that the permission question was not appearing because it was previously asking for another permission. So I modified the code to first ask for app tracking permission and it apparently resolved it in my tests.

toco1001 commented 9 months ago

I have the same issue.

ExPrLtd commented 9 months ago

Same issue here, but I've found that my app crashes even when tapping a button to call the function and nothing else.

Rileyjrjohns commented 9 months ago

Hey there, got the same issue, fix it following this => https://github.com/deniza/app_tracking_transparency/issues/44#issuecomment-1586821838

do something like this solve the issue

Capture d’écran 2023-10-03 à 10 11 14

blk-raffy commented 9 months ago

Hey there, got the same issue, fix it following this => #44 (comment)

do something like this solve the issue

Capture d’écran 2023-10-03 à 10 11 14

Unfortunately my code has already this workaround to pass AppStoreConnect checking routine, but this time with iOS 17.0.1 does not work anymore

import UIKit
import Flutter
import AppTrackingTransparency
import AdSupport

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  override 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")
            }
        }
    }
  }
}
Rileyjrjohns commented 9 months ago

@blk-raffy i also did this https://github.com/deniza/app_tracking_transparency/issues/44#issuecomment-1581994132 Prior any other method when app launch Capture d’écran 2023-10-03 à 10 48 03

with a retry method did you try this ? i've both implemented and it work with the flutter latest version

blk-raffy commented 9 months ago

@Rileyjrjohns I will definetely try, thanks. If this works I'll let you know. Give me 2-3 working days to check if appstoreconnect accept my new version

Rileyjrjohns commented 9 months ago

I retry to submit my app, everything work in debug, in my devices in ios 17.0.1, but still rejected by apple. These testing guy are not really competent initially and apple just released a bugged ios version...

clairtonluz commented 9 months ago

I retry to submit my app, everything work in debug, in my devices in ios 17.0.1, but still rejected by apple. These testing guy are not really competent initially and apple just released a bugged ios version...

I have the same problem, I fix the problem here. Its working when runing locally and I test by TestFlight and its working too, but apple reject my app saying that my app not is asking by app tracking transparency.

But my app is asking and I send the print attached. but apple reject the same way.

I don`t know what I need do to app be approved.

ExPrLtd commented 9 months ago

I wasn't able to fix it, but I was able to get my app approved last night by pointing out it's an iOS 17 issue and referenced this thread.

@clairtonluz What was your fix?

clairtonluz commented 9 months ago

I wasn't able to fix it, but I was able to get my app approved last night by pointing out it's an iOS 17 issue and referenced this thread.

@clairtonluz What was your fix?

In my case the promp was hidded because I request permission to notification together, so the iOS only show the first request. I changed my code to request only App Tracking Transparency request permition first and after this request be answered I call next request permition. This solve my problem, but the apple say that it`s not solved. But I tested the app in Simulator and in my Iphone 13 pro max and this feature is working perfectly.

Sadmansamee commented 9 months ago

Doing this on App Widget seems to be working

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      _trackingTransparencyRequest();
    });
  }

  Future<String?> _trackingTransparencyRequest() async {
    await Future.delayed(const Duration(milliseconds: 1000));

    final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
    if (status == TrackingStatus.authorized) {
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    } else if(status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    }

    return null;
  }

Here await Future.delayed(const Duration(milliseconds: 1000)); is crucial, without this line of code it doesn't work! strange!

Rileyjrjohns commented 9 months ago

@Sadmansamee did apple validate your app with this fix ?

Sadmansamee commented 9 months ago

@Rileyjrjohns yup, it was accepted

Sadmansamee commented 9 months ago

Main idea of this issue is, this prompt needs to be shown when App is fully running and view is there, that's why on initstate and 1s delay.

toco1001 commented 9 months ago

Finally I passed the app review by this way. Thanks you!!

https://github.com/deniza/app_tracking_transparency/issues/47#issuecomment-1746697074

clairtonluz commented 9 months ago

I have solved this issue but the apple keeping reject my app. Apple say that I need implement the request permission, but I have implemented it. So after trying explain that it was implemented and be reject 2 times more I request a call of a member of the Apple to discuss about it. When the member of Apple call to me he says that the request is implemented and that he will approve my request. But I can`t understood why not approved before the call. But I`m glad it was resolved.

amendezcabrera commented 9 months ago

I could solve it by using the @Sadmansamee code snippet, approved by the Apple Store app validation team too after one refused request previous to this changes. Thank you very much.

Doing this on App Widget seems to be working

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      _trackingTransparencyRequest();
    });
  }

  Future<String?> _trackingTransparencyRequest() async {
    await Future.delayed(const Duration(milliseconds: 1000));

    final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
    if (status == TrackingStatus.authorized) {
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    } else if(status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    }

    return null;
  }

Here await Future.delayed(const Duration(milliseconds: 1000)); is crucial, without this line of code it doesn't work! strange!

blk-raffy commented 9 months ago

My app was approved by using this code:

export 'lib.dart';
import 'dart:io';

import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:flutter/services.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized()
      .addPostFrameCallback((_) => _trackingTransparencyRequest());

  // other stuff ...

}

Future<String?> _trackingTransparencyRequest() async {
  await Future.delayed(const Duration(milliseconds: 1000));
  if (Platform.isIOS &&
      int.parse(Platform.operatingSystemVersion.split(' ')[1].split('.')[0]) >=
          14) {
    final TrackingStatus status =
        await AppTrackingTransparency.trackingAuthorizationStatus;
    if (status == TrackingStatus.authorized) {
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    } else if (status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    }
  }

  return null;
}

The issue is only on iOS17

Feel free to re-open if this solutions doesn't work for you.

gferreirakalshi commented 9 months ago

Adding the code below at AppDelegate.swift solved the issue for me:

    override func applicationDidBecomeActive(_ application: UIApplication) {
        if #available(iOS 15.0, *) {
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in

            })
        }
    }

This code will show the permission popup at app startup, you won't have too much control but at least you should be able to get your app approved and won't need to add Future.delay like the other solutions

NahitCalisir commented 4 months ago

Doing this on App Widget seems to be working

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      _trackingTransparencyRequest();
    });
  }

  Future<String?> _trackingTransparencyRequest() async {
    await Future.delayed(const Duration(milliseconds: 1000));

    final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
    if (status == TrackingStatus.authorized) {
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    } else if(status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    }

    return null;
  }

Here await Future.delayed(const Duration(milliseconds: 1000)); is crucial, without this line of code it doesn't work! strange!

This method fixed my problem. Thanks

BrainCoreLab commented 4 months ago

I work with flutterflow...it is placed in a widget or a custom action, what would be the correct way to do it?

eudaldpons commented 1 month ago

Doing this on App Widget seems to be working

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_){
      _trackingTransparencyRequest();
    });
  }

  Future<String?> _trackingTransparencyRequest() async {
    await Future.delayed(const Duration(milliseconds: 1000));

    final TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
    if (status == TrackingStatus.authorized) {
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    } else if(status == TrackingStatus.notDetermined) {
      await AppTrackingTransparency.requestTrackingAuthorization();
      final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
      return uuid;
    }

    return null;
  }

Here await Future.delayed(const Duration(milliseconds: 1000)); is crucial, without this line of code it doesn't work! strange!

That works for me. Thanks!!!