Skip to main content

Migration Guide — React Native to Native iOS/Android SDKs

This guide helps developers move from @hoberhq/react-native-sdk to the native HoberKit (iOS) or hober-android-sdk (Android) SDKs.


When to Choose Native vs React Native

ScenarioRecommendation
Greenfield native iOS or Android appUse the native SDK
Existing full Swift/Kotlin codebaseMigrate to native SDK
Performance-sensitive app (games, media)Use the native SDK to avoid the React Native bridge overhead
Cross-platform product sharing JS business logicStay on @hoberhq/react-native-sdk
Expo managed workflow (cannot eject)Use @hoberhq/react-native-sdk (Expo bare) or the Hober REST API

In short: choose the native SDK when your app is written primarily in Swift or Kotlin and you want to eliminate the JavaScript bridge. Stick with @hoberhq/react-native-sdk for cross-platform React Native apps where the React component model provides value.


API Comparison

The table below maps each @hoberhq/react-native-sdk API to its native iOS and Android equivalent.

React Native SDKNative iOS (HoberKit)Native Android (hober-android-sdk)
<HoberProvider sdkKey channelId> (JSX wrapper)Hober.configure(sdkKey:channelId:) in AppDelegateHober.init(context, sdkKey, channelId) in Application.onCreate()
useHober() hookN/A — use Hober.* class methods directlyN/A — use Hober.* companion object methods directly
requestPermission()Promise<boolean>await Hober.requestPermission()BoolRuntime POST_NOTIFICATIONS permission request (Android 13+)
identifySubscriber({ externalId, email })Hober.identifySubscriber(externalId:email:attributes:)Hober.identifySubscriber(externalId, email, attributes, callback)
registerDevice() (auto via HoberProvider)Hober.registerDevice(token:) in didRegisterForRemoteNotificationsWithDeviceTokenHober.registerDevice(token) via HoberFirebaseMessagingService.onNewToken
Foreground handling via React component re-renderUNUserNotificationCenterDelegate.userNotificationCenter(_:willPresent:)Override onMessageReceived in your FirebaseMessagingService
Background/silent push via JS handlerapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:)content-available: 1onMessageReceived when app is backgrounded

API surface gaps

@hoberhq/react-native-sdk exposes a unified JS interface over both iOS and Android. The native SDKs have full API parity for all production features — configure/init, requestPermission, identifySubscriber, and registerDevice are all available on both platforms. There is no feature exclusive to the React Native SDK that is unavailable in the native SDKs.

The one difference is paradigm: the React Native SDK wraps both platforms behind a single useHober() hook, while each native SDK uses the platform's own lifecycle hooks and class APIs.


Paradigm Shift: Declarative to Imperative

The React Native SDK uses React's component model — you wrap your app in HoberProvider and call methods from useHober():

// React Native — declarative / hook-based
import { HoberProvider, useHober } from '@hoberhq/react-native-sdk';

export default function App() {
return (
<HoberProvider sdkKey="YOUR_SDK_KEY" channelId="default">
<PushSetup />
</HoberProvider>
);
}

function PushSetup() {
const { requestPermission, identifySubscriber, registerDevice } = useHober();
// ...
}

The native SDKs use imperative APIs tied to platform lifecycle methods. There is no JSX, no hook, and no provider context — you call Hober.* static methods directly at the right lifecycle points.


From React Native to Native iOS

Step 1 — Remove the React Native SDK

npm uninstall @hoberhq/react-native-sdk
cd ios && pod install

Remove the <HoberProvider> wrapper from your root component and delete all useHober() imports.

Step 2 — Install HoberKit via Swift Package Manager

In Xcode, go to File > Add Package Dependencies… and enter:

https://github.com/hoberhq/hober-ios-sdk.git

Choose Up to Next Major Version from 1.0.0 and add the HoberKit target.

Step 3 — Configure in AppDelegate

Replace the HoberProvider initialisation with Hober.configure(sdkKey:channelId:) inside application(_:didFinishLaunchingWithOptions:):

import UIKit
import HoberKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
Hober.configure(sdkKey: "YOUR_SDK_KEY", channelId: "YOUR_CHANNEL_ID")
UNUserNotificationCenter.current().delegate = self
return true
}

func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Hober.registerDevice(token: deviceToken)
}
}

Step 4 — Request Permission

Replace the useHober().requestPermission() call with the native equivalent:

// React Native (before)
// const { requestPermission } = useHober();
// const granted = await requestPermission();

// Native iOS (after)
let granted = await Hober.requestPermission()

Call this at a meaningful moment in your onboarding flow — not immediately on launch.

Step 5 — Identify a Subscriber

// After user login/sign-in
Task {
try await Hober.identifySubscriber(
externalId: user.id,
email: user.email
)
}

Step 6 — Handle Foreground Notifications

Add UNUserNotificationCenterDelegate to display banners while the app is in the foreground:

extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
completionHandler([.banner, .sound, .badge])
}
}

Token Lifecycle in Native iOS

In @hoberhq/react-native-sdk the token refresh is handled internally — you never see didRegisterForRemoteNotificationsWithDeviceToken. With HoberKit, token refresh is automatic via the same delegate method: whenever iOS rotates the APNs token, didRegisterForRemoteNotificationsWithDeviceToken is called and Hober.registerDevice(token:) forwards it to Hober. No extra code is needed beyond the boilerplate above.


From React Native to Native Android

Step 1 — Remove the React Native SDK

npm uninstall @hoberhq/react-native-sdk

Remove the <HoberProvider> wrapper from your root component and delete all useHober() imports. Clean up the React Native bridge references in android/.

Step 2 — Add the Gradle Dependency

In your project-level build.gradle, ensure mavenCentral() is listed:

repositories {
mavenCentral()
google()
}

In your app-level build.gradle, add:

dependencies {
implementation("io.hober:sdk:1.0.0")
implementation("com.google.firebase:firebase-messaging:24.0.0")
}

Step 3 — Initialise in Application.onCreate()

Create an Application subclass (if you don't already have one) and replace the HoberProvider initialisation with Hober.init():

import android.app.Application
import io.hober.sdk.Hober
import io.hober.sdk.android.AppContextImpl

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Hober.init(
context = AppContextImpl(this),
sdkKey = "YOUR_SDK_KEY",
channelId = "default"
)
}
}

Register MyApplication in AndroidManifest.xml:

<application android:name=".MyApplication" ...>

Step 4 — Request POST_NOTIFICATIONS Permission (Android 13+)

The React Native SDK's requestPermission() handled this for you. In the native Android SDK you must request the POST_NOTIFICATIONS permission directly:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}

Declare the permission in AndroidManifest.xml:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Step 5 — Set Up HoberFirebaseMessagingService

Extend HoberFirebaseMessagingService to handle token updates automatically:

import io.hober.sdk.fcm.HoberFirebaseMessagingService

class MyFirebaseService : HoberFirebaseMessagingService()

Register it in AndroidManifest.xml:

<service android:name=".MyFirebaseService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

Step 6 — Identify a Subscriber

// After user logs in
Hober.identifySubscriber(
externalId = user.id,
email = user.email
) { result -> /* handle result */ }

Token Lifecycle in Native Android

In @hoberhq/react-native-sdk the FCM token is obtained and refreshed internally. With hober-android-sdk, HoberFirebaseMessagingService overrides onNewToken and forwards the new token to Hober automatically. If you need manual control, call Hober.registerDevice(token) directly — for example, inside your own FirebaseMessagingService.onNewToken:

override fun onNewToken(token: String) {
super.onNewToken(token)
Hober.registerDevice(token = token)
}

Behavioural Differences Summary

BehaviourReact Native SDKNative iOS (HoberKit)Native Android (hober-android-sdk)
Initialisation<HoberProvider> JSX wrapper (component mount)Hober.configure(sdkKey:channelId:) in didFinishLaunchingWithOptionsHober.init(...) in Application.onCreate()
Permission requestrequestPermission() — unified cross-platformHober.requestPermission() — async/awaitManual POST_NOTIFICATIONS runtime request (Android 13+)
Token registrationAutomatic inside HoberProviderHober.registerDevice(token:) in didRegisterForRemoteNotificationsWithDeviceTokenAutomatic via HoberFirebaseMessagingService.onNewToken
Token refreshHandled internallyiOS calls didRegisterForRemoteNotificationsWithDeviceToken automaticallyFCM calls onNewToken automatically
Foreground handlingReact state / JS event listenerUNUserNotificationCenterDelegate.userNotificationCenter(_:willPresent:)FirebaseMessagingService.onMessageReceived while foregrounded
Background/silent pushJS handler registered via HoberProviderapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:)content-available: 1onMessageReceived (FCM handles wake-up)
Subscriber identificationidentifySubscriber({ externalId, email })Hober.identifySubscriber(externalId:email:attributes:)Hober.identifySubscriber(externalId, email, attributes, callback)