firebase token is null and token refresh is called continously in my testFlight - iphone

First of all, i have no problem for FCM, firebase token is never null every time tokenRefreshNotification is called. But after, i add Google analytics, i got weird problem for Firebase token. Every time i turn off and turn on notification in my app settings used
UIApplication.shared.registerForRemoteNotifications()
my tokenRefreshNotification is called continously and it doesn't stop looping until i force close my apps. At first, my app crash, and when i try to trace it with NsLog, i found that Firebase token is null. The problem occurs only when i`m using my apps installed from TestFlight / production. When i try it from my Xcode builder, firebase token is null only once, but the second call, firebase token is exist and it stop working.
For google Analytics, it works fine and in my GoogleService-info.plist,
i have set IS_ANALYTICS_ENABLED to YES and IS_GCM_ENABLED to YES also. For the other, IS_ADS_ENABLED = YES, IS_APPINVITE_ENABLED = NO, and IS_SIGNIN_ENABLED = YES
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
NotificationCenter.default.addObserver(self, selector: #selector(self.registerNotification), name: NSNotification.Name(rawValue: "registerNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification(_:)), name: .firInstanceIDTokenRefresh, object: nil)
setupGoogleAnalytics()
return true
}
//when firebase token is null, this function is working continously until my firebase token is exist
func tokenRefreshNotification(_ notification: Notification) {
print("token Refresh")
if FIRInstanceID.instanceID().token() == nil{
NSLog("firebase token is null")
}
if (UserDefaults.standard.object(forKey: "id") != nil) && FIRInstanceID.instanceID().token() != nil{
FIRInstanceID.instanceID().getWithHandler({ (instanceID, error) in
NSLog("instanceID: \(instanceID!)")
//save firebase token to my database, sorry i can`t show it
})
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
Note: At the first launch, i called my RegisterForRemoteNotifications, at TestFlight version, when tokenRefreshNotification is called, the firebase token is null, but the second call, firebase token is exist, so it could stop. But, when i run my app from Xcode, the first call is success because firebase token is not null.

i have figured it out! just change ANPS Type token from Sandbox to Unknown!
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// With swizzling disabled you must set the APNs token here.
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.unknown)
}

Related

didReceiveRemoteNotification not being called on MacCatalyst

When I create a CKSubscription, didReceiveRemoteNotification gets called on iOS just fine but not on MacOS. I came across a 2015 SO thread talking about a bug and the suggested workaround was to set the notification info's soundName to an empty string - unfortunately that didn't resolve the issue for me.
Here is how I register my remote notifications:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let subscription = CKQuerySubscription(recordType: "Reminder", predicate: NSPredicate(format: "TRUEPREDICATE"), options: [.firesOnRecordCreation, .firesOnRecordUpdate])
// Here we customize the notification message
let info = CKSubscription.NotificationInfo()
info.shouldSendContentAvailable = true
info.desiredKeys = ["identifier", "title", "date"]
info.soundName = ""
subscription.notificationInfo = info
// Save the subscription to Private Database in Cloudkit
CKContainer.default().privateCloudDatabase.save(subscription, completionHandler: { subscription, error in
if error == nil {
// Subscription saved successfully
} else {
// Error occurred
}
})
}
This has to do with the bundle identifier being different on Mac Catalyst. Thanks to the soon to be introduced universal app purchase, catalyst apps can now bear the same bundle identifier as their iOS counterpart, and that fixes the issue.
Note that I was also experiencing issues with cloudkit key values not syncing on Mac (NSUbiquitousKeyValueStore). Having a single bundle id for Mac and iOS fixed the problem too.

Can I convert a String into a SINCall?

Im working with sinch and using firebase as my database and using its cloud functions to send notifications. Sending notifications are working fine but the shouldSendPushNotifications function but it never gets called so i can't add the sinch payload to the notification data and I couldn't find anything on the internet of a solid working example so I gave up on that and decided to send the SINcall object to the database and the callee will retrieve it and answer that.
But the problem is that firebase only stores strings so when I retrieve the SINCall I stored i get an error Could not cast value of type '__NSCFString' (0x102096998) to '__ObjC.SINCall' (0x10209ab08). So is there a way to convert this to a SINCall so I can answer, decline, etc with it?
EDIT:
this is where i have my code in AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("USERINFO: \(userInfo["sin"]!)") <-- prints call: <SINCallImpl: 0x1c00f2600>
let incomingCall = userInfo["sin"]!
SINClientManager.shared.call = incomingCall as! SINCall <-- Error occurs
...
}
You need to send the data to the sinch client to set up the call, you cant convert a string to a call.
NSString* payload = [remotePush objectForKey:#"SIN"];
// Get previously initiated Sinch client
id<SINClient> client = [self sinchClient];
id<SINNotificationResult> result = [client relayRemotePushNotificationPayload:payload];
if (result.isCall && result.callResult.isTimedOut) {
// Present alert notifying about missed call
} else if (!result.isValid) {
// Handle error
}

How do I get an access token for Firebase Authentication?

I'm using Firebase and FirebaseUI in my project. I want to give the user an options to delete his account, but if the user has been in the app longer than 5 minutes I need to reauthenticate again.
I'm not sure how to fill these parameters in the following method:
+ (FIRAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(NSString *)accessToken;
With the credentials I can call
- (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *) credential
completion:(nullable FIRAuthDataResultCallback) completion
I know the ProviderId from:
Auth.auth().currentUser.providerID
But how do I get the access token?
You can call this function and get the Token!
Swift Code:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
}

Determine login type using AWS Cognito during resume session (Swift)

I'm having a hard time trying to figure out how to determine the login type during a resume session using AWS Cognito. My code is based upon the MobileHub sample (below).
I've integrated a name/password mode for user pools (account creation and login) as well as as a Facebook login button which all works perfectly.
I have some logic in my application that needs to behave differently depending on the login type but I can't figure out how to do it.
Anyone done this?
func didFinishLaunching(_ application: UIApplication, withOptions launchOptions: [AnyHashable: Any]?) -> Bool {
print("didFinishLaunching:")
// Register the sign in provider instances with their unique identifier
AWSSignInManager.sharedInstance().register(signInProvider: AWSFacebookSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(FacebookIdentityProfile.sharedInstance(), forProviderKey: AWSFacebookSignInProvider.sharedInstance().identityProviderName)
AWSSignInManager.sharedInstance().register(signInProvider: AWSCognitoUserPoolsSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(UserPoolsIdentityProfile.sharedInstance(), forProviderKey: AWSCognitoUserPoolsSignInProvider.sharedInstance().identityProviderName)
setupAPIGateway()
setupS3()
let didFinishLaunching: Bool = AWSSignInManager.sharedInstance().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
if (!isInitialized) {
AWSSignInManager.sharedInstance().resumeSession(completionHandler: { (result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
print("didFinishLaunching Result: \(String(describing: result)) AuthState: \(authState) \n Error:\(String(describing: error))")
if authState == .authenticated {
// Facebook or Cognito???
AWSCognitoUserAuthHelper.getCurrentUserAttribute(name: "sub", completionHandler: { (userid) in
// we need to fetch the user
ObjectManager.instance.getUser(userid: userid, completionHandler: { (user) in
ObjectManager.instance.setCurrentUser(user: user)
})
})
}
}) // If you get an EXC_BAD_ACCESS here in iOS Simulator, then do Simulator -> "Reset Content and Settings..."
// This will clear bad auth tokens stored by other apps with the same bundle ID.
isInitialized = true
}
return didFinishLaunching
}
One solution I found was to cast to the different identity profile types such as the following:
let identityManager = AWSIdentityManager.default()
if let fbIdentityProfile = identityManager.identityProfile as? FacebookIdentityProfile {
print("didFinishLaunching - Facebook login")
} else if let upIdentityProfile = identityManager.identityProfile as? UserPoolsIdentityProfile {
print("didFinishLaunching - User Pools login")
}
I can model logic in my application around this. Not sure if there is a cleaner approach using the MobileHub helper classes or AWS APIs but this works.

iOS: cannot request authorization from Spotify app

I'm developping app using spotify-iOS-SDK, i have succesfully connect my app to Spotify from Safari, but when i try to connect my app from Spotify App, it doesn't request authorization in spotify app, instead it throw me back to my app after a checkmark icon show in Spotify and it caused crash to my app because the session is null.
This is my code:
var auth = SPTAuth.defaultInstance()!
auth.redirectURL = URL(string: ENV.SPOTIFY_REDIRECT_URL
auth.clientID = ENV.SPOTIFY_CLIENT_ID
auth.requestedScopes = [SPTAuthStreamingScope, SPTAuthPlaylistReadPrivateScope,
SPTAuthPlaylistModifyPublicScope, SPTAuthPlaylistModifyPrivateScope]
if SPTAuth.supportsApplicationAuthentication(){
UIApplication.shared.openURL(auth.spotifyAppAuthenticationURL())
}else{
if UIApplication.shared.openURL(auth.spotifyWebAuthenticationURL()){
if auth.canHandle(auth.redirectURL) {
// To do - build in error handling
}
}
}
I have put spotify-action in my LSApplicationQueriesSchemes. What am i doing wrong here? I saw DemoProject from https://github.com/spotify/ios-sdk
and it worked. It should request authorization right after my app go to Spotify App
You need some code in your AppDelegate that looks like follows:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let auth = SPTAuth()
if auth.canHandle(auth.redirectURL) {
auth.handleAuthCallback(withTriggeredAuthURL: url, callback: { (error, session) in
// Do other things to save session...
return true
}
return false
}
i have resolved my issues, the problem is my Bundle ID in my app is different from my BundleID in my Spotify Dashboard.
https://developer.spotify.com/my-applications
Just match my bundle ID and it worked!