Support deeplinking using universal links

Summary:
## See the following [Proposal](https://fburl.com/gdoc/z90ch5in)

## Problem

We want to add support for universal links.
In order to do that, developers who have app events integration (AEM) will be required to add a call to the `openURL:` on the SDK delegate class from `application(_:continue:restorationHandler:)` in the short term.

We would like to simplify things for app developers since extracting the webpage URL from NSUserActivity may cause confusion and errors for deep linking.

## Solution

The better way is to just introduce a method with a similar signature to `application(_:continue:restorationHandler:)` in the SDK delegate.
Developers could simply invoke that method in order to have the universal link processed.

By doing that, we will to make FB SDK more accessible to developers.

## Testing

See the test plan section

Reviewed By: samodom

Differential Revision: D34786435

fbshipit-source-id: 289fea5ecc9e106fe0c9fcc94bf2a65b0c07c0ab
This commit is contained in:
Daniel Huri
2022-03-14 13:40:41 -07:00
committed by Facebook GitHub Bot
parent 2d60224ea1
commit d57a25a755
5 changed files with 71 additions and 2 deletions

View File

@@ -12,6 +12,27 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
[Full Changelog](https://github.com/facebook/facebook-ios-sdk/compare/v13.0.0...HEAD)
### Notable Changes
#### Added an API to support deep linking using Universal Links
In order to ensure that your app properly supports [deep linking from app ads](https://developers.facebook.com/docs/app-ads/deep-linking) with Universal Links, you will need to implement `application(_:continue:restorationHandler:)` in your App Delegate, and call `ApplicationDelegate.shared.application(_:continue:)` from your implementation.
Your change might look like the following snippet:
```swift
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
ApplicationDelegate.shared.application(application, continue: userActivity)
// Rest of implementation...
return true
}
```
## 13.0.0
### Notable Changes

View File

@@ -189,6 +189,14 @@ static UIApplicationState _applicationState;
#pragma mark - UIApplicationDelegate
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
{
if (userActivity.activityType != NSUserActivityTypeBrowsingWeb) {
return NO;
}
return [self application:application openURL:userActivity.webpageURL options:@{}];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options

View File

@@ -36,6 +36,18 @@ NS_SWIFT_NAME(ApplicationDelegate)
@property (class, nonatomic, readonly, strong) FBSDKApplicationDelegate *sharedInstance
NS_SWIFT_NAME(shared);
/**
Call this method from the [UIApplicationDelegate application:continue:restorationHandler:] method
of the AppDelegate for your app. It should be invoked in order to properly process the web URL (universal link)
once the end user is redirected to your app.
@param application The application as passed to [UIApplicationDelegate application:continue:restorationHandler:].
@param userActivity The user activity as passed to [UIApplicationDelegate application:continue:restorationHandler:].
@return YES if the URL was intended for the Facebook SDK, NO if not.
*/
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity;
/**
Call this method from the [UIApplicationDelegate application:openURL:sourceApplication:annotation:] method
of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction
@@ -49,7 +61,7 @@ NS_SWIFT_NAME(shared);
@param annotation The annotation as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
@return YES if the url was intended for the Facebook SDK, NO if not.
@return YES if the URL was intended for the Facebook SDK, NO if not.
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
@@ -67,7 +79,7 @@ NS_SWIFT_NAME(shared);
@param options The options dictionary as passed to [UIApplicationDelegate application:openURL:options:].
@return YES if the url was intended for the Facebook SDK, NO if not.
@return YES if the URL was intended for the Facebook SDK, NO if not.
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url

View File

@@ -528,6 +528,33 @@ final class ApplicationDelegateTests: XCTestCase {
)
}
func testOpeningUniversalLinkChecksAEMFeatureAvailability() {
// See https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app
let userActivity = NSUserActivity(activityType: NSUserActivityTypeBrowsingWeb)
userActivity.webpageURL = SampleURLs.validUniversalLink
delegate.application(
UIApplication.shared,
continue: userActivity
)
XCTAssertTrue(
featureChecker.capturedFeaturesContains(.AEM),
"Opening a deep link should check if the AEM feature is enabled"
)
}
func testOpeningUniversalLinkNonBrowsingWebDoesNotCheckAEMAvailability() {
let userActivity = NSUserActivity(activityType: "Example")
userActivity.webpageURL = SampleURLs.validUniversalLink
delegate.application(
UIApplication.shared,
continue: userActivity
)
XCTAssertFalse(
featureChecker.capturedFeaturesContains(.AEM),
"Opening a deep link should check if the AEM feature is enabled"
)
}
// MARK: - Application Observers
func testDefaultsObservers() {

View File

@@ -12,6 +12,7 @@ public enum SampleURLs {
// swiftlint:disable force_unwrapping
public static let valid = URL(string: "https://www.example.com")!
public static let validApp = URL(string: "fb://test.com")!
public static let validUniversalLink = URL(string: "https://www.test.com")!
public static let validPNG = URL(string: "https://www.example.com/babyamnimal.png")!
// swiftlint:enable force_unwrapping