AppTrackingTransparency and SDK initialization (Facebook, Firebase...) - ios

I'm a bit lost about AppTrackingTransparency and how to initialize some SDKs (like FB or Firebase), especially after a user first install of the app.
I don't want to show the user the app tracking transparency popup IMMEDIATELY after he installs the app because it feels too aggressive. I prefer him to go through a few steps before.
However, I know that I need to initialize some SDKs in the AppDelegate's didFinishLaunching method, i.e.:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Firebase
FirebaseApp.configure()
// FB
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
if #available(iOS 14, *) {
Settings.setAdvertiserTrackingEnabled(true)
}
return true
}
What I'm afraid of is that initializing these SDKs before showing the ATTrackingManager.requestTrackingAuthorization popup later in the app could lead to a rejection from Apple, or these SDKs to not work properly. Or can I let this code like this and call the requestTrackingAuthorization later without any issue?
Thank you

Firebase should always be the last initialization before the return true. Otherwise your code is good.

Related

IOS: Firebase Offline isPersistenceEnabled not working

I am using the following line in my AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Database.database().isPersistenceEnabled = true
return true
}
Is this all I need to add to make my ReactJS app available offline? When I compile and run and test through Testflight - I turn off WIFI and use Airplane Mode and my app just returns a blank screen ... do I have to enable something else?
The Database.database().isPersistenceEnabled = true only ensures that data that you app has recently loaded while online is also available when you call the same API next time while offline.
If the app itself doesn't load, it is unrelated to this API call and you'll want to look at how to make a React app available while offline.

When in iOS applicationDidEnterBackground called immediately after applicationDidBecomeActive?

in our app we are logging (with an external analytics service) every time the user open our app.
However, we have noticed that there are many weird app sessions (almost 15% of total sessions).
Following the device timestamp of the events, the following methods are called:
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
applicationDidBecomeActive(_ application: UIApplication)
viewDidAppear(_ animated: Bool) // App Splash Screen
applicationDidEnterBackground(_ application: UIApplication)
Looking at the timestamp, from didFinishLaunchingWithOptions to applicationDidEnterBackground there is just a very short delay (<1 sec).
Our hypothesis is that the system sometimes wakes up the app without it being actually opened and "seen" by the user. But we can't find any docs about this kind of use case, and we can't reproduce ourself the issue.
Did someone have experienced something similar?
EDIT:
I want to add that these suspicious sessions are often (but not always) linked to an app update.
I'm not sure...
I suppose if app wasn't user terminated nor suspended but was just put out of memory because other apps needed the memory, then almost a launch options can wake the app up if needed. Some examples:
geofence
interaction with push notification's actions. Example if you have userNotificationCenter(_:didReceive:withCompletionHandler:) implemented...
silent notification
background app refresh
Take a look at here and see what launch options are possible for your app. I'm not sure if all of them can actually launch the app or what...
If you want more visibility into this, then make sure for future you log the launchoptionskey that caused the app to get launched...
You need more info - I would extend your logging to dump the launchOptions dictionary in
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
Looking at UIApplication.LaunchOptionsKey, there are a lot of options which may be involved. Note, as the help says: The contents of this dictionary may be empty in situations where the user launched the app directly
if let lop = launchOptions {
let toLog = lop.map{"\($0.0.rawValue) \($0.1)"}.joined(separator:"\n")
// log the options
...}
I did have an idea this might be related to previewing in AppSwitcher but that doesn't seem to trigger didFinishLaunchingWithOptions, unless you actually bring the app to the front. Maybe some split-screen stuff on iPad? It feels like the app is being invoked in a context where it can't get past the launch screen.

How to switch push notification providers without re-prompting to enable push notifications?

There are many third party push notification providers like Appboy (Braze), Localytics, Urban Airship, etc. Our app is in production using "Provider A" but we are switching to "Provider B." Fresh installations get push notifications, but upgrade installations do not. Upon inspection it looks like didRegisterForRemoteNotificationsWithDeviceToken isn't called. How can push be enabled without having to re-prompt the user?
It is enough to call registerForRemoteNotifications in didFinishLaunchingWithOptions. It will trigger didRegisterForRemoteNotificationsWithDeviceToken or didFailToRegisterForRemoteNotificationsWithError callback if they've opted-in. The best part is that the callbacks are triggered if they opt-in sometime in the future (Assuming they've been prompted in-app at least once via registerUserNotificationSettings).
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//...
UIApplication.shared.registerForRemoteNotifications()
//...
}
See:
iOS 8 Remote notifications - When should I call registerForRemoteNotifications()?

Xcode 8 and Swift Could not build Objective C module 'FBSDKLoginKit'

I am having an issue when integrating the latest Facebook SDK 4.16.0 in my Swift 3.0 project using XCode 8. I manually added Facebook SDK to my project
Framework search paths
I got a compiling error saying 'Could not build module FBSDKLoginKit'.
When I navigate into FBSDKLoginKit.h, an error says 'FBSDKLoginKit/FBSDKLoginButton.h' file not found.
I searched and found this might relevant Could not build module 'FBSDKCoreKit' For FacebookSDK 4 . I tried some approaches, however, it has not worked out.
I'm appreciated your helps. Thank you.
I experienced the same issue. I was able to solve it thanks to this link. The link was actually useful in completely getting my swift project integrated with the facebook sdk. But because the post might have been a little outdated, I had to do a few things differently. One in particular is my appdelegate. Here's how mine looked when I was done.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
{
return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options)
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
FBSDKAppEvents.activateApp()
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
So basically following the link would be helpful, but you should make your appdelegate.swift, particularly the application functions and the applicationDidBecomeActive function look as I pasted above.
Also after creating the bridge-header file, adding it to the project build settings looked like this.
In the link it says it should include the directory of the project like so:
projectName/Bridging-Header.h but when I tried that, it seemed it was already looking from my project directory so it ended up looking for my header file at projectName/projectName/Bridging-Header.h which is an invalid path. So I added mine like the above screenshot instead.

iOS 9 Facebook Access Token is nil on future app launches

After the recent iOS 9 update, along with updates to the Facebook SDK (4.6.0), I'm finding that my login session is no longer persisting between app launches.
My flow so far has been pretty simple.
Login to Facebook using the FBSDKLoginButton.
On future View's and Launches check the FBSDKAccessToken.currentAccessToken() to be able to then use Facebook in the app.
What I'm finding is after the recent updates my AccessToken is now showing up as nil if I close and start the app again. This is a major issue because previously, I only had to login once, and then my session was being automatically renewed.
If I'm correct, login should only occur once, and after that the app should be able to either store the info it needs to connect to Facebook in the future, or simply remain with a token that refreshes itself.
Does anyone have any ideas what might have changed to cause this after the iOS9 or 4.6.0 Facebook SDK updates? Is there properties that need to be persisted to then refresh the token in the future or is the token supposed to renew automatically? I'm near 100% positive, the intended experience with Facebook SDK is NOT to have to login on every app launch (When you restart the app, close all the way and open again).
Thanks!
Update
As requested in a response, I added an additional key into the TransportSecurity info of my Plist file. Unfortunately, no luck still.
Adding this line on didFinishLaunchingWithOptions worked for me:
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
Final method looks something like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
if let accessToken = FBSDKAccessToken.currentAccessToken(){
print(accessToken)
}else{
print("Not logged In.")
}
return true
}
Reference
This happened to me also when upgrading to FBSDK 4.18.0
Downgrading to 4.17.0 solved it for me.
Even it didn't worked for me when I updated my iOS 9 but after try this solution it worked for me.
1) Add data in info.plist as shown image
For iOS 11 / Swift 4 you should add the following code to your AppDelegate:didFinishLaunchingWithOptions
SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
Final code is:
import FacebookCore
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.\
// FACEBOOK CONFIGURATION
SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}

Resources