iOS Question [SOLVED] Question about App Tracking Transparency - iOS 15

Pendrush

Well-Known Member
Licensed User
Longtime User
Is this solution still valid for iOS 15?


I have a doubt about this line:
B4X:
 if (@available(iOS 14, *)) {

EDIT:
This code
B4X:
Dim no As NativeObject = Me
no.RunMethod("requestIDFA", Null)
Wait For GAD_TrackingAuthorization (Status As Int)
Log ("IDFA Status: " & Status)

#if OBJC
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
    if (@available(iOS 14, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(status)]];
      }];
  } else {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(3)]];
    }
}
#End If

Return IDFA Status: 0 on first app run, without showing dialog. After killing app and start app again IDFA dialog is shown.
This behavior is only on iOS 15. My app is declined as they cannot find App Tracking Transparency dialog on the first run.
 
Last edited:
Solution
This is working code for iOS 15 when you have some dialog(s) and ATT dialog, for example, notification dialog and ATT dialog:
B4X:
#AdditionalLib: AppTrackingTransparency.framework
#PlistExtra: <key>SKAdNetworkItems</key><array><dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict></array>
#PlistExtra: <key>NSUserTrackingUsageDescription</key>
#PListExtra: <string>This identifier will be used To deliver personalized ads To you.</string>

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
    Private TimerIdfa As Timer
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav...

Erel

B4X founder
Staff member
Licensed User
Longtime User
if (@available(iOS 14, *)) {
This nested code will run on iOS 14+.

I've created a new B4XPages project with this code:
B4X:
#AdditionalLib: AppTrackingTransparency.framework
#PlistExtra: <key>SKAdNetworkItems</key><array><dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict></array>
#PlistExtra: <key>NSUserTrackingUsageDescription</key>
#PListExtra: <string>This identifier will be used To deliver personalized ads To you.</string>
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("Page1")
    NavControl.ShowPage(Page1)
End Sub

Sub Button1_Click
    Dim no As NativeObject = Me
    no.RunMethod("requestIDFA", Null)
    Wait For GAD_TrackingAuthorization (Status As Int)
    Log(Status)
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int)
    
End Sub

#if OBJC
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
    if (@available(iOS 14, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(status)]];
      }];
  } else {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(3)]];
    }
 
}

#End If
It works as expected and shows the dialog.
It doesn't matter whether it is a B4XPages project or not.

Try it.
 
Upvote 0

Pendrush

Well-Known Member
Licensed User
Longtime User
OK, I have found example case.
If some other dialog is already open, for example dialog for push notification, App Tracking Transparency dialog will not show and status 0 (undetermined) is returned.
Example NON WORKING code (Status = 0):
B4X:
#AdditionalLib: AppTrackingTransparency.framework
#PlistExtra: <key>SKAdNetworkItems</key><array><dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict></array>
#PlistExtra: <key>NSUserTrackingUsageDescription</key>
#PListExtra: <string>This identifier will be used To deliver personalized ads To you.</string>

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("Page1")
    NavControl.ShowPage(Page1)
    App.RegisterUserNotifications(True, False, True)
    Dim no As NativeObject = Me
    no.RunMethod("requestIDFA", Null)
    Wait For GAD_TrackingAuthorization (Status As Int)
    Log(Status)
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int)
End Sub

#if OBJC
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
    if (@available(iOS 14, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(status)]];
      }];
  } else {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(3)]];
    }
}
#End If

On first run App Tracking Transparency dialog is missing, Status = 0.
On second app start will work as expected.

EDIT:
Thread on Reddit with same problem:


EDIT 2:
As workaround I'm using timer that checks status every 2 seconds. So when user close all dialogs on app start, timer will trigger ATT dialog.
App waiting for review now. I will report review result here.

EDIT 3:
The application is approved. Working code is in post #4.
 
Last edited:
Upvote 1

Pendrush

Well-Known Member
Licensed User
Longtime User
This is working code for iOS 15 when you have some dialog(s) and ATT dialog, for example, notification dialog and ATT dialog:
B4X:
#AdditionalLib: AppTrackingTransparency.framework
#PlistExtra: <key>SKAdNetworkItems</key><array><dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict></array>
#PlistExtra: <key>NSUserTrackingUsageDescription</key>
#PListExtra: <string>This identifier will be used To deliver personalized ads To you.</string>

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
    Private TimerIdfa As Timer
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("Page1")
    NavControl.ShowPage(Page1)  
    TimerIdfa.Initialize("TimerIdfa", 2000)
    App.RegisterUserNotifications(True, False, True)
    TimerIdfa.Enabled = True
End Sub

Sub TimerIdfa_Tick
    CheckIdfa
End Sub

Private Sub CheckIdfa
    TimerIdfa.Enabled = False
    Dim no As NativeObject = Me
    no.RunMethod("requestIDFA", Null)
    Wait For GAD_TrackingAuthorization (Status As Int)
    Log("IDFA Status: " & Status)
    If Status = 0 Then
        TimerIdfa.Enabled = True
        Return
    End If
    'From this line you can continue ADs loading
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int)  
End Sub

#if OBJC
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
    if (@available(iOS 14, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(status)]];
      }];
    } else {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(3)]];
    }
}
#End If
 
Last edited:
Upvote 1
Solution

Computersmith64

Well-Known Member
Licensed User
Longtime User
I see you have solved this issue, but as I was working on this exact issue yesterday I thought I'd chime in. I initially implemented ATT a while ago for iOS14+ apps, but then when I was updating one of them yesterday (Swift in XCode) I noticed it wasn't working in iOS15. After some searching & trial & error I found that if I moved the code from my main ViewController's viewDidLoad method to the AppDelegate's applicationDidBecomeActive method, it works as expected in both iOS14 & iOS15.

Not sure how this translates directly to what you've done, but it might be useful to know if you're still looking for a solution.

- Colin.
 
Upvote 1

tufanv

Expert
Licensed User
Longtime User
This is working code for iOS 15 when you have some dialog(s) and ATT dialog, for example, notification dialog and ATT dialog:
B4X:
#AdditionalLib: AppTrackingTransparency.framework
#PlistExtra: <key>SKAdNetworkItems</key><array><dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict></array>
#PlistExtra: <key>NSUserTrackingUsageDescription</key>
#PListExtra: <string>This identifier will be used To deliver personalized ads To you.</string>

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private xui As XUI
    Private TimerIdfa As Timer
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("Page1")
    NavControl.ShowPage(Page1) 
    TimerIdfa.Initialize("TimerIdfa", 2000)
    App.RegisterUserNotifications(True, False, True)
    TimerIdfa.Enabled = True
End Sub

Sub TimerIdfa_Tick
    CheckIdfa
End Sub

Private Sub CheckIdfa
    TimerIdfa.Enabled = False
    Dim no As NativeObject = Me
    no.RunMethod("requestIDFA", Null)
    Wait For GAD_TrackingAuthorization (Status As Int)
    Log("IDFA Status: " & Status)
    If Status = 0 Then
        TimerIdfa.Enabled = True
        Return
    End If
    'From this line you can continue ADs loading
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int) 
End Sub

#if OBJC
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
    if (@available(iOS 14, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(status)]];
      }];
    } else {
          [self.bi raiseUIEvent:nil event:@"gad_trackingauthorization:" params:@[@(3)]];
    }
}
#End If

Thanks. I am dealing with app review team for the last 2 days.
 
Upvote 0

yiankos1

Active Member
Licensed User
Longtime User
I see you have solved this issue, but as I was working on this exact issue yesterday I thought I'd chime in. I initially implemented ATT a while ago for iOS14+ apps, but then when I was updating one of them yesterday (Swift in XCode) I noticed it wasn't working in iOS15. After some searching & trial & error I found that if I moved the code from my main ViewController's viewDidLoad method to the AppDelegate's applicationDidBecomeActive method, it works as expected in both iOS14 & iOS15.

Not sure how this translates directly to what you've done, but it might be useful to know if you're still looking for a solution.

- Colin.
Good morning,
I had same problem with app review team. A simple solution (without timers) as computersmith says, it is to add idfa code at Sub Application_Active. My apps succeed review.
 
Upvote 0
Top