I am new to ReactNative.In my current app, deeplinking was coded and working well when it was done through appDelegate.later, the app support Carplay as well, so to handle multiple scenes sceneDelegate was introduced.
After that, whenever deeplinking is invoked then
- if the app is in background state then it launches the app at specific location
- if the app is removed from memory and deeplink clicked then it only launches the app, but doesn't navigate to desired screen.
What is the issue here,what things I need to change / add to make app launch at desired location even if app is removed from memory.
Here is my appDelegate.
func appDelegate() -> AppDelegate { return UIApplication.shared.delegate as! AppDelegate}@UIApplicationMainclass AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var appCenter: AppCenterReactNative! var appCenterAnaltics: AppCenterReactNativeAnalytics! var appCenterCrashes: AppCenterReactNativeCrashes! let mParticleKey: String = ReactNativeConfig.env(for: "MPARTICLE_IOS_KEY"); let mParticleSecret: String = ReactNativeConfig.env(for: "MPARTICLE_IOS_SECRET"); // var mParticleEmail: String = ReactNativeConfig.env(for: "MPARTICLE_EMAIL"); let mParticleEnv: String = ReactNativeConfig.env(for: "MPARTICLE_ENV"); let mParticleDataPlanName: String = ReactNativeConfig.env(for: "MPARTICLE_DATAPLAN"); let mParticleDataPlanVersion: String = ReactNativeConfig.env(for: "MPARTICLE_DATAPLAN_VERSION"); let moEngageAppID: String = ReactNativeConfig.env(for: "MOENGAGE_APP_ID"); /* CarPlay setup */ var playableContentManager: MPPlayableContentManager? var remoteCommandCenter: MPRemoteCommandCenter? let carplayPlaylist = CarPlayPlaylist() let carplayArtworkCache = NSCache<AnyObject, UIImage>() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { initializeFlipper(with: application) /* Moengage */ let sdkConfig = MoEngageSDKConfig(appId: moEngageAppID, dataCenter: .data_center_01); MoEngageInitializer.sharedInstance().initializeDefaultSDKConfig(sdkConfig, andLaunchOptions: launchOptions ?? [:]) AppCenterReactNative.register() AppCenterReactNativeAnalytics.register(withInitiallyEnabled: true); AppCenterReactNativeCrashes.registerWithAutomaticProcessing(); FirebaseApp.configure() /* ChromeCast activate */ let receiverAppID:String = "CC1AD845"; // or @"ABCD1234" let criteria = GCKDiscoveryCriteria(applicationID: receiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) let bridge = RCTBridge(delegate: self, launchOptions: launchOptions)! let rootView = RCTRootView(bridge: bridge, moduleName: "nova", initialProperties: nil) let rootViewController = UIViewController() rootViewController.view = rootView self.window = UIWindow(frame: UIScreen.main.bounds) self.window?.rootViewController = rootViewController self.window?.makeKeyAndVisible() /* MPNowPlayingInfoCenter */ UIApplication.shared.beginReceivingRemoteControlEvents() setupCarPlay(); RNSplashScreen.show() /* Setup MParticle */ var dPlanVersion:NSNumber = 0 if let versionInt = Int(mParticleDataPlanVersion) { dPlanVersion = NSNumber(value:versionInt) } var mParticleEnvMode: MPEnvironment = MPEnvironment.development if(mParticleEnv == "PROD") { mParticleEnvMode = MPEnvironment.production } let mParticleOptions = MParticleOptions(key: mParticleKey, secret: mParticleSecret) mParticleOptions.environment = mParticleEnvMode mParticleOptions.dataPlanId = mParticleDataPlanName mParticleOptions.dataPlanVersion = dPlanVersion mParticleOptions.proxyAppDelegate = false if #available(iOS 14, *) { mParticleOptions.attStatus = NSNumber.init(value: ATTrackingManager.trackingAuthorizationStatus.rawValue) } // Remove AST Events mParticleOptions.onCreateBatch = { (batch: [AnyHashable: Any]) -> [AnyHashable: Any]? in var modifiedBatch = batch guard var modifiedMessages = batch["msgs"] as? [AnyHashable] else { return batch } var index = 0 for message in modifiedMessages { // the following removes Application State Transition (AST) events, except for those uploaded on installs and upgrades // Install AST events are used by many server-side integrations and are used by // mParticle to ensure there is a user profile created guard let messageAsDictionary = message as? [AnyHashable: Any] else { continue } guard let type = messageAsDictionary["dt"] as? String else { continue } let isFirstRun = messageAsDictionary["ifr"] as? Bool ?? false let isUpgrade = messageAsDictionary["iu"] as? Bool ?? false if type == "ast" && !isFirstRun && !isUpgrade { modifiedMessages.remove(at: index) index -= 1 } index += 1 } modifiedBatch["msgs"] = modifiedMessages return modifiedBatch } // Start the SDK MParticle.sharedInstance().start(with: mParticleOptions) return true } private func initializeFlipper(with application: UIApplication) { #if DEBUG let client = FlipperClient.shared() let layoutDescriptorMapper = SKDescriptorMapper(defaults: ()) client?.add(FlipperKitLayoutPlugin(rootNode: application, with: layoutDescriptorMapper!)) client?.add(FKUserDefaultsPlugin(suiteName: "nova")) client?.add(FlipperKitReactPlugin()) client?.add(FlipperKitNetworkPlugin(networkAdapter: SKIOSNetworkAdapter())) client?.start() #endif } /* Allow for orientation change */ func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return Orientation.getOrientation() } /* Allow Link back URLs ('nova://') */ public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { return RCTLinkingManager.application(app, open: url, options: options) } public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { return RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler) }}extension AppDelegate: RCTBridgeDelegate { func sourceURL(for bridge: RCTBridge!) -> URL! { #if DEBUG return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") #else return CodePush.bundleURL() #endif }}
This is my sceneDelegate
@available(iOS 13.0, *)class SceneDelegate: UIResponder, UIWindowSceneDelegate, RCTBridgeDelegate { let mParticleKey: String = ReactNativeConfig.env(for: "MPARTICLE_IOS_KEY"); let mParticleSecret: String = ReactNativeConfig.env(for: "MPARTICLE_IOS_SECRET"); // var mParticleEmail: String = ReactNativeConfig.env(for: "MPARTICLE_EMAIL"); let mParticleEnv: String = ReactNativeConfig.env(for: "MPARTICLE_ENV"); let mParticleDataPlanName: String = ReactNativeConfig.env(for: "MPARTICLE_DATAPLAN"); let mParticleDataPlanVersion: String = ReactNativeConfig.env(for: "MPARTICLE_DATAPLAN_VERSION"); func sourceURL(for bridge: RCTBridge!) -> URL! { let jsCodeLocation: URL jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") return jsCodeLocation } var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { var deeplink: URL? if let userActivity = connectionOptions.userActivities.first(where: { $0.activityType == NSUserActivityTypeBrowsingWeb }), let webpageURL = userActivity.webpageURL { // get universal link deeplink = webpageURL } else if let urlContext = connectionOptions.urlContexts.first { // get app scheme deep link deeplink = urlContext.url } handleDeepLink(deeplink) let bridge = RCTBridge.init(delegate: self, launchOptions: nil) let rootView = RCTRootView.init(bridge: bridge!, moduleName: "nova", initialProperties: nil) let rootViewController = UIViewController() rootViewController.view = rootView AppCenterReactNative.register() AppCenterReactNativeAnalytics.register(withInitiallyEnabled: true); AppCenterReactNativeCrashes.registerWithAutomaticProcessing(); FirebaseApp.configure() /* ChromeCast activate */ let receiverAppID:String = "CC1AD845"; // or @"ABCD1234" let criteria = GCKDiscoveryCriteria(applicationID: receiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) /* MPNowPlayingInfoCenter */ UIApplication.shared.beginReceivingRemoteControlEvents() RNSplashScreen.show() // Instantiate root view here instead of scene to start the bundler on app launch RNBridgeInstanceHolder.sharedInstance.bridge = bridge RNBridgeInstanceHolder.sharedInstance.rctRootView = rootView if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = rootViewController self.window = window window.makeKeyAndVisible() } if #unavailable(iOS 14.0) { appDelegate().setupCarPlay() } /* Setup MParticle */ var dPlanVersion:NSNumber = 0 if let versionInt = Int(mParticleDataPlanVersion) { dPlanVersion = NSNumber(value:versionInt) } var mParticleEnvMode: MPEnvironment = MPEnvironment.development if(mParticleEnv == "PROD") { mParticleEnvMode = MPEnvironment.production } let mParticleOptions = MParticleOptions(key: mParticleKey, secret: mParticleSecret) mParticleOptions.environment = mParticleEnvMode mParticleOptions.dataPlanId = mParticleDataPlanName mParticleOptions.dataPlanVersion = dPlanVersion mParticleOptions.proxyAppDelegate = false if #available(iOS 14, *) { mParticleOptions.attStatus = NSNumber.init(value: ATTrackingManager.trackingAuthorizationStatus.rawValue) } // Remove AST Events mParticleOptions.onCreateBatch = { (batch: [AnyHashable: Any]) -> [AnyHashable: Any]? in var modifiedBatch = batch guard var modifiedMessages = batch["msgs"] as? [AnyHashable] else { return batch } var index = 0 for message in modifiedMessages { // the following removes Application State Transition (AST) events, except for those uploaded on installs and upgrades // Install AST events are used by many server-side integrations and are used by // mParticle to ensure there is a user profile created guard let messageAsDictionary = message as? [AnyHashable: Any] else { continue } guard let type = messageAsDictionary["dt"] as? String else { continue } let isFirstRun = messageAsDictionary["ifr"] as? Bool ?? false let isUpgrade = messageAsDictionary["iu"] as? Bool ?? false if type == "ast" && !isFirstRun && !isUpgrade { modifiedMessages.remove(at: index) index -= 1 } index += 1 } modifiedBatch["msgs"] = modifiedMessages return modifiedBatch } // Start the SDK MParticle.sharedInstance().start(with: mParticleOptions) } //handels app scheme novaplayer:// in active and inactive foreground mode func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { if let url = URLContexts.first?.url { handleDeepLink(url) } } //handels universal links https://novaplayer in active and inactive foreground mode func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { if userActivity.activityType == NSUserActivityTypeBrowsingWeb { if let url = userActivity.webpageURL { handleDeepLink(url) } } } //function to pass deelink value to react native func handleDeepLink(_ deeplink: URL?) { guard let deeplink = deeplink else { os_log("No deeplink found", log: OSLog.default, type: .debug) return } os_log("Deeplink URL FOUND: %@", log: OSLog.default, type: .debug, deeplink.absoluteString) RCTLinkingManager.application(UIApplication.shared, open: deeplink, options: [:]) }}
Here is my info.plist piece of code.
<key>UIApplicationSceneManifest</key><dict><key>UISceneConfigurations</key><dict><key>CPTemplateApplicationSceneSessionRoleApplication</key><array><dict><key>UISceneClassName</key><string>CPTemplateApplicationScene</string><key>UISceneConfigurationName</key><string>CarPlay Configuration</string><key>UISceneDelegateClassName</key><string>$(PRODUCT_MODULE_NAME).CarPlaySceneDelegate</string></dict></array><key>UIWindowSceneSessionRoleApplication</key><array><dict><key>UISceneConfigurationName</key><string>Default Configuration</string><key>UISceneDelegateClassName</key><string>$(PRODUCT_MODULE_NAME).SceneDelegate</string></dict></array></dict></dict>
It is working as expected in Android build, but having issue only with iOS build.If I switch back to appDelegate without scenedelegate then my Carplay app is not getting launched.
Any help will be appreciated.
Thanks.