iOS handle dynamic link while app is inactive - ios

My ApplicationDelegate:
let customURLScheme = "dlscheme"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIROptions.default().deepLinkURLScheme = self.customURLScheme
FIRApp.configure()
return true
}
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 {
let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLink(fromCustomSchemeURL: url)
if let dynamicLink = dynamicLink {
let message = generateDynamicLinkMessage(dynamicLink)
if #available(iOS 8.0, *) {
showDeepLinkAlertView(withMessage: message)
}
return true
}
if #available(iOS 8.0, *) {
showDeepLinkAlertView(withMessage: "openURL:\n\(url)")
} else {
}
return false
}
#available(iOS 8.0, *)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
guard let dynamicLinks = FIRDynamicLinks.dynamicLinks() else {
return false
}
let handled = dynamicLinks.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
let message = self.generateDynamicLinkMessage(dynamiclink!)
self.showDeepLinkAlertView(withMessage: message)
}
return handled
}
func generateDynamicLinkMessage(_ dynamicLink: FIRDynamicLink) -> String {
let matchConfidence: String
if dynamicLink.matchConfidence == .weak {
matchConfidence = "Weak"
} else {
matchConfidence = "Strong"
}
let message = "App URL: \(dynamicLink.url)\nMatch Confidence: \(matchConfidence)\n"
return message
}
#available(iOS 8.0, *)
func showDeepLinkAlertView(withMessage message: String) {
let okAction = UIAlertAction.init(title: "OK", style: .default) { (action) -> Void in
print("OK")
}
let alertController = UIAlertController.init(title: "Deep-link Data", message: message, preferredStyle: .alert)
alertController.addAction(okAction)
self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
}
Here is my code. I am working with firebase dynamic link, and implemented it like this tutorial:
https://firebase.google.com/docs/dynamic-links/ios
And this sample:
https://github.com/firebase/quickstart-ios/blob/master/dynamiclinks/DynamicLinksExampleSwift/AppDelegate.swift
Its working well when my app is in background. Open the app and show alert with url when I tap on dynamic link.
But in the case my app is inactive (not running), it not working. Just open the app and do nothing.
And my question: How can i handle dynamic link while app is inactive?
Sorry about my english

Swift 5
You can handle it in such way:
AppDelegate.swift
import Firebase
import FirebaseDynamicLinks
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// ... your other code here
FirebaseApp.configure()
let activityKey = NSString(string: "UIApplicationLaunchOptionsUserActivityKey")
if let userActivityDict = launchOptions?[.userActivityDictionary] as? [NSObject : AnyObject], let userActivity = userActivityDict[activityKey] as? NSUserActivity, let webPageUrl = userActivity.webpageURL {
DynamicLinks.dynamicLinks().handleUniversalLink(webPageUrl) { (dynamiclink, error) in
// do some stuff with dynamiclink
}
}
return true
}

I have do like this...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
if let option = launchOptions
{
if option.keys.contains(UIApplicationLaunchOptionsKey.userActivityDictionary)
{
if let userActivityDict = option[UIApplicationLaunchOptionsKey.userActivityDictionary] as? [AnyHashable:Any]
{
if userActivityDict.keys.contains(UIApplicationLaunchOptionsKey.userActivityType)
{
if let userActivity = userActivityDict["UIApplicationLaunchOptionsUserActivityKey"] as? NSUserActivity {
if let webpageURL = userActivity.webpageURL
{
// Write your code here.
}
}
}
}
}
}
}

I had a problem when application(_:open:options:) wasn't called when the app was in background. The Firebase SDK swizzles methods and that was the reason.
I solved this problem by setting FirebaseAppDelegateProxyEnabled = NO in Info.plist
For more detailed information on how it works and what it affects you can read here https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in

Related

SWIFT :- Universal linking in swift is not working

I am using universal linking in my project.
I have made apple-app-site-association file in server.
I enable in developer account, Xcode for associate domains and I wrote
applinks:www.laundry.com
The code used in AppDelegate is:-
//Universal links in swift delegatemethod.
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: #escaping ([Any]?) -> Void) -> Bool
{
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let url = userActivity.webpageURL!
let userurl = url.absoluteString
// print(url.absoluteString)
//handle url
if defaultValues.value(forKey: accessToken) != nil
{
print("user url is:",userurl)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Pickup", bundle: nil)
let innerPage: PickupController = mainStoryboard.instantiateViewController(withIdentifier: "PickupController") as! PickupController
innerPage.selectedfrom = "Deeplink"
self.window?.rootViewController = innerPage
}else{
setRootControllerBeforeLogin()
}
}
return true
}
But it is not working, please help to me.
I once used dynamic links of firebase, and override another function in appDelegate like below.
func application(_ application:UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
print("I have received a URL through custom url scheme : \(url.absoluteString)")
// tot do with dynamic link....
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
return true
} else {
// handle others like twitter or facebook login
}
}
Do it on App delegate
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
if let url = userActivity.webpageURL {
let component = URLComponents.init(string: url.absoluteString)!
print(component.path)
}
return true
}

Deep Link does not contain valid required params while clicking a dynamic link

i have setup my dynamic link as a documentation but while clicking a link it shows :
Deep Link does not contain valid required params. URL params: {
"_cpb" = 1;
"_cpt" = cpit;
"_fpb" = "CJsFEPcCGgVlbi1VUw==";
"_iumchkactval" = 1;
"_iumenbl" = 1;
"_osl" = "https://ttnfleetsolutions.page.link/azrN2YkJQncowdQ78";
"_plt" = 3698;
"_uit" = 1651;
apn = "com.ttnfleetsolutions.ttnfleet.debug";
cid = 4103105643708739955;
ibi = "com.ttnfleetsolutions.ttnfleetCustomer";
link = "https://www.ttnfleetsolutions.com/";
}
App is open when dynamiclink clicked but it dose not call any function and show error how to get know link clicked or not?
my didfinishlunchingwithoption methode:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool{
IQKeyboardManager.shared.enable = true
FirebaseApp.configure() UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: UIControl.State.highlighted)
GMSServices.provideAPIKey(GOOGLE_API_KEY)
GMSPlacesClient.provideAPIKey(GOOGLE_API_KEY)
return true
}
and function from docs:
#available(iOS 9.0, *)
func application(_ app: UIApplication, open url: URL, options:
[UIApplication.OpenURLOptionsKey : Any]) -> Bool {
return application(app, open: url,
sourceApplication:
options[UIApplication.OpenURLOptionsKey.sourceApplication] as?
String,
annotation: "")
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
print("DynamicLink\(dynamicLink)")
return true
}
return false
}
and
extension AppDelegate {
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: #escaping ([Any]?) -> Void) ->
Bool {
guard
userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let webpageURL = userActivity.webpageURL else {
return false
}
return
DynamicLinks.dynamicLinks().handleUniversalLink(webpageURL) {
dynamiclink, error in
guard let url = dynamiclink!.url else { return }
print("url:", url)
}
}
}
If you are opening the app using the long version of the deep link you should make sure your link value is percent encoded, that way your &,?,= signs inside the inner link are encoded and properly processed by firebase.

appflayer deeplinking not working when application open from link (delegate method not called)

I have deeplinking with AppFlayer SDK and universal link open the application successfully means deeplinking working fine.
Now issue is that when application open from link then it will not redirect to it's page. But if I put application in background and take in foreground then deeplinking works
I follow this guide lines.(link)
AppFlayer setup code
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
AppsFlyerTracker.shared().appsFlyerDevKey = "xxxxxxxxxxxx"
AppsFlyerTracker.shared().appleAppID = "xxxxxxx"
AppsFlyerTracker.shared().isDebug = false
AppsFlyerTracker.shared().delegate = self
self.pushNotificationService(application)
objStoryBoard = UIStoryboard(name:"Main", bundle: nil)
return true
}
AppFlayer delegate
Edit :: This method not called when application is open from link of appsflayer marketing
//MARK:
//MARK: appflayer delegate
func onAppOpenAttribution(_ installData: [AnyHashable: Any]) {
NSLog("installData ::%#", installData )
if let link = installData["link"] as? String
{
if link.contains(read_Localizable("titleAppflayer"))
{
if let arrQueryItems = URLComponents(string: link)!.queryItems {
for obj in arrQueryItems {
if obj.name.caseInsensitiveCompare(read_Localizable("appflayerParameter")) == .orderedSame
{
self.redirectAppflayer(withstrUrl: obj.value!)
return
}
}
}
}
}
}
user activity method of application
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
// if let url = userActivity.webpageURL
// {
// NSLog("URL :: %#",[url])
// }
if userActivity.webpageURL?.absoluteString.contains(read_Localizable("titleAppflayer")) == true
{
AppsFlyerTracker.shared().continue(userActivity, restorationHandler: restorationHandler)
return true
}
return Branch.getInstance().continue(userActivity)
}
Let me know what i doing wrong.
You are calling the AppsFlyerTracker from willFinishLaunchingWithOptions when it should be called from didFinishLaunchingWithOptions. Could you move the relevant code and test again?
Add
[[AppsFlyerTracker sharedTracker] trackAppLaunch];
onConversionDataSuccess method will start getting call.

Branch.io - link opening the app but not getting data in it

Branch.io link not getting data if app opened installed already. When app installed link opens the app directly but data missing. But if i redirect to app store then click again on branch link and open the app directly then data comes. Please guide, posting the code below.
Update:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
let branch: Branch = Branch.getInstance()
branch.setDebug()
branch.initSessionWithLaunchOptions(launchOptions, andRegisterDeepLinkHandler: {params, error in
if error == nil {
// params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
// params will be empty if no data found
print("params: %#", params.description)
print(params["event_id"])
if let url = params["event_id"] as? NSInteger {
let strEventID = String(url)
print(strEventID)
})
self.window?.rootViewController = nav
self.window?.makeKeyAndVisible()
return true
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
Branch.getInstance().handleDeepLink(url)
if(sourceApplication == "com.linkedin.LinkedIn")
{
if(LISDKCallbackHandler.shouldHandleUrl(url))
{
return LISDKCallbackHandler.application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
}
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
// handler for Universal Links
Branch.getInstance().continueUserActivity(userActivity)
return true
}
// Called when a notification is received and the app is in the
// foreground (or if the app was in the background and the user clicks on the notification).
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
{
Branch.getInstance().handlePushNotification(userInfo)
if(UserSingleton.sharedInstance.accessToken != kEmptyString)
{
if let aps = userInfo["aps"] as? NSDictionary {
var title = kEmptyString
var message = kEmptyString
var inviteID = kEmptyString
var statusType = kEmptyString
if let inviteIDLocal = aps.valueForKey("id") as? NSNumber
{
inviteID = "\(inviteIDLocal)"
}
else if let inviteIDLocal = aps.valueForKey("id") as? String
{
inviteID = inviteIDLocal
}
else
{
inviteID = "0"
}
if let statusTypeLocal = aps.valueForKey("status_type") as? String
{
statusType = statusTypeLocal
}
if let titleLocal = aps.valueForKey("alert")?.valueForKey("title") as? String
{
title = titleLocal
}
if let messageLocal = aps.valueForKey("alert")?.valueForKey("body") as? String
{
message = messageLocal
}
CommonFunctions.addNotificationBar(title,message: message, inviteID: inviteID,statusType: statusType)
}
}
}
After spending an day, finally came to know the reason.
// Respond to Universal Links
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([**Any**]?) -> Void) -> Bool {
// pass the url to the handle deep link call
Branch.getInstance().continue(userActivity)
return true
}
"Any" should be actually "AnyObject".

Ambiguous Reference To Member 'Subscript' when using UIApplicationShortcutItem

I am trying to migrate my code to Swift 3, and came across an error regarding trying to handle 3D Touch shortcuts..
I get the following error
Performing segue using 3D Touch Shortcut - Ambiguous Reference To
Member 'Subscript'
For the following line
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: Any]?) -> Bool {
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
handleShortcutItem(shortcutItem)
}
}
I am not sure why I am getting this, does anyone else know ?
Here's how I am handling the shortcuts
enum ShortcutItemType: String {
case First
case Second
case Third
init?(shortcutItem: UIApplicationShortcutItem) {
guard let last = shortcutItem.type.components(separatedBy: ".").last else { return nil }
self.init(rawValue: last)
}
var type: String {
return Bundle.main.bundleIdentifier! + ".\(self.rawValue)"
}
}
fileprivate func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
if let rootViewController = window?.rootViewController, let shortcutItemType = ShortcutItemType(shortcutItem: shortcutItem) {
let rootNavController = rootViewController.childViewControllers.first as! UINavigationController
let viewController = rootNavController.childViewControllers[1]
switch shortcutItemType {
case .First:
viewController.performSegue(withIdentifier: "firstSegue", sender: self)
break
case .Second:
viewController.performSegue(withIdentifier: "secondSegue", sender: self)
break
case .Third:
//Segue to view controller from first then perform another segue to a modal view.
viewController.performSegue(withIdentifier: "thirdSegue", sender: self)
break
}
}
}
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
handleShortcutItem(shortcutItem)
}
The method header of application(_:didFinishLaunchingWithOptions:) has changed to:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil)
The symbol UIApplicationLaunchOptionsShortcutItemKey has been replaced with UIApplicationLaunchOptionsKey.shortcutItem.
And this may be another issue, but application(_:performActionFor:completionHandler:) needs to have this header:
func application(_ application: UIApplication,
performActionFor shortcutItem: UIApplicationShortcutItem,
completionHandler: #escaping (Bool) -> Void)
Try fixing all of them.

Resources