How to NOT handle some Universal Links programmatically? - ios

My iOS application handles universal links to redirect safari users to my app. So far everything is working great, if a user tap a link to my web site from Google my app is opening instead of my web site like this:
from safari https://my-web-site.com -> my-app
But my app doesn't implement certains features that my web site does, so I would like to programmatically reject some URLs and let my users on safari instead of redirecting him in my app, like this:
from safari https://my-web-site.com -> my-app
OR
from safari https://my-web-site.com?reject -> safari
That should by possible according to Apple documentation:
It’s important to understand that if your app uses openURL: to open a universal link to your website, the link does not open in your app. In this scenario, iOS recognizes that the call originates from your app and therefore should not be handled as a universal link by your app.
Unfortunately that's not what's appending, instead of staying in safari, my user is redirected to my app for a brief moment, then redirected again to safari like this:
from safari https://my-web-site.com?reject -> my-app (briefly) -> safari
here is my code for AppDelegate.swift:
internal func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard let url = userActivity.webpageURL else { return false }
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return false }
let params = urlComponents.queryItems ?? []
if params.contains(where: { $0.name == "reject" }) {
// This line should prevent the app from opening according to Apple's documentation
application.open(url)
return false
} else {
return true
}
}
So anyone have an idea how I could make the rejection of an Universal link the way it's described by Apple's documentation ?
note: the rejection of an universal link need to be done programmatically by the app, according to data stored locally. So adding a path exception in the apple-app-site-association file is not an option in my case :
{
"applinks": {
"apps": [],
"details": [
{
"appID": "XXXXXXXXX.com.my-app",
"paths": [
"*",
"NOT /reject"
]
}
]
}
}

If you prefix an entry in the paths array with "NOT" then you can explicitly prevent a match. So in your example you could do something like
["NOT /settings/*", "NOT /activity/*", "/*"]
which would prevent paths with /settings or /activity prefixes, and then match everything else.
Reference

Related

Universal link not performing action despite url being hit

I've successfully implemented universal links in to my app. The AASA is live on my website, and running the following command in my terminal successfully boots the app as expected:
xcrun simctl openurl booted https://websiteurl.com
Note - the url is different in practice.
For reference, this is my AASA structure:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "identifier.bundle_id",
"paths": ["*"]
}
]
}
}
However, my eventual aim with these universal links is to integrate it into an API which requires a redirect URI, where I send users back to the app.
As a result, I've created a ViewController, imaginatively called CallbackViewController. I will redirect users to this screen when the app is ready.
For now, I've introduced the following code into my AppDelegate file. The aim here is to print 'callback' when a universal link with the phrase 'callback' in is hit. However, when running the initial command in my terminal and adding /callback onto the end, nothing happens.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL, let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
if (components.path.contains("callback")) {
print("callback hit...")
}
return true
}
Does anyone know what I'm doing wrong in this function? I'm wondering if it's related to my AASA but unsure.
Thanks!

Access Universal Link app-argument in AppDelegate

I'm working on implementing Universal Links on our website, and I've run into a seemingly simple issue that I can't figure out. Searching Google and Stack Overflow hasn't helped, which leads me to believe I might just be missing something.
Basically, I'm adding the following to my page header (which has a URL of "https://www.website.com/slug").
<meta name="apple-itunes-app" content="app-id=xxx, app-argument=https://www.website.com/1" />
Note that the app-argument has a different URL than the actual page.
I've setup my apple-app-site-association file properly. When I try and handle the Universal Link in our iOS app, I do this:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard
userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else
{
return false
}
// Set breakpoint here.
return false
}
I set the breakpoint at the last return false, and when I inspect components, it contains the actual page URL ("https://www.website.com/slug") and not the URL passed in via app-argument ("https://www.website.com/id").
So my question is: How do I access the app-argument in my AppDelegate?

iOS App Delegate params dictionary doesn't contain any relevant links

I've added the Branch.io SDK to my iOS project. I have a custom URL scheme which works fine, I've added universal app links which work fine.
Now, I've enabled in my Dashboard the iOS app where I've added my custom URL scheme, custom URL for downloading the app, the App Prefix and the bundle identifier.
In the 'quick links' section I've created a quick link witch has a ["key": "value"] pair for the deep link section and added a redirect again to my jenkins where the ipa can be downloaded.
Now, if I access that link by copy/pasting in mobile safari, without the app installed i'm correctly taken to Jenkins.
At this point I run the app from xcode, and in app delegate I have
branch = Branch.getInstance()
branch.initSession(launchOptions: 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
// ... insert custom logic here ...
print("params: %#", params as? [String: AnyObject] ?? {})
} else {
print(error?.localizedDescription ?? "")
}
})
The issue is here that params always only contains two params:
params: %# ["+clicked_branch_link": 0, "+is_first_session": 0]
I've also implemented
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let branchHandled = branch.application(application,
open: url,
sourceApplication: sourceApplication,
annotation: annotation
)
if (!branchHandled) {
// If not handled by Branch, do other deep link routing for the Facebook SDK, Pinterest SDK, etc
var handled = false
handled = //this is Facebook handling
guard handled == false else { return true }
} else {
// do some stuff if it's coming from branch
}
return branchHandled
}
My interest is for branch to pass my ["key": "value"] pair in order to have it handled like a deep link at this point, but I don't know what else to try.
The failure of deferred deep-linking could be due to mismatch of Branch key and Branch link for a particular Branch app. Verify the Branch link used for deferred deep-linking is generated using the same Branch key which is used in info.plist of the iOS project.

Send button click event from iOS Today Widget without launching the host app

I am writing a Today Widget for an iOS app. The widget has a few action buttons. I want to receive the click event when someone clicks on it. However, it should not launch the app.
I've already tried this but to no avail.
My current implementation is to define a URL Scheme, and call openURL on those button presses like so:
Button 1 links to myApp://button1
Button 2 links to myApp://button2
Button 3 links to myApp://button3
I am receiving these events in the AppDelegate's
application(_:open:options:)
Here's the Code in TodayWodgetController
#IBAction func widgetClicked(sender: UIButton){
if sender == button1 {
let u = NSURL(string: "myApp://button1")
self.extensionContext?.open(u! as URL, completionHandler: nil)
}
...
}
and here is the code I'm using in the host app's AppDelegate
func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if url.absoluteString.range(of: "button1") != nil{
print ("Button 1 Pressed")
}
....
return true
}
However, like I said, it also launches the host App. I want it to just send me the click event without launching the App.
Any help would be appreciated.
I don't think there is a way to do that from an app extension.
Definition of open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil) as described by Apple:
Asks the system open a URL on behalf of the currently running app
extension.
Each extension point determines whether to support this method, or
under which conditions to support this method. In iOS 8, only the
Today extension point (used for creating widgets) supports this
method.
Important: Apple allows a widget to use the open(_:completionHandler:) method to open the widget’s own containing
app.

How to enable "Install" or "Open" Button in facebook messenger in a "yet-to-launch" ios App for Testing

I have an iOS app under development [Not yet launched]
And i want to get the following "Open" button visible on it while sharing the "from my app" via facebook messenger using FBSDKMessengerSharer:
Facebook SDK
What i have done is the following:
As per Facebook's guidelines for Optimized integration.
https://developers.facebook.com/docs/messenger/ios#optimized_integration
I have put .plist entries for facebook app ids, my own app id, URL schemes etc.
i confirm the when i type my scheme://, it open up my app.
Facebook developer console on developer.facebook.com has correct entries for the app/bundle.
I have added myself and another user as test users as per the guidelines and Facebook have clearly written this is testable without submitting the app.
And then i have the following pieces of code for sharing in the app:
func Share(){
let image : UIImage = UIImage(named: "Sample")!
let opts : FBSDKMessengerShareOptions = FBSDKMessengerShareOptions()
opts.contextOverride = cContext
FBSDKMessengerSharer.shareImage(image, withOptions: opts)
}
And the following for enabling optimized sharing in AppDelegate:
func application(app: UIApplication,
openURL url: NSURL,
options: [String : AnyObject]) -> Bool {
print("Called OpenURL")
let h = FBSDKMessengerURLHandler()
let a = "com.appcompany-new.name"
if h.canOpenURL(NSURL(string: "temp://abc.xyz"), sourceApplication: a) {
h.openURL(NSURL(string: "temp://abc.xyz"), sourceApplication: a)
}
return true
}
func messengerURLHandler(messengerURLHandler : FBSDKMessengerURLHandler,didHandleOpenFromComposerWithContext context : FBSDKMessengerURLHandlerOpenFromComposerContext) {
cContext = context
print("Called Open from composer")
}
I donot see any button, the Open, Install or Reply button even now. What am i missing?

Resources