I am trying to handle the firebase invites when using universal links.
When a user clicks on the invitation link, from the e-mail for example, the method below is called.
How to get the invitation from the url?
#available(iOS 8.0, *)
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
let handled = FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
// ...
}
return handled!
}
To get the invitation i need to call
FIRInvites.handleURL(url, sourceApplication:sourceApplication, annotation:annotation)
I think the problem lays on what to pass to application and annotation parameters. I already try passing the bundled on sourceApplication but has no effect.
Note: Methods used in firebase invitation example are not called once continueUserActivity method is added.
Try this one.
It's in objective c but you can concert it to swift also. Hope this help you.
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
{
NSURL *url = userActivity.webpageURL;
FIRDynamicLinks *links = [FIRDynamicLinks dynamicLinks];
if([links matchesShortLinkFormat:url])
{
[links resolveShortLink:url completion:^(NSURL * _Nullable url, NSError * _Nullable error)
{
NSString *message =
[NSString stringWithFormat:#"Deep link \n:%#",
url];
[[[UIAlertView alloc] initWithTitle:#"Deep-link Data"
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}];
return YES;
}
return false;
}
Related
i'm adding Facebook and Google signup in my application but i have this issue
The operation couldn’t be completed. -10814
in the Facebook login and i don't know how to solve it, this is my app delegate code for the openUrl:
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any])
-> Bool {
if let fbSDKAppId = FBSDKSettings.appID(), url.scheme!.hasPrefix("fb\(fbSDKAppId)"), url.host == "authorize" {
var shouldOpen :Bool = FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication:options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!,annotation:options[UIApplicationOpenURLOptionsKey.annotation])
return shouldOpen
}
else {
return GIDSignIn.sharedInstance().handle(url,
sourceApplication:options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
annotation: [:])
}
}
what i can do?
now I used the latest SDK v4.26.0 downloaded from here and I followed the link for steps to install for FB. and my code is
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
if ([[[UIDevice currentDevice] systemVersion] floatValue] <= 9) {
// After iOS9 we can not use it anymore
login.loginBehavior = FBSDKLoginBehaviorSystemAccount;
} else {
login.loginBehavior = FBSDKLoginBehaviorWeb;
}
NSArray *permission = [[NSArray alloc] initWithObjects:#"email",#"public_profile",#"user_friends", nil];
NSLog( #"### running FB sdk version: %#", [FBSDKSettings sdkVersion] );
[login logInWithReadPermissions:permission fromViewController:(UIViewController *)self handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
[self removeActivityIndicatorWithBg:activityIndicator];
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
NSLog(#"Logged in%#",result.grantedPermissions);
}
}];
here i used the login behavior as FBSDKLoginBehaviorSystemAccount and I get the error as
(- error: "The operation couldn’t be completed. -10814)
so in my simulator or device contains no accounts setup in system settings for facebook. then it comes on the following block
if (error) {
NSLog(#"Process error");
}
if I print the error,
No Facebook account.
There are no Facebook accounts configured. You can add or create a Facebook account in Settings.
so I changed the loginBehavior from FBSDKLoginBehaviorSystemAccount to FBSDKLoginBehaviorWeb, I got all OP with out error
Worked after adding openUrl with options:
Facebook documentation
Note that application:openURL:options: is only available in iOS 9 and above. If you are building with an older version of the iOS SDK, you can use:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
BOOL handled = [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation
];
// Add any custom logic here.
return handled;
}
LSApplicationQueriesSchemes property set in info.plist has solved the problem for me.
Check attached screenshot:
In this thread you can find an issue and a temporary fix for such kind of error.
I read up on all the posts I could find and am still getting a nil URL when launching the app for the first time after tapping a dynamic link pasted into the Notes app on iOS. Actually I followed the video:
https://www.youtube.com/watch?v=sFPo296OQqk
Universal Links work fine and as expected through application(_:continue:restorationHandler:).
When coming through application(_:open:options:) (formerly application:openURL:options:) however, the URL comes in as <my-scheme-name>://google/link/?is_weak_match=1. No matter how I configure my project/app, the URL is always nil. Also, application(_:open:options:) is called on every first launch of the app regardless of whether a dynamic link was tapped before the app was installed or not. Is that to be expected?
Configuration:
apple-app-site-association file is set up and looks good for Universal Links.
Custom URL scheme set up in Info.plist.
Using latest GoogleService-Info.plist
Not in Safari 'Private' Mode
Calling in didFinishLaunchingWithOptions
[FIROptions defaultOptions].deepLinkURLScheme = CUSTOM_URL_SCHEME;
[FIRApp configure];
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
// Handle the deep link. For example, show the deep-linked content or
// apply a promotional offer to the user's account.
// [START_EXCLUDE]
// In this sample, we just open an alert.
NSString *message = [self generateDynamicLinkMessage:dynamicLink];
[self showDeepLinkAlertViewWithMessage:message];
// [END_EXCLUDE]
return YES;
}
// [START_EXCLUDE silent]
// Show the deep link that the app was called with.
[self showDeepLinkAlertViewWithMessage:[NSString stringWithFormat:#"openURL:\n%#", url]];
// [END_EXCLUDE]
return NO;
}
// [END openurl]
// [START continueuseractivity]
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler
{
// [START_EXCLUDE silent]
NSLog(#"%#", userActivity.webpageURL);
__weak AppDelegate *weakSelf = self;
// [END_EXCLUDE]
BOOL handled = [[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink,
NSError * _Nullable error) {
// [START_EXCLUDE]
AppDelegate *strongSelf = weakSelf;
NSString *message = [strongSelf generateDynamicLinkMessage:dynamicLink];
[strongSelf showDeepLinkAlertViewWithMessage:message];
// [END_EXCLUDE]
}];
// [START_EXCLUDE silent]
if (!handled) {
// Show the deep link URL from userActivity.
NSString *message =
[NSString stringWithFormat:#"continueUserActivity webPageURL:\n%#", userActivity.webpageURL];
[self showDeepLinkAlertViewWithMessage:message];
}
// [END_EXCLUDE]
return handled;
}
// [END continueuseractivity]
- (NSString *)generateDynamicLinkMessage:(FIRDynamicLink *)dynamicLink {
NSString *matchConfidence;
if (dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong) {
matchConfidence = #"strong";
} else {
matchConfidence = #"weak";
}
NSString *msg = [NSString stringWithFormat:#"App URL: %#\n"
#"Match Confidence: %#\n",
dynamicLink.url, matchConfidence];
return msg;
}
- (void)showDeepLinkAlertViewWithMessage:(NSString *)message {
UIAlertAction *okAction = [UIAlertAction actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
NSLog(#"OK"); }];
UIAlertController *alertController =
[UIAlertController alertControllerWithTitle:#"Deep-link Data"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:okAction];
[self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
}
Setup:
Xcode 8.3
Deployment target: iOS 10.3.3
Objective-C
Please try to connect to Cellular and WiFi and repeat the experiment. Also connecting to different WiFi networks may help to figure out the issue. If your WiFi has small number of public facing IP addresses than retrieving pending dynamic link may fail. Also see suggestions in this answer Firebase Dynamic Links not survive installation
If that does not work, I suggest opening support ticket with Firebase.
About link <my-scheme-name>://google/link/?is_weak_match=1 you are receiving: this link being sent by FDL iOS SDK to communicate the event that pending dynamic link is not available. You will receive this link only after first launch of the application. If we found pending dynamic link, we will pass that dynamic link instead.
I know that the openParentApplication api in watch kit extension can open the host app in the background but not in the foreground.
I also tried using openUrl() api of NSExtensionContext as below:
NSExtensionContext *ctx = [[NSExtensionContext alloc] init];
NSURL *url = [NSURL URLWithString:#"myScheme://today"];
[ctx openURL:url completionHandler:^(BOOL success) {
NSLog(#"fun=%s after completion. success=%d", __func__, success);
}];
[ctx completeRequestReturningItems:ctx.inputItems completionHandler:nil];
Here too the host app is not launched. Am I missing something? or is it not possible to
launch the host app from watch kit extension?
As of Beta 3 of iOS 8.2 it is currently not possible to open iOS app to foreground.
As you said openParentApplication can open app in background. Unfortunately there is no sign of API to open app on iPhone.
Multiple posts on Apple Dev Forums mentioned that it's not possible
https://devforums.apple.com/message/1076125#1076125
Correct, a notification can still declare a background action that the iPhone app will handle, so in that sense it can launch the iPhone app. But the iPhone app cannot be brought to the foreground by a WatchKit app.
And other post
https://devforums.apple.com/message/1082620#1082620
On a device, it[Watch app] will not - bring your iOS app to the foreground.
I'm hopeful that Apple will provide API for launching the parent app from a watch app in a future beta, but for now I've managed to achieve it by doing the following...
Call openParentApplication:reply: as normal:
- (void)openPhoneApp {
[WKInterfaceController openParentApplication:[NSDictionary new] reply:nil];
}
Implement application:handleWatchKitExtensionRequest:reply: in your AppDelegate, and launch itself using a custom URL scheme:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"myappscheme://open"]];
}
If you need to open your parent app in the foreground, use Handoff!
https://developer.apple.com/handoff/
Example:
Somewhere shared for both:
static let sharedUserActivityType = "com.yourcompany.yourapp.youraction"
static let sharedIdentifierKey = "identifier"
on your Watch:
updateUserActivity(sharedUserActivityType, userInfo: [sharedIdentifierKey : 123456], webpageURL: nil)
on your iPhone in App Delegate:
func application(application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
if (userActivityType == sharedUserActivityType) {
return true
}
return false
}
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]!) -> Void) -> Bool {
if (userActivity.activityType == sharedUserActivityType) {
if let userInfo = userActivity.userInfo as? [String : AnyObject] {
if let identifier = userInfo[sharedIdentifierKey] as? Int {
//Do something
let alert = UIAlertView(title: "Handoff", message: "Handoff has been triggered for identifier \(identifier)" , delegate: nil, cancelButtonTitle: "Thanks for the info!")
alert.show()
return true
}
}
}
return false
}
And finally (this step is important!!!): In your Info.plist(s)
Problem:
Using the FB SDK and the method openActiveSessionWithReadPermissions, the completion handler doesn't appear to get called when the app is reopened from Facebook web or Facebook app and I get this error output:
FBSDKLog: FBSession INVALID transition from FBSessionStateCreated to FBSessionStateClosed
FBSDKLog: FBSession transition from FBSessionStateCreated to FBSessionStateCreatedOpening
Context
Using Facebook SDK 3.2.1
App is built for iOS 5.0+
Using xCode 4.6.1
Testing on Simulator iOS 5.1
Testing on iPhone 4S, running iOS 6.1.2 (not using 6.0 social framework as want to test implementation for 5.0+)
Updating an app that was originally built for iOS 3.0 and using an old version of sharekit, but has now been updated for ARC and the share kit implementation I believe has all been commented out - hoping the issue is not a conflict with a old share kit function, can't fin any within the code
Steps taken to resolve
Searched throughout Stack Overflow, found similar issues mentioned but not a solution
ios6 facebook integration login always FBSessionStateClosedLoginFailed never opens (i already have bool:application implemented)
Facebook iOS SDK 3.0 - session not open
Facebook SDK 3.1 - Error validating access token
Have the correct app bundle in the FB settings panel
Have the correct Facebook app ID is the plist
Have FB logging turned on FBSettings setLoggingBehavior
Specifics:
These are the steps I took to implement Facebook connectivity within the app.
The first step I took was walking through the Facebook tutorial at: https://developers.facebook.com/docs/tutorials/ios-sdk-tutorial/. I got the first part, the authentication part working as expected (I built a separate app as instructed by the tutorial.)
I then took the same steps within the tutorial in the app I'm updating, this did not work
I then followed the instructions on https://developers.facebook.com/docs/howtos/login-with-facebook-using-ios-sdk/ (which are very similar to the tutorial)
Again I ran into issues
Then spent a lot of time searching for solution, could not find one
Highlevel steps in code:
I have my FB methods set up in AppDelegate
In a specific view controller I have a button that calls the openSessionWithAllowLoginUI method to start the login process
Code
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// set up facebook logging
[FBSettings setLoggingBehavior:[NSSet setWithObjects:FBLoggingBehaviorFBRequests, FBLoggingBehaviorFBURLConnections, FBLoggingBehaviorAccessTokens, FBLoggingBehaviorSessionStateTransitions, nil]];
// Call the ACAccountStore method renewCredentialsForAccount, which will update the OS's understanding of the token state
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) &&
(accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 &&
(account = [fbAccounts objectAtIndex:0])){
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// We need to properly handle activation of the application with regards to Facebook Login
// (e.g., returning from iOS 6.0 Login Dialog or from fast app switching).
NSLog(#"Calling app did become active");
[FBSession.activeSession handleDidBecomeActive];
}
/*
* Callback for session changes.
*/
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
NSLog(#"Session State Changed");
switch (state) {
case FBSessionStateOpen:
if (!error) {
// We have a valid session
NSLog(#"User session found");
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
if (error) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
/*
* Opens a Facebook session and optionally shows the login UX.
*/
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSLog(#"Openning session with Facebook");
return [FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
/*
* If we have a valid session at the time of openURL call, we handle
* Facebook transitions by passing the url argument to handleOpenURL
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
NSLog(#"Calling open URL");
return [FBSession.activeSession handleOpenURL:url];
}
- (void) closeSession {
NSLog(#"Clossing Facebook Sessions");
[FBSession.activeSession closeAndClearTokenInformation];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
NSLog(#"handleOpenUrl Called");
return [FBSession.activeSession handleOpenURL:url];
}
View Controller with button
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Register for Facebook change notification
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(sessionStateChanged:)
name:FBSessionStateChangedNotification
object:nil];
}
- (IBAction)login:(id)sender {
ATIAppDelegate *myAppDelegate = (ATIAppDelegate *)[[UIApplication sharedApplication]delegate];
[myAppDelegate openSessionWithAllowLoginUI:YES];
}
What I think the issue could be?
It seems like it may be something with the tokens?
Or maybe the notification center?
Note that during testing I've been going and revoking access of the Facebook app to my account and then trying to login again to the app, I see these has caused issues with other users
Okay I figured it out - the issue was nothing to do with FB itself, the app (I'm working on updating someone else's code) had a setting in the .plist - 'Application does not run in background' set to true.
Meaning that once the app was relaunched from the Facebook app or Facebook mobile site it wasn't prepared to handle the next step.
If you don't want the app to run in the background, you can bind to the FBSDKApplicationDelegate in your AppDelegate like so:
import UIKit
import FBSDKLoginKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func applicationWillResignActive(_ application: UIApplication) {
FBSDKAppEvents.activateApp()
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
}
https://forums.developer.apple.com/thread/50332
http://ashishkakkad.com/tag/fbsdkapplicationdelegate/
i am integrating login through facebook in an ios app , in which during the app launch i show an alert to the user , and when the user clicks on the OK button on the alert view , then the FB login dialog is shown to the user .The problem is when i click on the home button and relaunch the app to show the alert, then after clicking on OK does not show the user the facebook login dialog. i have used the facebook ios sdk 3.0 and xcode 4.5 gm. *Interestingly when i kill the app from background every thing works fine.*below is the code in the app did finish launching for facebook
if (!self.session.isOpen)
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",#"publish_stream",#"email",
nil];
self.session = [[FBSession alloc] initWithPermissions:permissions];
if (self.session.state == FBSessionStateCreatedTokenLoaded)
{
// even though we had a cached token, we need to login to make the session usable
[self.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
}
}
this is the method i call when user clicks on the OK button on the alert view
-(IBAction) facebookLogin
{
if (self.session.isOpen)
{
[self.session closeAndClearTokenInformation];
}
else
{
if (self.session.state != FBSessionStateCreated) {
// Create a new, logged out session.
self.session = [[FBSession alloc] init];
}
[self.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
if (error) {
NSLog(#"dex is %#",error.description);
}
}];
}
}
Follow this doc on Facebook developer.
It explains how to handle login and logout functionalities. Implement as it says, works perfectly. And also you can use the latest 3.1 sdk.
It's an old question, but anyway.
I had same behaviour when I didn't updated my AppDelegate. In swift it should look like this:
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationWillResignActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Some code was here
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}