diff --git a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/Airborne.kt b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/Airborne.kt index b77c267e..e219c0e2 100644 --- a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/Airborne.kt +++ b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/Airborne.kt @@ -12,12 +12,20 @@ import javax.net.ssl.X509TrustManager @Keep class Airborne( - context: Context, - releaseConfigUrl: String, - private val airborneInterface: AirborneInterface + private val context: Context, + private val releaseConfigUrl: String, + private val airborneInterface: AirborneInterface, + private val shouldUpdate: Boolean ) { - constructor(context: Context, releaseConfigUrl: String) : this(context, releaseConfigUrl, object : AirborneInterface() {}) + constructor(context: Context, releaseConfigUrl: String) : this(context, releaseConfigUrl, object : AirborneInterface() {}, true) + + constructor(context: Context, releaseConfigUrl: String, airborneInterface: AirborneInterface) : this( + context, + releaseConfigUrl, + airborneInterface, + true + ) /** * Default no-op TrackerCallback. @@ -59,6 +67,7 @@ class Airborne( init { airborneObjectMap.put(airborneInterface.getNamespace(), this) + applicationManager.shouldUpdate = shouldUpdate applicationManager.loadApplication(airborneInterface.getNamespace(), airborneInterface.getLazyDownloadCallback()) } @@ -94,15 +103,13 @@ class Airborne( } /** - * Set custom SSL configuration for mTLS support. - * Call this before network requests are made to enable client certificate authentication. - * - * @param sslSocketFactory SSL socket factory configured with client certificate - * @param trustManager Trust manager for server certificate validation + * Checks for updates by fetching the remote RC and comparing with local. + * Uses the dimensions provided via AirborneInterface at init time. + * @return JSON string with update metadata. */ @Keep - fun setSslConfig(sslSocketFactory: SSLSocketFactory, trustManager: X509TrustManager) { - applicationManager.setSslConfig(sslSocketFactory, trustManager) + fun checkForUpdate(): String { + return applicationManager.checkForUpdate() } companion object { diff --git a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModule.kt b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModule.kt index 17c62206..da3010f8 100644 --- a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModule.kt +++ b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModule.kt @@ -31,6 +31,11 @@ class AirborneModule(reactContext: ReactApplicationContext) : implementation.getBundlePath(namespace, promise) } + @ReactMethod + fun checkForUpdate(namespace: String, promise: Promise) { + implementation.checkForUpdate(namespace, promise) + } + companion object { const val NAME = "Airborne" } diff --git a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModuleImpl.kt b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModuleImpl.kt index fceed5b3..10d7f50c 100644 --- a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModuleImpl.kt +++ b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneModuleImpl.kt @@ -68,4 +68,18 @@ class AirborneModuleImpl(private val reactContext: ReactApplicationContext) { promise.reject("AIRBORNE_ERROR", "Failed to get bundle path: ${e.message}", e) } } + + fun checkForUpdate(namespace: String, promise: Promise) { + try { + val airborne = Airborne.airborneObjectMap[namespace] + if (airborne == null) { + promise.reject("UNKNOWN_NAMESPACE", "Namespace not found: $namespace") + return + } + val result = airborne.checkForUpdate() + promise.resolve(result) + } catch (e: Exception) { + promise.reject("AIRBORNE_ERROR", "Failed to check for update: ${e.message}", e) + } + } } diff --git a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneTurboModule.kt b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneTurboModule.kt index 04300ce4..0d681550 100644 --- a/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneTurboModule.kt +++ b/airborne-react-native/android/src/main/java/in/juspay/airborneplugin/AirborneTurboModule.kt @@ -26,6 +26,10 @@ class AirborneTurboModule(reactContext: ReactApplicationContext) : implementation.getBundlePath(nameSpace, promise) } + override fun checkForUpdate(nameSpace: String, promise: Promise) { + implementation.checkForUpdate(nameSpace, promise) + } + companion object { const val NAME = "AirborneReact" } diff --git a/airborne-react-native/example/src/App.tsx b/airborne-react-native/example/src/App.tsx index e37518d7..0431e961 100644 --- a/airborne-react-native/example/src/App.tsx +++ b/airborne-react-native/example/src/App.tsx @@ -4,6 +4,7 @@ import { readReleaseConfig, getFileContent, getBundlePath, + checkForUpdate, } from 'airborne-react-native'; export default function App() { @@ -11,6 +12,7 @@ export default function App() { const [bundlePath, setBundlePath] = useState(); const [fileContent, setFileContent] = useState(); const [isInitialized, setIsInitialized] = useState(false); + const [updateMessage, setUpdateMessage] = useState(""); // Airborne is initialized in native code (MainApplication.kt for Android, AppDelegate.swift for iOS) // This ensures the instance is ready before React Native starts @@ -22,6 +24,15 @@ export default function App() { .catch(() => setIsInitialized(false)); }, []); + const handleCheckForUpdate = async () => { + try { + const resp = await checkForUpdate("airborne-example"); + setUpdateMessage(resp); + }catch(err: any) { + Alert.alert('Error', err.message || 'Failed to check for update'); + } + } + const handleReadReleaseConfig = async () => { try { const config = await readReleaseConfig("airborne-example"); @@ -66,6 +77,16 @@ export default function App() { )} + +