Integrate your Flutter iOS app

This article provides information on how to integrate your Flutter app with our platform.

After adding the Blueshift Flutter plugin to your project, run pod install inside the iOS directory. The pod installs the Blueshift plugin along with the Blueshift iOS SDK in your iOS Project.

If you have an Objective-C project, add use_frameworks! to your pod file and then run pod install. For more information, see the sample pod file.

Prerequisites

The following permissions must be enabled in your Xcode project to send push notifications to the user’s device.

After adding the Push Notifications capability and enabling Remote notifications background mode, it should look like this.

alt text

1. SDK integration

We support the following 3 types of SDK integration:
a. Automatic Integration - Blueshift integration when you have not integrated Firebase in your project.
b. Auto Integration with Firebase SDK - Blueshift integration when you have already integrated Firebase in your project.
c. Manual Integration - Manual integration for customized implementation.

a. Automatic Integration

You can integrate the Blueshift Flutter plugin for your iOS project using Automatic integration. After automatic integration, the Blueshift plugin takes care of handling the device token, push notification, and deep link callbacks.

To use automatic integration, complete the following steps:

Setup AppDelegate.h

  • Include the Plugin’s header BlueshiftPluginManager.h in the AppDelegate.h file of the app’s Xcode project.

The AppDelegate.h file should look like this:

#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import <blueshift_plugin/BlueshiftPluginManager.h>
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic, strong) UIWindow *window;
@end

Initialise the Plugin

For Swift project, open the AppDelegate.swift file, import the plugin blueshift_plugin and add the function as shown in the following code snippet.

For Objective-C project, open the AppDelegate.m file and add the following function in the AppDelegate class.

The helper function creates an object of BlueshiftConfig class to set up the API key and the other SDK configurations.

  • Initialise the Blueshift Flutter plugin by using BlueshiftPluginManager class method initialisePluginWithConfig: autoIntegrate:.
  • Pass the created config object and pass autoIntegrate as YES to opt-in for automatic integration.
func initialiseBlueshiftWithLaunchOptions(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        // Create config object
        let config = BlueShiftConfig()
        
        // Set Blueshift API key to SDK
        config.apiKey = "API_KEY"
        
        // Set launch options to track the push click from killed app state
        if let launchOptions = launchOptions {
            config.applicationLaunchOptions = launchOptions
        }
        
        // Delay push permission dialog by setting false, by default push permission dialog is displayed on app launch.
        config.enablePushNotification = false
        
        // Set userNotificationDelegate to self to get the push notification callbacks.
        if #available(iOS 10.0, *) {
            config.userNotificationDelegate = self
        }
         
        // Initialise the Plugin and SDK using the Automatic integration.
        BlueshiftPluginManager.sharedInstance()?.initialisePlugin(with: config, autoIntegrate:true)
    }
- (void)initialiseBlueshiftWithLaunchOptions:(NSDictionary*)launchOptions {
  // Create config object
  BlueShiftConfig *config = [[BlueShiftConfig alloc] init];
  
  // Set Blueshift API key to SDK
  config.apiKey = @"API KEY";
 
  // Set launch options to track the push click from killed app state
  config.applicationLaunchOptions = launchOptions;
    
  // Delay push permission dialog by setting NO, by default push permission dialog is displayed on app launch.
  config.enablePushNotification = YES;
  
  // Set userNotificationDelegate to self to get the push notification callbacks.
  config.userNotificationDelegate = self;
  
  // Initialise the Plugin and SDK using the Automatic integration.
  [[BlueshiftPluginManager sharedInstance] initialisePluginWithConfig:config autoIntegrate:YES];
}
  • Now call the function that you added in the application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method of the AppDelegate class.

The AppDelegate class should look like this:

import UIKit
import Flutter
import blueshift_plugin

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        // Initialise the Blueshift Plugin & SDK by calling the `initialiseBlueshiftWithLaunchOptions` method before the return statement.
        self.initialiseBlueshiftWithLaunchOptions(launchOptions: launchOptions)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

func initialiseBlueshiftWithLaunchOptions(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        let config = BlueShiftConfig()
        config.apiKey = "API_KEY"
        if let launchOptions = launchOptions {
            config.applicationLaunchOptions = launchOptions
        }
        if #available(iOS 10.0, *) {
            config.userNotificationDelegate = self
        }
        BlueshiftPluginManager.sharedInstance()?.initialisePlugin(with: config, autoIntegrate:true)
    }
}
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [GeneratedPluginRegistrant registerWithRegistry:self];
    
    // Initialise the Blueshift Plugin & SDK by calling the `initialiseBlueshiftWithLaunchOptions` method before the return statement.
    [self initialiseBlueshiftWithLaunchOptions:launchOptions];
    
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)initialiseBlueshiftWithLaunchOptions:(NSDictionary*)launchOptions {
    BlueShiftConfig *config = [[BlueShiftConfig alloc] init];
    config.apiKey = @"API_KEY";
    config.userNotificationDelegate = self;
    config.applicationLaunchOptions = launchOptions;

    [BlueshiftPluginManager.sharedInstance initialisePluginWithConfig:config autoIntegrate:YES];
}

@end

SDK Config values

The following optional SDK config values can be used to configure the SDK. For more information, see SDK Config Values.

// Optional: From v2.2.3, Set Blueshift Region US or EU, default region will be US if not set.
    config.region = .EU
  
    // Optional: Set AppGroupId only if you are using the Carousel push notifications.
    config.appGroupID = "Your App Group ID here" 

    // Optional: From v2.2.0, Set custom authorization options
    config.customAuthorizationOptions = [.alert, .badge, .sound, .providesAppNotificationSettings]

    // Optional: From v2.2.0, Set custom categories
    config.customCategories = getCustomeCategories()

    // Optional: Set Batch upload interval in seconds.
    // If you do not add below line, SDK by default sets it to 
    // 300 seconds.
    BlueShiftBatchUploadConfig.sharedInstance().batchUploadTimer = 60
  
    // Optional: SDK uses IDFV by default if you do not 
    // include the following line of code.For more information,
    // see: https://developer.blueshift.com/docs/include-configure-initialize-the-ios-sdk-in-the-app#specify-the-device-id-source
    config.blueshiftDeviceIdSource = .idfvBundleID
    
    // Optional: Set debug true to see Blueshift SDK info and api logs, by default its set as false.
     #ifdef DEBUG
       config.debug = true
     #endif

    // Optional: Change the SDK core data files location only if needed. The default location is the Document directory.
    config.sdkCoreDataFilesLocation = .libraryDirectory
// Optional:  Set Blueshift Region US or EU, default region will be the US if not set.
  [config setRegion:BlueshiftRegionEU];

  // Optional: Set AppGroupId only if you are using the Carousel push notifications.
  [config setAppGroupID:@"Your App Group ID here"];

  // Optional: Set custom authorization options
  [config setCustomAuthorizationOptions: UNAuthorizationOptionAlert| UNAuthorizationOptionSound| UNAuthorizationOptionBadge| UNAuthorizationStatusProvisional];

  // Optional: Set App's push notification custom categories, SDK will register them
  [config setCustomCategories: [self getCustomeCategories]];
  
  // Optional: Set Batch upload interval in seconds.
  // If you do not add the below line, SDK by default sets it to 300 seconds.
  [[BlueShiftBatchUploadConfig sharedInstance] setBatchUploadTimer:60.0];

  // Optional: Set device Id type, SDK uses IDFV by default if you do not
  // Add the below line of code. For more information, see:
  //https://developer.blueshift.com/docs/include-configure-initialize-the-ios-sdk-in-the-app#specify-the-device-id-source
  [config setBlueshiftDeviceIdSource: BlueshiftDeviceIdSourceIDFVBundleID];

  // Optional: Change the SDK core data files location only if needed. The default location is the Document directory.
  [config setSdkCoreDataFilesLocation:BlueshiftFilesLocationLibraryDirectory];

  //Optional: Set debug true to see Blueshift SDK info and API logs, by default it's set as false.
  #ifdef DEBUG
        [config setDebug:YES];
  #endif

The SDK setup with automatic integration is complete. Using this setup you will be able to send events to Blueshift, send basic push notifications (title+content) to the iOS device. You will also get the push notification deep links in your Flutter app using the Deep links Event Listener.

For more information, see enable Rich push notifications, enable in-app notifications, and enable Blueshift email deep links.

b. Auto Integration with Firebase SDK

As Blueshift and Firebase both are responsible for handling the push notifications and both provide the automatic integration feature, you can not use Blueshift Auto integration when you have integrated Firebase SDK with auto integration (method swizzling). To use Blueshift SDK in your project,

  1. Complete the steps from Automatic Integration to integrate the Blueshift SDK.
  2. Then disable the Firebase auto integration and integrate manually by completing the following steps.
  • To disable Firebase Method Swizzling, add FirebaseAppDelegateProxyEnabled key with type Boolean and value NO in info.plist from your app's target.

  • As the Firebase method swizzling is disabled, you must explicitly set the APNS token to Firebase. To do that, add the following method in your AppDelegate class.
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Set device token to Firebase when the method swizzling is disabled.
        Messaging.messaging().apnsToken = deviceToken
        super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    // Set device token to Firebase when the method swizzling is disabled.
    [[FIRMessaging messaging] setAPNSToken:deviceToken];
    [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

The Blueshift Auto integration setup along with Firebase is complete. Using this setup you will be able to send events to Blueshift, send basic push notifications (title+content) to the iOS device. You will also get the push notification deep links in your Flutter app using the Deep links Event Listener.

For more information, see enable Rich push notifications, enable in-app notifications, and enable Blueshift email deep links.

c. Manual Integration

If auto integration is not an option, you can integrate the Blueshift plugin manually.

  1. Complete the steps from Automatic Integration to create the Blueshift Config and then initialize the Plugin by passing autoIntegrate as false.
// Create Blueshift config and then initialize the Plugin with `autoIntegrate` as `false`.
BlueshiftPluginManager.sharedInstance()?.initialisePlugin(with: config, autoIntegrate:false)
// Create Blueshift config and then initialize the Plugin with `autoIntegrate` as `NO`.
  [[BlueshiftPluginManager sharedInstance] initialisePluginWithConfig:config autoIntegrate:NO];

To integrate the Blueshift SDK manually to handle push notifications and deep link callbacks, complete the following steps:

Configure AppDelegate for push notifications

Add the following to the AppDelegate class of your app’s Xcode project to support the push notifications. See Configure App delegate for push notifications for more information.

// Override remote notification methods
    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        BlueShift.sharedInstance()?.appDelegate?.register(forRemoteNotification: deviceToken)
        super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }
    
    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        BlueShift.sharedInstance()?.appDelegate?.failedToRegisterForRemoteNotificationWithError(error)
        super.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
    }
    
    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // If Blueshift push, let Blueshift SDK handle it.
        if BlueShift.sharedInstance()?.isBlueshiftPushNotification(userInfo) == true {
            BlueShift.sharedInstance()?.appDelegate?.handleRemoteNotification(userInfo, for: application, fetchCompletionHandler: completionHandler)
        } else {
            //Let the Flutter handle the Notifications other than Blueshift
            super.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
        }
    }
    
    // Override UserNotificationCenter methods
    override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
           // If Blueshift push, let Blueshift SDK handle it.
           if BlueShift.sharedInstance()?.isBlueshiftPushNotification(response.notification.request.content.userInfo) == true {
           //v1.1.1 - Send Blueshift Push notification payload to flutter
           [[BlueshiftPluginManager sharedInstance] sendPushNotificationPayloadToFlutter:response.notification.request.content.userInfo];

           // Call Blueshift method to handle the push notification click
           BlueShift.sharedInstance()?.userNotificationDelegate?.handleUserNotification(center, didReceive: response, withCompletionHandler: completionHandler)
        } else {
            //Let the Flutter handle the Notifications other than Blueshift
            super.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
        }
    }
    
    override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // If Blueshift push, let Blueshift SDK handle it.
        if BlueShift.sharedInstance()?.isBlueshiftPushNotification(notification.request.content.userInfo) == true {
            BlueShift.sharedInstance()?.userNotificationDelegate?.handle(center, willPresent: notification, withCompletionHandler: completionHandler)
        } else {
            //Let the Flutter handle the Notifications other than Blueshift
            super.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
        }
    }
#pragma mark - remote notification delegate methods
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [[BlueShift sharedInstance].appDelegate registerForRemoteNotification:deviceToken];
    [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
    [[BlueShift sharedInstance].appDelegate failedToRegisterForRemoteNotificationWithError:error];
    [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler {
    // If Blueshift push, let Blueshift SDK handle it.
    if([[BlueShift sharedInstance]isBlueshiftPushNotification:userInfo] == YES) {
        [[BlueShift sharedInstance].appDelegate handleRemoteNotification:userInfo forApplication:application fetchCompletionHandler:handler];
    } else {
        //Let the Flutter handle the Notifications other than Blueshift
        [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:handler];
    }
}

#pragma mark - UserNotificationCenter delegate methods
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
    NSDictionary* userInfo = notification.request.content.userInfo;
    // If Blueshift push, let Blueshift SDK handle it.
    if([[BlueShift sharedInstance]isBlueshiftPushNotification:userInfo]) {
        [[BlueShift sharedInstance].userNotificationDelegate handleUserNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler];
    } else {
        //Let the Flutter handle the Notifications other than Blueshift
        [super userNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler];
    }
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    NSDictionary* userInfo = response.notification.request.content.userInfo;
    // If Blueshift push, let Blueshift SDK handle it.
    if([[BlueShift sharedInstance]isBlueshiftPushNotification:userInfo]) {
        [[BlueShift sharedInstance].userNotificationDelegate handleUserNotification:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
    } else {
        //Let the Flutter handle the Notifications other than Blueshift
        [super userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
    }
}

Handle the push and in-app deep links manually

The Blueshift iOS SDK supports deep links on push notifications and in-app messages. If a deep-link URL is present in the push or in-app message payload, the Blueshift SDK triggers AppDelegate class application:openURL:options: method on notification click/tap action and delivers the deep link there. If the URL is from Blueshift, then let the plugin manager send it to Flutter using the Deep links Event Listener. Add the following code to the AppDelegate class to handle it manually.

/// Override the open url method for handling deep links
    override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // Check if the received link is from Blueshift, then pass it to Blueshift plugin to handle it.
        if BlueshiftPluginManager.sharedInstance()?.isBlueshiftOpenURLLink(url, options: options) == true {
            BlueshiftPluginManager.sharedInstance()?.sendDeepLink(toFlutter: url);
        } else {
            // If the url is not from Blueshift, let Flutter handle it.
            return super.application(app, open: url, options: options)
        }
        return true;
    }
/// Override the open url method for handling deep links
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { 
    // Check if the received link is from Blueshift, then pass it to Blueshift plugin to handle it.
    if ([[BlueshiftPluginManager sharedInstance] isBlueshiftOpenURLLink:url options:options] == YES) {
        [[BlueshiftPluginManager sharedInstance] sendDeepLinkToFlutter:url];
    } else {
        // If the url is not from Blueshift, let Flutter handle it.
        [super application:application openURL:url options:options];
    }
    return YES;
}

2. Enable Rich push notifications

Blueshift supports Image, Carousel, and Custom action button push notifications.

3. Enable In-App Messages

By default, In-app messages are disabled in the SDK. You must enable it explicitly from the Blueshift config.

Enable In-App messages from Blueshift Config

During the SDK initialisation in AppDelegate.swift or AppDelegate.m file, we have set the values to the config. To enable in-app messages from Blueshift iOS SDK, you must set enableInAppNotification property of config to true.

config.enableInAppNotification = true
[config setEnableInAppNotification:YES];

Configure time intervals between two in-apps

By default, the time interval between two in-app messages (the interval when a message is dismissed and the next message appears) is one minute. You can use the following method to change this interval during the SDK initialization in the AppDelegate class:

// Set time interval in seconds
config.blueshiftInAppNotificationTimeInterval = 30
// Set time interval in seconds
[config setBlueshiftInAppNotificationTimeInterval:30];

Enable Background Modes

We highly recommend enabling Background fetch and Remote notifications background modes from the Signing & Capabilities. This enables the app to fetch the in-app messages if the app is in the background state.

alt_text

Register screens for in-app messages

Once you enable In-app messages, you should register all the screens for receiving the in-app messages. If you skip this step, in-app messages will not be displayed in the app as the screens are not registered.
You must add registerForInAppMessage line in the AppDelegate class immediately after the SDK initialisation line irrespective of automatic or manual integration. See the following code snippet for reference.

BlueshiftPluginManager.sharedInstance()?.initialisePlugin(with: config, autoIntegrate: true)
BlueShift.sharedInstance()?.registerFor(inAppMessage: "Flutter")
[[BlueshiftPluginManager sharedInstance] initialisePluginWithConfig:config autoIntegrate:YES];
[[BlueShift sharedInstance] registerForInAppMessage:@"Flutter"];

The in-app setup completes here. The deep links of the in-app notifications will be delivered to the Flutter using the Deep links Event Listener.

4. Enable Mobile Inbox

As Mobile inbox stores the in-app notifications for later use, you need to enable and set up the in-app notifications first. Once that is done, you can enable the mobile inbox from the SDK config at the time of SDK initialization.

config.enableMobileInbox = true
config.enableMobileInbox = YES;

Now, the Inbox is enabled from the SDK, you can use the Blueshift plugin inbox widget to show the inbox in your app as shown here.

5. Enable Blueshift email deep links

Blueshift’s deep links are usually https URLs that take users to a page in the app or launch them in a browser. If an email or text message that we send as a part of your campaign contains a Blueshift deep link and a user clicks on it, iOS will launch the installed app and Blueshift SDK will deliver the deep link to the app so that app can navigate the user to the respective screen.

To use Blueshift's email deep links, complete the following steps:

Implement protocol BlueshiftUniversalLinksDelegate on the AppDelegate class to get the deep links callbacks from the SDK. Your AppDelegate.swift for the Swift project or AppDelegate.h file for the Objective-C project should look like this:

import blueshift_flutter_plugin

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, BlueshiftUniversalLinksDelegate {
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        // Initialise the Blueshift Plugin & SDK by calling the `initialiseBlueshiftWithLaunchOptions` method before the return statement.
        self.initialiseBlueshiftWithLaunchOptions(launchOptions: launchOptions)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
#import <blueshift_flutter_plugin/BlueshiftPluginManager.h>
@interface AppDelegate : FlutterAppDelegate
<BlueshiftUniversalLinksDelegate>
@end

Now set the blueshiftUniversalLinksDelegate config variable to self to enable the Blueshift deep links during the Blueshift Plugin initialisation in AppDelegate file.

// If you want to use the Blueshift universal links, then set the delegate as below.
config.blueshiftUniversalLinksDelegate = self;
// If you want to use the Blueshift universal links, then set the delegate as below.
[config setBlueshiftUniversalLinksDelegate:self];

Note:

  • If you have integrated the plugin using the automatic integration, your setup is completed here. You will receive the deep link on the Flutter using the Deep links Event Listener.
  • If you have opted for Manual integration, you must complete the following steps to integrate the Blueshift Plugin.

Configure continueUserActivity method

Pass the URL/activity from the continueUserActivity method to the Plugin, so that the Plugin can process the URL and track clicks. After processing the URL, the SDK sends the original URL in the BlueshiftUniversalLinksDelegate method. Add the following code to the AppDelegate class to handle it manually.

// Override the `application:continueUserActivity:` method for handling the universal links
    override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        if let url = userActivity.webpageURL {
            // Check if the received URL is Blueshift universal link URL, then pass it to Blueshift plugin to handle it.
            if BlueshiftPluginManager.sharedInstance()?.isBlueshiftUniversalLinkURL(url) == true {
                BlueShift.sharedInstance()?.appDelegate?.handleBlueshiftUniversalLinks(for: userActivity)
            } else {
                // If the activity url is not from Blueshift, let Flutter handle it
                return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
            }
        }
        return true
    }
// Override the `application:continueUserActivity:` method for handling the universal links
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
    // Check if the received URL is Blueshift universal link URL, then pass it to Blueshift plugin to handle it.
    if ([[BlueshiftPluginManager sharedInstance] isBlueshiftUniversalLinkURL:userActivity.webpageURL] == YES) {
        [[BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForActivity:userActivity];
    } else {
        // If the activity url is not from Blueshift, let Flutter handle it
        [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
    }
    return YES;
}

Implement BlueshiftUniversalLinksDelegate

Now, implement the BlueshiftUniversalLinksDelegate delegate methods in the AppDelegate class to get success and failure callbacks. BlueshiftPluginManager will take care of delivering this deep link under event url to Flutter. Add the following code to the AppDelegate class.

// Deep link processing success callback
    func didCompleteLinkProcessing(_ url: URL?) {
        if let url = url {
            BlueshiftPluginManager.sharedInstance()?.sendDeepLink(toFlutter: url)
        }
    }
    
    // Deep link processing failure callback
    func didFailLinkProcessingWithError(_ error: Error?, url: URL?) {
        if let url = url {
            BlueshiftPluginManager.sharedInstance()?.sendDeepLink(toFlutter: url)
        }
    }
// Deep link processing success callback
- (void)didCompleteLinkProcessing:(NSURL *)url {
    if (url) {
        [[BlueshiftPluginManager sharedInstance] sendDeepLinkToFlutter:url];
    }
}

// Deep link processing failure callback
- (void)didFailLinkProcessingWithError:(NSError *)error url:(NSURL *)url {
    if (url) {
        [[BlueshiftPluginManager sharedInstance] sendDeepLinkToFlutter:url];
    }
}

See the Troubleshooting section for any integration issues.