Firebase iOS / Swift and Deep Links - ios

We have just integrated firebase, and all of a sudden our deep links are no longer working. We're using AppAuth for authentication, so we're reliant on deep links to direct us to the right place. I'm getting the following error:
<Debug> [Firebase/Analytics][I-ACS023001] Deep Link does not contain valid required params. URL params: {...}
Initialization of firebase as follows:
let bundleId = Bundle.main.bundleIdentifier
let filePath = Bundle.main.path(forResource: "GoogleService-Info-" + bundleId!, ofType: "plist")!
let options = FIROptions(contentsOfFile: filePath)
FIRApp.configure(with: options!)
And here's the deep linking functions:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
return application(app, open: url, sourceApplication: nil, annotation: [:])
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if url.host == AppHost.deeplink {
...
}
If i remove the call to FIRApp.configure, everything in the app works fine. My AppAuth redirects flow into the function above without any issue. However, with the call to configure(), it never gets into either one of the functions. As a result, i can't do a token exchange and complete authentication.
I suspected the AppDelegate proxy might be the issue, so i tried disabling it in the plist file. I've validated that the plist file passed to FIRApp.configure has the appropriate keys:
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
But no matter what i do, it's still activating the proxy:
[Firebase/Analytics][I-ACS003007] Successfully created Firebase Analytics App Delegate Proxy automatically. To disable the proxy, set the flag FirebaseAppDelegateProxyEnabled to NO in the Info.plist
I'm using only FirebaseCrash and FirebaseCore (and FirebaseAnalytics indirectly through crash)

Instead of adding the FirebaseAppDelegateProxyEnabled key to the GoogleServices-Info.plist, add it to your App's info.plist. The Google Services plist should not be modified once it's generated.
As for disabling the proxy, it's fine to do this long term. The proxy is a convenience thing (it's just swizzling some methods), and you can reimplement it manually. There's some examples here of how to handle the lack of the proxy (non-swizzling case).

Related

How to fetch the appID without using Branch SDK iOS?

I am working in iOS swift project. I have integrated branch for deep link activity. In the branch link we have appended the appID and retrieved the id when the user clicked the app link using below code in didFinishLaunch in AppDelegate.
let branch: Branch = Branch.getInstance()
branch.initSession(launchOptions: launchOptions, automaticallyDisplayDeepLinkController: true, deepLinkHandler: { params, error in
if error == nil {
// parse appID
}
})
But sometimes, we can’t fetch the ID due to branch error. So we planned to remove branch integration in our code. But plist contains URL Scheme, URL identifier etc.. for navigate to this app.
So, When the user clicks the app link, how to fetch the value with out using above code?
Additional note:
The below function is not triggered in my app while clicking the app link. Is any other way to trigger this function, so that I can check the url value in the below function to processing further.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
}

Universal linking with website by using swift

I using Universal-linking in my application, For that, I make the following apple-app-site-association file, like with the following code.
I place this file into server please find here:- http://dev.2ULaundry.com/apple-app-site-association
I add Domain URL into under associated domain into Capabilities of project file also.
But my Universal linking is not working anyone please help to me.
"applinks": {
"apps": [],
"details": [
{
"appID": "D929J2.com.apple.wwdc",
"paths": [ "/scheduled-pickups/","/new-schedule/", "dashboard-1", "/refer-a-friend/", "/price-list/", "/give-a-gift/", "/locations", "2u-rewards/", "payments/"]
}
]
}
}
And add the following code into appdelegate file also for hadling.
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: #escaping ([Any]?) -> Void) -> Bool
{
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let url = userActivity.webpageURL!
let userurl = url.absoluteString
if userurl.contains("/scheduled-pickups/")
{
let innerPage = UIStoryboard.loadPickupController()
innerPage.selectedfrom = SelectedFromVc.Deeplinking.rawValue
let nav = UINavigationController.init(rootViewController: innerPage)
nav.isNavigationBarHidden = true
self.window?.rootViewController = nav
}
}
You should check is your domain valid for using universal links. You could do it here: https://branch.io/resources/aasa-validator/.
I've checked your domain http://dev.2ulaundry.com there and there are some issues with your domain. Fix them and it should be fine.
Before the implementation, you have to verify your website domain with this AASA validator https://branch.io/resources/aasa-validator/. It has few warnings so please run the validator and fix the issue.
As per you shared, the domain starts with "http" but
Universal link only serves "https"
and also it would be good if you are placing the AASA file in the below path
https://dev.2ulaundry.com/.well-known/apple-app-site-association
Since I spent lot of times on Universal link & App links, my
recommendation is to use Firebase dynamic link for free or
Branch.io before wasting your time.Universal link will create lot of issues
like you can't check the app availability(app installed or not) and
you can't passing the parameter via Apple/Play store.

How to use deep-linking same as facebook in iOS?

I want to use deep-linking , for example consider my post url is http://myappsite/api/video/post_id , how can I implement deep-linking using this link. as facebook is doing with this url https://www.facebook.com/page_name/videos/post-id
You need to implement universal links on website and app.
You can also use Branch to help you integrating universal links / deep linking.
You need link you mobile app and website by universal links and than you need parse url inside you ios code and open correct screen
You have to implement Universal linking for acheaving this type of functionality. This would give you a good start .
https://medium.com/#abhimuralidharan/universal-links-in-ios-79c4ee038272
After that, when you click on the link, your application will open and following delegate function called in AppDelegate.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
print("Continue User Activity called: ")
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let url = userActivity.webpageURL!
print(url.absoluteString)
//handle url and open whatever page you want to open.
}
return true
}
The url.absolutelyString return the url string on which you tapped. Chop out your video_id and open the appropriate ViewController.

How to launch our app when we click a link in gmail

I am sending a link after signing up to the account from which user has signed up.
Now I want that when user click on that link from the corresponding account then he/she will move to app.
is there any way to launch our app from link clicked on gmail app?
Please help...
Thanks
You need to do perform Universal Linking.For universal linking you need to first create a “apple-app-site-association” file, which look like this :->
{
"applinks": {
"apps": [],
"details": {
"appID": "9JA89QQLNQ.com.apple.wwdc": {
"paths": [
"/wwdc/news/",
"/videos/wwdc/2015/*"
]
}
}
}
}
The applinks tag determines which apps are associated with the website. Leave the apps value as an empty array. Inside the details tag is an array of dictionaries for linking appIDs and URL paths.
The appID consists of your team ID combined with the app’s bundle ID.
After creating file you need to upload it on your domain like www.yourHost/apple-app-site-association.
now you need to go capabilities -> Associated Domains add here a link which you want to make universal i.e, which link you want to tappable to open your app.
Then you need to add this method in your app delegate class.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
//code here to related universal links
/* The activity type used when continuing from a web browsing session to either a web browser or a native app. Only activities of this type can be continued from a web browser to a native app.
*/
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
//do something
return true
}
Here is the use of URL scheme, you can add it to your application in the info plist file.
And use the below delegate to catch the response
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool
You just asked for the details so this tutorial will help you

iOS linkedin authentication

I started developing an app for iOS in Swift. Now I am at the part where I need to create a login system. However we need the LinkedIn information from people.
How can I use the OAuth2 API in iOS to achieve this?
I already created an app in the LinkedIn developers area, but now I am stuck. I got some advice from someone that I need to use the UIWebView but I have no clue how this works.
Integrating LinkedIn Login in a Swift application
First, download the LinkedIn iOS SDK. I'll be using the 1.07 stable version for this example. I'll be following the integration guide here.
Create a new Developer Application.
Add your iOS app's Bundle Identifier to your LinkedIn App under Mobile.
Add your LinkedIn app Id and URL Scheme to your app's Info.plist file.
Whitelist the specified LinkedIn URL schemes and ATS URLs.
Copy the linkedin-sdk.framework library to your application. Make sure "copy files if necessary" and "create groups for folder references" are selected.
Project setup complete, now let's write some code!
Create a new Header file called BridgingHeader.h. Under Targets -> YourApp -> Build Settings -> Swift Compiler - Code Generation, add MyApp/BridgingHeader.h to "Objective-C Bridging Header."
In your BridgingHeader.h, add these two lines:
#import <Foundation/Foundation.h>
#import <linkedin-sdk/LISDK.h>
In your AppDelegate.swift, add this code to handle the OAuth URL callback:
Swift 3:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if LISDKCallbackHandler.shouldHandle(url) {
return LISDKCallbackHandler.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
return true
}
Swift 2.x:
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
if LISDKCallbackHandler.shouldHandleUrl(url) {
return LISDKCallbackHandler.application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
return true
}
Now it's time to log in the user. In your view controller, say you have a "Login" button. Your IBAction might look like this:
#IBAction func doLogin(sender: AnyObject) {
LISDKSessionManager.createSessionWithAuth([LISDK_BASIC_PROFILE_PERMISSION], state: nil, showGoToAppStoreDialog: true, successBlock: { (returnState) -> Void in
print("success called!")
let session = LISDKSessionManager.sharedInstance().session
}) { (error) -> Void in
print("Error: \(error)")
}
}
When logging in, the user will be asked to authenticate with your application:
If the user allows, the success block will be called, and you can get information about the authenticated user. If the login fails or the user does not allow access, then the failure block will be called, and you can alert the user on the issue that occurred.
To get information about the user we authenticated with, call a GET request on the user's profile:
let url = "https://api.linkedin.com/v1/people/~"
if LISDKSessionManager.hasValidSession() {
LISDKAPIHelper.sharedInstance().getRequest(url, success: { (response) -> Void in
print(response)
}, error: { (error) -> Void in
print(error)
})
}
The response.data will contain information on the authenticated user:
"{\n \"firstName\": \"Josh\",\n \"headline\": \"Senior Mobile Engineer at A+E Networks\",\n ... }"
Read the docs further for more things you can do with the API.
A sample project (with my App ID obfuscated) can be found here.
LinkedIn is an interesting beast, since their mobile SDKs have two flaws:
An end user NEEDS the LinkedIn app to be installed, otherwise the "login" button will redirect the user to the App Store.
The mobile access token cannot be used on the server. See this screenshot from LinkedIn's iOS documentation
So while JAL's answer is sufficient, you may want to look into implementing LinkedIn's authorization_code OAuth flow in your mobile app instead of the LinkedIn SDK. This would look roughly like the following flow:
The app will redirect the user to your webserver.
The webserver begins the LinkedIn authentication flow, and redirects the user to LinkedIn.
The user logs into LinkedIn, and gets redirected back to your webserver.
The webserver reads the response, and exchanges the Authorization Code with LinkedIn for an access token.
The webserver redirects your user back to the app, using a custom url scheme to send it the LinkedIn access token.
The app uses the LinkedIn access token to login to Stormpath.
Sound complicated? It's actually more straightforward than it seems. I actually wrote some demo code for this flow using Express.js & Swift. This example ultimately sends the access token to Stormpath to ultimately authenticate the user, but you can always replace it with your own code that calls the LinkedIn REST API to grab the profile's information.
In Swift 3.0, UIApplicationOpenURLOptionsKey should be add for Facebook and LinkedIn.
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if LISDKCallbackHandler.shouldHandle(url)
{
return LISDKCallbackHandler.application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: nil)
}
else
{
return FBSDKApplicationDelegate.sharedInstance().application(app, open: url
, options: options)
}
}
I know this has already been answered but I faced this issue as well and had done everything set in the Accepted answer, but for whatever reason the code still was not hitting success or failure. It turned out that with iOS 9 the following is deprecated.
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
The solution was to use this instead :
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *,
id> *)options
For example, you could do:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
if ([LISDKCallbackHandler shouldHandleUrl:url]) {
return [LISDKCallbackHandler application:app openURL:url sourceApplication:options[UIApplicationLaunchOptionsSourceApplicationKey] annotation:options[UIApplicationLaunchOptionsAnnotationKey]];
}
return YES;
}
Update for Edward Jiang's answer; changes is token access on server + mobile side. Source: https://developer.linkedin.com/docs/ios-sdk-auth
As #Edward Jiang already explained, LinkedIn turns the whole authentication process very clumsy due to the requirement of having the LinkedIn app installed. I wrote a Swift library that handles the authentication flux within an embeded WKWebView: LinkedInAuth-Swift.
This library even eliminates the necessity of handling LinkedIn's response in a server. The WKWebView instance which is presenting the authentication flux is in charge of capturing the authorization code returned by LinkedIn and subsequently requesting the access token.

Resources