> ## Documentation Index
> Fetch the complete documentation index at: https://help.airbridge.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting - Cordova-Ionic SDK (Deprecated)

<AccordionGroup>
  <Accordion title="[Xcode 27] SceneDelegate Migration Required — Additional Setup Needed for Airbridge Deep Links">
    <Note>
      **Attention**

      This troubleshooting guide is for customers who need to migrate an existing AppDelegate-based app to the UIScene(SceneDelegate) lifecycle.
    </Note>

    ### Problem

    * When you run an app built with Xcode 27, the screen appears blank (white) or the app does not render properly.
    * Airbridge deep link events are not collected even when the app is opened through a scheme deep link or Universal Link.
    * The `setDeeplinkListener` callback is not called.
    * The app does not work even though the code was added to `AppDelegate` as shown in the [SDK Installation](/en/developers/deprecated-cordova-ionic-sdk-v2#sdk-installation) and [Deep Link Setup](/en/developers/deprecated-cordova-ionic-sdk-v2#deep-link-setup) developer guide examples.

    ### Cause

    Apple is moving the app lifecycle from the `UIApplicationDelegate`-only AppDelegate model to the `UIScene`-based SceneDelegate model, and adopting the Scene lifecycle has effectively become required in the latest Xcode and iOS environments.

    When an app adopts the Scene lifecycle through `UIApplicationSceneManifest`, the following `AppDelegate` callbacks are **no longer called.**

    | Existing `AppDelegate` callback | Replacement callback in the Scene lifecycle (`SceneDelegate`) |
    | - | - |
    | `window` creation in `application:didFinishLaunchingWithOptions:` | `scene:willConnectToSession:options:` |
    | Deep link at app cold start | `connectionOptions` of `scene:willConnectToSession:options:` |
    | `application:openURL:options:` | `scene:openURLContexts:` |
    | `application:continueUserActivity:restorationHandler:` | `scene:continueUserActivity:` |

    In cordova-ios 7.x and earlier, `CDVAppDelegate` creates the `window` and `MainViewController` in `application:didFinishLaunchingWithOptions:`.

    In the Scene lifecycle, `SceneDelegate` owns the `window`, so this `window` is not displayed and the screen appears blank.

    ### Solution

    The required work depends on your cordova-ios platform version.

    Check the version with `cordova platform ls`, then select the matching tab in each step below.

    <Note>
      **Attention**

      `CDVSceneDelegate` in cordova-ios 8.0.0 / 8.0.1 does not implement `scene:continueUserActivity:`.

      Applying the code below causes the app to terminate when it is opened through a Universal Link.

      **Update to cordova-ios 8.1.0 or later before applying this guide.**
    </Note>

    | | cordova-ios<br />8.1.0 or later | cordova-ios<br />7.x or earlier |
    | - | - | - |
    | Deep link when the app is terminated | Scheme deep links are forwarded by `CDVSceneDelegate` to `scene:openURLContexts:`, so no separate handling is needed<br />For Universal Links only, extract `NSUserActivity` from `userActivities` of `scene:willConnectToSession:options:` and call `handleUserActivity:` | In `scene:willConnectToSession:options:`, from `connectionOptions`<br />- Extract `URL` from `URLContexts` and call `handleURLSchemeDeeplink:`<br />- Extract `NSUserActivity` from `userActivities` and call `handleUserActivity:` |
    | Scheme deep link (background) | In `scene:openURLContexts:`, extract `URL` from `URLContexts` and call `handleURLSchemeDeeplink:` | Same |
    | Universal Link (background) | In `scene:continueUserActivity:`, call `handleUserActivity:` with `NSUserActivity` | Same |

    <Note>
      **Attention**

      Files under `platforms/ios` are reset when you run `cordova platform rm/add`.

      Manage the files using `<config-file>` and `<source-file>` in `config.xml` or a hook, or include the `platforms` directory in version control.
    </Note>

    #### 1. Add Scene Manifest to Info.plist

    <Note>
      **Attention**

      The `UISceneDelegateClassName` value must match the language used to implement `SceneDelegate`: **`$(PRODUCT_MODULE_NAME).SceneDelegate` for Swift and `SceneDelegate` for Objective-C.**

      A Swift class is registered with the Objective-C runtime as `<module>.SceneDelegate`.

      If the value does not match, the scene connection fails and the screen appears blank.
    </Note>

    <Tabs>
      <Tab title="cordova-ios 8.1.0 or later">
        This is included by default in `platforms/ios/App/App-Info.plist`.

        Confirm that no values are missing.

        **`UISceneStoryboardFile` must be set to `Main`.**

        Without this value, the screen appears blank.

        ```xml lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        <key>UIApplicationSceneManifest</key>
        <dict>
            <key>UIApplicationSupportsMultipleScenes</key>
            <false/>
            <key>UISceneConfigurations</key>
            <dict>
                <key>UIWindowSceneSessionRoleApplication</key>
                <array>
                    <dict>
                        <key>UISceneConfigurationName</key>
                        <string>Default Configuration</string>
                        <key>UISceneDelegateClassName</key>
                        <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                        <key>UISceneStoryboardFile</key>
                        <string>Main</string>
                    </dict>
                </array>
            </dict>
        </dict>
        ```
      </Tab>

      <Tab title="cordova-ios 7.x or earlier">
        Add the following `UIApplicationSceneManifest` to `platforms/ios/YOUR_PROJECT_NAME/YOUR_PROJECT_NAME-Info.plist`.

        cordova-ios 7.x and earlier do not include `Main.storyboard`, so **do not set `UISceneStoryboardFile`.**

        ```xml lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        <key>UIApplicationSceneManifest</key>
        <dict>
            <key>UIApplicationSupportsMultipleScenes</key>
            <false/>
            <key>UISceneConfigurations</key>
            <dict>
                <key>UIWindowSceneSessionRoleApplication</key>
                <array>
                    <dict>
                        <key>UISceneConfigurationName</key>
                        <string>Default Configuration</string>
                        <key>UISceneDelegateClassName</key>
                        <string>SceneDelegate</string>
                    </dict>
                </array>
            </dict>
        </dict>
        ```
      </Tab>
    </Tabs>

    #### 2. Create SceneDelegate and move the deep link collection code to SceneDelegate

    The code below uses the default template language for each cordova-ios version: Swift for 8.1.0 or later and Objective-C for 7.x or earlier.

    If you implement it in the other language, also apply the following.

    * **When implementing cordova-ios 8.1.0 or later in Objective-C**: Delete the default `App/SceneDelegate.swift` file and change `UISceneDelegateClassName` in `App-Info.plist` to `SceneDelegate`. Add `#import "AirbridgeCO.h"` to call `AirbridgeCO`.
    * **When implementing cordova-ios 7.x or earlier in Swift**: Change `UISceneDelegateClassName` to `$(PRODUCT_MODULE_NAME).SceneDelegate`. In the default `platforms/ios/YOUR_PROJECT_NAME/Bridging-Header.h` file, add `#import "AppDelegate.h"`, `#import "MainViewController.h"`, `#import <Cordova/CDVPlugin.h>`, and `#import "AirbridgeCO.h"`.

    <Tabs>
      <Tab title="cordova-ios 8.1.0 or later">
        Update `platforms/ios/App/SceneDelegate.swift` as follows.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import Cordova

        class SceneDelegate: CDVSceneDelegate {
            override func scene(
                _ scene: UIScene,
                willConnectTo session: UISceneSession,
                options connectionOptions: UIScene.ConnectionOptions
            ) {
                // CDVSceneDelegate forwards URL contexts to scene(_:openURLContexts:).
                super.scene(scene, willConnectTo: session, options: connectionOptions)

                // CDVSceneDelegate does not forward user activities.
                if let userActivity = connectionOptions.userActivities.first {
                    self.scene(scene, continue: userActivity)
                }
            }

            override func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
                // Required to notify other Cordova plugins of the URL.
                super.scene(scene, openURLContexts: URLContexts)

                if let context = URLContexts.first {
                    AirbridgeCO.deeplink().handleURLSchemeDeeplink(context.url)
                }
            }

            override func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
                super.scene(scene, continue: userActivity)
                AirbridgeCO.deeplink().handle(userActivity)
            }
        }
        ```
      </Tab>

      <Tab title="cordova-ios 7.x or earlier">
        Add the following two files under `platforms/ios/YOUR_PROJECT_NAME/Classes` and include them in the app target in Xcode.

        ```objective-c lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        // SceneDelegate.h
        #import <UIKit/UIKit.h>

        API_AVAILABLE(ios(13.0))
        @interface SceneDelegate : UIResponder <UIWindowSceneDelegate>

        @property (strong, nonatomic) UIWindow *window;

        @end
        ```

        ```objective-c lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        // SceneDelegate.m
        #import "SceneDelegate.h"
        #import "AppDelegate.h"
        #import "MainViewController.h"
        #import <Cordova/CDVPlugin.h>
        #import "AirbridgeCO.h"

        @implementation SceneDelegate

        - (void)scene:(UIScene *)scene
            willConnectToSession:(UISceneSession *)session
                         options:(UISceneConnectionOptions *)connectionOptions
        {
            if (![scene isKindOfClass:[UIWindowScene class]]) {
                return;
            }
            UIWindowScene *windowScene = (UIWindowScene *)scene;

            // SceneDelegate owns the window in the Scene lifecycle.
            MainViewController *viewController = [[MainViewController alloc] init];
            self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
            self.window.autoresizesSubviews = YES;
            self.window.rootViewController = viewController;
            [self.window makeKeyAndVisible];

            // Preserve properties read by existing code.
            AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
            appDelegate.window = self.window;
            appDelegate.viewController = viewController;

            UIOpenURLContext *context = connectionOptions.URLContexts.allObjects.firstObject;
            if (context != nil) {
                [self postCordovaOpenURLNotificationWithContext:context];
                [AirbridgeCO.deeplink handleURLSchemeDeeplink:context.URL];
            }
            NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject;
            if (userActivity != nil) {
                [AirbridgeCO.deeplink handleUserActivity:userActivity];
            }
        }

        - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
        {
            UIOpenURLContext *context = URLContexts.allObjects.firstObject;
            if (context == nil) {
                return;
            }

            [self postCordovaOpenURLNotificationWithContext:context];
            [AirbridgeCO.deeplink handleURLSchemeDeeplink:context.URL];
        }

        - (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity
        {
            [AirbridgeCO.deeplink handleUserActivity:userActivity];
        }

        // Replaces CDVAppDelegate's URL notification dispatch for other Cordova plugins.
        - (void)postCordovaOpenURLNotificationWithContext:(UIOpenURLContext *)context API_AVAILABLE(ios(13.0))
        {
            if (context.URL == nil) {
                return;
            }

            [[NSNotificationCenter defaultCenter] postNotificationName:CDVPluginHandleOpenURLNotification
                                                                  object:context.URL];

            NSMutableDictionary *openURLData = [[NSMutableDictionary alloc] init];
            [openURLData setValue:context.URL forKey:@"url"];
            [openURLData setValue:context.options.sourceApplication forKey:@"sourceApplication"];
            [openURLData setValue:context.options.annotation forKey:@"annotation"];
            [[NSNotificationCenter defaultCenter]
                postNotificationName:CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification
                              object:openURLData];
        }

        @end
        ```
      </Tab>
    </Tabs>

    <Note>
      **Attention**

      In cordova-ios 8.1.0 or later, **do not additionally call** `handleURLSchemeDeeplink(_:)` with `connectionOptions.urlContexts` in `scene(_:willConnectTo:options:)`.

      `CDVSceneDelegate` forwards it to `scene(_:openURLContexts:)`, so the deep link is collected twice at cold start.
    </Note>

    #### 3. Clean up AppDelegate

    * Keep the SDK initialization code (`getInstance:appName:withLaunchOptions:`) in `application:didFinishLaunchingWithOptions:` **as is.**
    * `application:openURL:options:` and `application:continueUserActivity:restorationHandler:`, which were added for deep link collection, are not called in the Scene lifecycle. After moving them to `SceneDelegate`, remove them from `AppDelegate`.
    * **For cordova-ios 7.x and earlier**, delete `self.viewController = [[MainViewController alloc] init];` and `return [super application:application didFinishLaunchingWithOptions:launchOptions];`, and replace them with `return YES;`. The default `CDVAppDelegate` implementation creates a new `window` and `CDVViewController`. If left unchanged, it creates a second Cordova web view that is not displayed.
  </Accordion>

  <Accordion title="Update 1.X.X → 2.X.X">
    The event API has been replaced to the below.

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    /**
     * Send event to server.
     * @param {string} category event name
     * @param {EventOption} [option={}] event options
     */
    trackEvent(category: string, option?: EventOption): void;
    ```

    Refer to the [Cordova 2.X.X migration](https://airbridge.readme.io/v1.1-en/page/cordova-2xx-migration-guide-1) guide for details.
  </Accordion>

  <Accordion title="Bitcode Compile Error">
    An error like below may occur when creating iOS builds with Cordova Ionic PhoneGap SDK v2.0.1+.

    ```text theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    ld: XCFrameworkIntermediates/AirBridge/AirBridge.framework/AirBridge(AirBridge-arm64-master.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE)
    ```

    Since Cordova Ionic PhoneGap SDK v2.0.1+ uses Airbridge iOS SDK v1.28.0+, Bitcode is no longer supported. Please refer to the [Bitcode compile error guide](/en/developers/troubleshooting-deprecated-ios-sdk-v1#bitcode-compile-error) for more details.
  </Accordion>

  <Accordion title="Update 1.1.X → 1.2.X">
    Uninstall the old version of the Airbridge SDK.

    Cordova: `cordova plugin remove airbridge-cordova-sdk`

    Ionic: `ionic cordova plugin remove airbridge-cordova-sdk`

    PhoneGap: `phonegap plugin remove airbridge-cordova-sdk`

    Install the new version of the Airbridge SDK.

    Cordova: `cordova plugin add airbridge-cordova-sdk`

    Ionic: `ionic cordova plugin add airbridge-cordova-sdk`

    PhoneGap: `phonegap plugin add airbridge-cordova-sdk`

    ###### Android

    Modify `android/app/src/main/java/.../MainActivity` as below.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    -     AirbridgeCO.getDeeplink().fetch(getIntent())
    +     AirbridgeCO.processDeeplinkData(getIntent())
    ```

    ###### iOS

    Modify `ios/[Project Name]/AppDelegate` as below.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    -     AirbridgeCO.deeplink()?.handleURLSchemeDeeplink(url, withSourceBundle: sourceApplication)
    +     AirbridgeCO.deeplink()?.handleURLSchemeDeeplink(url)
    ```

    ###### Settings

    1. Add an `airbridge.json`file to the project folder.
    2. Add the parameters shown in the example below in JSON format.

    ###### Example

    ```json lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    {
        "sessionTimeoutSeconds": 300,
        "autoStartTrackingEnabled": true,
        "userInfoHashEnabled": true,
        "trackAirbridgeLinkOnly": false,
        "facebookDeferredAppLinkEnabled": false,
        "locationCollectionEnabled": false
        "trackingAuthorizeTimeoutSeconds": 0
    }
    ```

    ###### Description

    | Name | Type | Default | Description |
    | - | - | - | - |
    | sessionTimeoutSeconds | number | 300 | An app open event will not be sent when the app is reopened within the designated period. |
    | autoStartTrackingEnabled | boolean | true | When set to false, no events will be sent until `airbridge.state.startTracking()` is called. |
    | userInfoHashEnabled | boolean | true | When set to false, user email and user phone information are sent without being hashed. |
    | trackAirbridgeLinkOnly | boolean | false | When set to true, deep link events are sent only when app is opened with an Airbridge deep link. |
    | facebookDeferredAppLinkEnabled | boolean | false | When set to true and the Facebook SDK is installed, Facebook Deferred App Link data is collected. |
    | locationCollectionEnabled | boolean | false | When set to true, location information is collected. (Android Only)<br />Two permissions must be allowed in `AndroidManifest.xml`android.permission.ACCESS\_FINE\_LOCATION<br />android.permission.ACCESS\_COARSE\_LOCATION |
    | trackingAuthorizeTimeoutSeconds | number | 0 | When set timeout, Install event is delayed until Request tracking authorization alert is clicked. (iOS only) |
  </Accordion>

  <Accordion title="Update 1.0.X → 1.1.X">
    ###### Install

    Uninstall the old version of the Airbridge SDK.

    Cordova: `cordova plugin remove airbridge-cordova-sdk`

    Ionic: `ionic cordova plugin remove airbridge-cordova-sdk`

    PhoneGap: `phonegap plugin remove airbridge-cordova-sdk`

    Install the new version of the Airbridge SDK.

    Cordova: `cordova plugin add airbridge-cordova-sdk`

    Ionic: `ionic cordova plugin add airbridge-cordova-sdk`

    PhoneGap: `phonegap plugin add airbridge-cordova-sdk`

    `setDeeplinkListener`

    Remove the `getInitialDeeplink` function and use the `setDeeplinkListener` function only.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    - Airbridge.deeplink.getInitialDeeplink().then((deeplink) => {
    -
    - });
    .
    . Airbridge.deeplink.setDeeplinkListner((deeplink) => {
    .
    . });
    ```

    ###### Android

    `AndroidManifest.xml`

    In the `MainActivity` section of the `android/app/src/main/AndroidManifest.xml` file, add `intent-filter` parameters as below.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    + <intent-filter android:autoVerify="true">
    +     <action android:name="android.intent.action.VIEW" />
    +
    +     <category android:name="android.intent.category.DEFAULT" />
    +     <category android:name="android.intent.category.BROWSABLE" />
    +
    +     <data android:scheme="http" android:host="YOUR_APP_NAME.deeplink.page" />
    +     <data android:scheme="https" android:host="YOUR_APP_NAME.deeplink.page" />
    + </intent-filter>
    . <intent-filter android:autoVerify="true">
    .     <action android:name="android.intent.action.VIEW" />
    .
    .     <category android:name="android.intent.category.DEFAULT" />
    .     <category android:name="android.intent.category.BROWSABLE" />
    .
    .     <data android:scheme="http" android:host="YOUR_APP_NAME.airbridge.io" />
    .     <data android:scheme="https" android:host="YOUR_APP_NAME.airbridge.io" />
    . </intent-filter>
    . <intent-filter>
    .     <action android:name="android.intent.action.VIEW" />
    .
    .     <category android:name="android.intent.category.DEFAULT" />
    .     <category android:name="android.intent.category.BROWSABLE" />
    .
    .     <data android:scheme="EXAMPLE_SCHEME" />
    . </intent-filter>
    ```

    ###### `MainActivity.java`

    Modify `android/app/src/main/java/.../MainActivity.java` as below.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    . import co.ab180.airbridge.cordova.AirbridgeCO;
    .
    . public class MainActivity extends ReactActivity {
    +     @Override
    +     protected void onResume() {
    +         super.onResume();
    +
    +         AirbridgeCO.getDeeplink().fetch(getIntent());
    +     }
    +
    .     @Override
    .     public void onNewIntent(Intent intent) {
    .         super.onNewIntent(intent);
    .         setIntent(intent);
    .     }
    . }
    ```

    ###### iOS

    ###### Universal Link

    1. Go to "Xcode → Project file → Signing & Capabilities".
    2. Click "+ Capability" and add "Associated Domains".
    3. Add `applinks:YOUR_APP_NAME.deeplink.page`to "Associated Domains".

    `YOUR_APP_NAME` can be found at the "Airbridge dashboard → Settings → Tokens → App Name". `AppDelegate.m`

    Modify `ios/.../AppDelegate.m` as below.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    . - (BOOL)application:(UIApplication *)application
    .             openURL:(NSURL *)url
    .             options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options
    . {
    -     [AirbridgeCO.instance handleURLSchemeDeeplink:url
    -                                withSourceBundle:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
    +     [AirbridgeCO.deeplink handleURLSchemeDeeplink:url
    +                                withSourceBundle:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
    .
    .     return YES;
    . }
    .
    . - (BOOL)application:(UIApplication*)application
    .             openURL:(NSURL*)url
    .   sourceApplication:(NSString*)sourceApplication
    .          annotation:(id)annotation
    . {
    -     [AirbridgeCO.instance handleURLSchemeDeeplink:url
    -                                withSourceBundle:sourceApplication];
    +     [AirbridgeCO.deeplink handleURLSchemeDeeplink:url
    +                                withSourceBundle:sourceApplication];
    .
    .     return YES;
    . }
    ```

    When targeting iOS 8.x or earlier, also make the following changes.

    ```diff lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    . -  (BOOL)application:(UIApplication*)application
    . continueUserActivity:(NSUserActivity*)userActivity
    .   restorationHandler:(void (^)(NSArray* _Nullable))restorationHandler
    . {
    -     [AirbridgeCO.instance handleUniversalDeeplink:userActivity.webpageURL];
    +     [AirbridgeCO.deeplink handleUniversalLink:userActivity.webpageURL];
    .
    .     return YES;
    . }
    ```
  </Accordion>
</AccordionGroup>
