Skip to content

Commit

Permalink
[MOB-10951] Add mobile framework info
Browse files Browse the repository at this point in the history
  • Loading branch information
sumeruchat committed Jan 13, 2025
1 parent def5e7c commit cfc4bf8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 26 deletions.
73 changes: 58 additions & 15 deletions swift-sdk/Internal/InternalIterableAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,15 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {

hexToken = token.hexString()

let mobileFrameworkType = MobileFrameworkType.detect()
let mobileFrameworkType = IterableAPIMobileFrameworkType.detect()
let registerTokenInfo = RegisterTokenInfo(hexToken: token.hexString(),
appName: appName,
pushServicePlatform: config.pushPlatform,
apnsType: dependencyContainer.apnsTypeChecker.apnsType,
deviceId: deviceId,
deviceAttributes: deviceAttributes,
sdkVersion: localStorage.sdkVersion,
mobileFrameworkInfo: MobileFrameworkInfo(frameworkType: frameworkType, iterableSdkVersion: localStorage.sdkVersion))
mobileFrameworkInfo: IterableAPIMobileFrameworkInfo(frameworkType: mobileFrameworkType, iterableSdkVersion: nil))
requestHandler.register(registerTokenInfo: registerTokenInfo,
notificationStateProvider: notificationStateProvider,
onSuccess: { (_ data: [AnyHashable: Any]?) in
Expand Down Expand Up @@ -779,24 +779,67 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
}
}

extension MobileFrameworkType {

static func detect() -> MobileFrameworkType {
extension IterableAPIMobileFrameworkType {
private struct FrameworkClasses {
static let flutter = [
"FlutterViewController",
"GeneratedPluginRegistrant",
"FlutterEngine",
"FlutterPluginRegistry"
]

static let reactNative = [
"RCTBridge",
"RCTRootView",
"RCTBundleURLProvider",
"RCTEventEmitter"
]
}

static func detect() -> IterableAPIMobileFrameworkType {
let bundle = Bundle.main

// Check for Flutter
if bundle.classNamed("FlutterViewController") != nil ||
bundle.classNamed("GeneratedPluginRegistrant") != nil {
return .flutter
// Helper function to check for framework classes
func hasFrameworkClasses(_ classNames: [String]) -> Bool {
// Consider framework present if ANY of its core classes are found
return classNames.contains { className in
bundle.classNamed(className) != nil
}
}

// Check for React Native
if bundle.classNamed("RCTBridge") != nil ||
bundle.classNamed("RCTRootView") != nil {
// Check for multiple framework classes to increase confidence
let hasFlutter = hasFrameworkClasses(FrameworkClasses.flutter)
let hasReactNative = hasFrameworkClasses(FrameworkClasses.reactNative)

switch (hasFlutter, hasReactNative) {
case (true, true):
ITBError("Both Flutter and React Native frameworks detected. This is unexpected.")
// In case of ambiguity, we could try to determine the primary framework
// by checking for more framework-specific indicators
if let mainBundle = Bundle.main.infoDictionary,
mainBundle["CFBundleExecutable"] as? String == "Runner" {
return .flutter // Flutter apps typically use "Runner" as executable name
}
return .reactNative

case (true, false):
return .flutter

case (false, true):
return .reactNative

case (false, false):
// Additional check for framework-specific build settings or Info.plist entries
if let mainBundle = Bundle.main.infoDictionary {
if mainBundle["FlutterDeploymentTarget"] != nil {
return .flutter
}
if mainBundle["RNBundleURLProvider"] != nil {
return .reactNative
}
}

return .native
}

// If no framework detected, assume native
return .native
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@

import Foundation

enum MobileFrameworkType: String {
case flutter = "Flutter"
case reactNative = "ReactNative"
case native = "Native"
}

struct MobileFrameworkInfo {
let frameworkType: MobileFrameworkType
let iterableSdkVersion: String?
}

struct RegisterTokenInfo {
let hexToken: String
Expand All @@ -23,7 +13,7 @@ struct RegisterTokenInfo {
let deviceId: String
let deviceAttributes: [String: String]
let sdkVersion: String?
let mobileFrameworkInfo: MobileFrameworkInfo?
let mobileFrameworkInfo: IterableAPIMobileFrameworkInfo?
}

struct UpdateSubscriptionsInfo {
Expand Down
15 changes: 15 additions & 0 deletions swift-sdk/SDK/IterableConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

import Foundation

public enum IterableAPIMobileFrameworkType: String {
case flutter = "Flutter"
case reactNative = "ReactNative"
case native = "Native"
}

public struct IterableAPIMobileFrameworkInfo {
let frameworkType: IterableAPIMobileFrameworkType
let iterableSdkVersion: String?
}

/// Custom URL handling delegate
@objc public protocol IterableURLDelegate: AnyObject {
/// Callback called for a deep link action. Return true to override default behavior
Expand Down Expand Up @@ -133,4 +144,8 @@ public class IterableConfig: NSObject {

/// Allows for fetching embedded messages.
public var enableEmbeddedMessaging = false

/// The type of mobile framework we are using.
public var mobileFrameworkInfo: IterableAPIMobileFrameworkInfo?
}

0 comments on commit cfc4bf8

Please sign in to comment.