On iOS 14 using SwiftUI, I'm currently trying to test Dynamic Links in the situation where the user clicks the link and installs the app, then opens it up and receives information from that link. I followed the recommendations in this post (How can I test Firebase Dynamic Links if my app is not in the App Store?) and also implemented all the AppDelegate functions on the Firebase iOS website.
However, nothing gets called when I open the link, install the app, and then open the app for the first time (It just says "Pasted from Safari"). The only thing that works is clicking Dynamic links when the app is already installed (it opens up the app and calls the url listener functions correctly).
This is the code for generating the link:
let dynamicLink = URL(string: "http://www.mydomainishereIjustremovedit.com/?referrer=\(referrerID)")!
//guard let uid = Auth.auth().currentUser?.uid else { return }
if let referralLink = DynamicLinkComponents(link: dynamicLink, domainURIPrefix: "https://penciltestapp.page.link") {
referralLink.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.penciltestapp.penciltestapp")
//referralLink.iOSParameters?.minimumAppVersion = "1.0"
referralLink.iOSParameters?.appStoreID = "962194608" // Opens up a random app on the app store. Just click this to open the app store, and then install your app from XCode
referralLink.shorten { (shortURL, warnings, error) in
if let error = error {
print(error.localizedDescription)
return
}
self.inviteURL = shortURL
}
}
Dont' forget to implement also this, this was missing in my case
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: "")
}
Related
I run the shortcuts with the x-callback url given below code:
let url = URL(string: "shortcuts://x-callback-url/run-shortcut?name=Airplane&x-success=shortcutsdemo://")
UIApplication.shared.open(url!, options: [:], completionHandler: nil)
When I open the URL in UIApplication.shared.open, it runs the shortcut and after its done, return back to our iOS app.
My question is if my shortcut is not added in shortcuts app, how I manage?
Is there any way to first find our shortcut is added or not in shortcuts app and then we run the shortcut.
Like :
if (Shortcut.isInstalled) {
let url = URL(string: "shortcuts://x-callback-url/run-shortcut?name=Airplane&x-success=shortcutsdemo://")
UIApplication.shared.open(url!, options: [:], completionHandler: nil)
} else {
print("Not installed")
}
Summary :
If the shortcut is added in our shortcuts app, Then it's run the shortcuts using our iOS app. Otherwise its not run. and give an error for that shortcut.
I think you will need to use func canOpenURL(_ url: URL) -> Bool
let url = URL(string: "shortcuts://x-callback-url/run-shortcut?name=Airplane&x-success=shortcutsdemo://")
if UIApplication.shared.canOpenURL(ur!l) {
print("Short uts is installed")
} else {
print("Shortcuts not installed")
}
I am not 100% sure, but I think it redirects you automatically to appstore if you don't have it, check that out.
I use in my app url scheme and I don't know why sometime when I click on URL (e.g. https://api.domain.com/menu?id=7ee5232764-0a79-4afe) iOS opens my app (correct) and 1 second later opens App Store application (not correct). This is my openUrl's method:
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool {
let components = url.absoluteString.components(separatedBy: "/")
if components.contains("menus") {
let menuId = url.lastPathComponent
let menu = Menu(id: menuId)
SessionManager.shared.navigationManager.present(NavigationItem.menu(menu: menu).viewController, animated: true, completion: nil)
return true
} else {
return false
}
}
Resolved! Bug is on the web side where they have activated a JS timeout that they don't stop after app is opened.
I created a keyboard extension with a scan button to open a barcode scanner in my containing app. When the scan is completed, it should navigate back to the initial app and the barcode data should be set as text to the textfield that initiated the keyboard and we clicked on scan button.
There is this app Scandit Wedge that does it the same way. But I couldn't find a way to achieve the same.
Please refer GIF below.
https://s3.amazonaws.com/id123-dev-ios/scandit.gif
Any help would be much appreciated.
There is no public API to switch to the previous app, here is the answer: https://stackoverflow.com/a/13447282/1433612
But you could do that if you know the app's bundle id and url scheme. You can find unofficial lists on internet. Assuming that you are able to recognize the source app you can do something like this in your AppDelegate:
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
guard let applicationBundleId = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String else {
return true
}
// Save your source application
sourceApplicationBundleId = applicationBundleId
return true
}
var sourceApplicationBundleId: String?
// Attempt to open application from which your app was opened
func openApplication() {
guard let applicationBundleId = sourceApplicationBundleId, let url = url(for: applicationBundleId) else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
func url(for bundleId: String) -> URL? {
guard let scheme = knownUrlSchemes[bundleId] else {
return nil
}
return URL(string: scheme)!
}
// A list of known url schemes
var knownUrlSchemes: Dictionary<String, String> = {
return ["com.google.Maps": "comgooglemaps://",
"com.facebook.Facebook": "fb://"]
}()
I updated Firebase Dynamic Link pod to 1.4 version. In this version I found very useful class named FIRDynamicLinkComponents. I decided to use it to generate dynamic links. But I have 2 problems:
Firebase doc says that dynamic links can survive installation process and open app on the content I described in dynamic link after installation from AppStore. It is not work.
When user without installed app taps on dynamic links, he will see strange screen with button "Open in App". After click AppStore appears.
Can we skip this screen?
My implementation:
static func createDynamicLinks(forChallangeId challangeId: String, authorId: String, authorEmail: String, completion: #escaping (_ dynamicLink: String?, _ error: Error?) -> Void) {
let link = URL(string: "https://CODE.app.goo.gl/challange/\(challangeId)/author/\(authorId)")!
let domain = DOMAIN
let components = FIRDynamicLinkComponents(link: link, domain: domain)
//add iOS params
let iOSParams = FIRDynamicLinkIOSParameters(bundleID: bundleId)
iOSParams.appStoreID = APP_STORE_ID
components.iOSParameters = iOSParams
//add Android params
let androidParams = FIRDynamicLinkAndroidParameters(packageName: PACKAGE_NAME)
androidParams.minimumVersion = 19
components.androidParameters = androidParams
//add social meta tag params
let socialParams = FIRDynamicLinkSocialMetaTagParameters()
socialParams.title = "You got new challenge"
socialParams.descriptionText = "\(authorEmail) sent the challenge to you."
socialParams.imageURL = IMAGE_URL
components.socialMetaTagParameters = socialParams
//add options
let options = FIRDynamicLinkComponentsOptions()
options.pathLength = .short
components.options = options
//make link shorter
components.shorten { (shortURL, warnings, error) in
if let error = error {
completion(nil, error)
return
}
guard let shortLinkString = shortURL?.absoluteString else {
completion(nil, error)
return
}
completion(shortLinkString, error)
}
}
Edit
3rd problem.
Target iOS10. Handle:
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
if let url = dynamiclink?.url {
DynamicLinksManager.handleDeepLink(link: url)
}
}
return handled
}
handled is true but in closure dynamiclink and error are nil.
A lot of solutions depend on having more context than you've currently included. I'll edit this answer with updates as possible.
Dynamic Links definitely can survive the installation process in most situations. However, there are a lot of edge cases. Could you add specific reproduction steps for exactly the process you're using to test?
No, unfortunately this modal cannot be skipped. Apple made some changes in iOS 10.3 that make something like this unavoidable (read here for more on what happened, and how we handled the same problem in a slightly more elegant way at Branch)
This might be expected, if no valid Dynamic Link were triggered. Again, could you add specific reproduction steps?
I am developing a very basic iOS app with Swift. Just to read the heart rate data. I am using SFSafariViewController. As known, I first need to register my app on dev.fitbit.com. The registration form requires a callback URL to be entered.
After logging in successfully, FitBit always redirects me back to that entered callback URL. What should I do/code/configure to be able to redirect user back to my iOS app after logging in successfully?
What you need to do is to add the application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool function to your AppDelegate and then create an url scheme for your application as an identifier. To create an url scheme go to your application target > Info > URL Types (at the bottom). Then just add the following in your AppDelegate:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
DispatchQueue.main.async {
// Conctrol so that we´re coming from the right application
if (url.scheme == "The url scheme that you created"){
// Navigate to the viewController you want
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "WebView") as! WebViewController
self.window?.rootViewController!.present(controller, animated: true, completion: { () -> Void in
})
}
}
return true
}
Try using below 3 steps in your application.
You are using "fitbit", so I am considering your are using OAuth2.0 for login and get access-token.
Step 1 : Set up you URL Schemes.
Step 2 : In your AppDelegate class
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if (url.host == "oauth-swift") {
OAuthSwift.handle(url: url)
}
return true
}
In Above function what we did is, we check the URL comes to handleOpenUrl method, and check weather it is the right url call back is coming or not.
Step 3 : Set the proper call back URL in you OAuth Handler.
oauthswift = OAuth2Swift(
consumerKey: "********",
consumerSecret: "********",
authorizeUrl: "your authorisation url",
responseType: "token"
)
let handle = oauthswift.authorize(
withCallbackURL: URL(string: "oauth-swift://oauth-callback/fitbit")!,
scope: "your application scope", state:"state",
success: { credential, response, parameters in
print(credential.oauth_token)
},
failure: { error in
print(error.localizedDescription)
}
)
In above step, we set the call back url starting with "oauth-swift:", so it will be work as a host of your call back url.
Image and Code Courtesy : I have tried to explain a solution of your
problem in easy words. And all information of this answers are
originally documented and explained on this URL :
https://github.com/OAuthSwift/OAuthSwift