Integrate native Android & iOS SDK’s in a react-native app (bridging)

How to create a "bridge" between a React Native app and a native iOS/Android SDK

Integrate native Android & iOS SDK’s in a react-native app (bridging)

Sometimes while developing apps with react-native we find ourselves in a situation where we don’t have an npm package for react-native but the SDKs exists for native Android and iOS apps. In such cases, we need to write native modules for Android/iOS and bridge it to call it from JavaScript.

The Bridge allows communication between JavaScript & Native Modules

For this tutorial, we will integrate SatisMeter native SDK’s for iOS and Android and use it from JS side of the app.

Let’s start with creating a react-native project.

npx react-native init rn_bridge_satismeter

First, we will integrate iOS SDK

You can refer to the documentation for iOS SDK integration here.

Step 1.
Open the project inn XCode.

cd rn_bridge_satismeter
cd ios
double click 'rn_bridge_satismeter.xcworkspace' file to open it on xcode

Step 2.
Let’s create a Cocoa Touch class RCTSatisMeter on xcode.

XCode Project setup

This will create 2 files inside:
RCTSatisMeter.h - header file.
RCTSatisMeter.m - implementation file.

Step 3.
Add the pod entry to your podfile

pod 'SatisMeter'

Step 4.
Update RCTSatisMeter.h file to look like this:

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

NS_ASSUME_NONNULL_BEGIN

@interface RCTSatisMeter : NSObject <RCTBridgeModule>

@end

NS_ASSUME_NONNULL_END
RCTSatisMeter.h

Step 5.
Update RCTSatisMeter.m file to look like this:

#import "RCTSatisMeter.h"
#import "SatisMeter/SatisMeter.h"

@implementation RCTSatisMeter

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

RCT_EXPORT_MODULE();

RCT_REMAP_METHOD(hook, 
    userId:(nonnull NSString *)userId 
    writeKey:(nonnull NSString *)writeKey
    traits:(NSDictionary *)traits
    callback:(RCTResponseSenderBlock)callback)
{
    callback(@[[NSString stringWithFormat: @"SatisMeter installation successful... userId: %@ writeKey: %@", userId, writeKey]]);
    
    [[SatisMeter sharedInstance] identifyUserWithUserId: userId
                                               writeKey: writeKey
                                    andTraitsDictionary: traits];

}


@end
RCTSatisMeter.m
  • RCT_EXPORT_MODULE macro, which exports and registers the native module class with React Native.
  • RCT_REMAP_METHOD() to specify the JavaScript method's name.


Step 6.

cd ios
pod install

🔆 And that's all that needs to be for iOS.

Let’s call it from JavaScript.

We will call SatisMeter.hook() from App.js.
Update your App.js

import React, {useEffect} from 'react';
import {View, Text, NativeModules} from 'react-native';

const App = () => {
  useEffect(() => {
    NativeModules.SatisMeter.hook(
      <userId>, //user id
      <writeKey>, // satismeter write key
      { // extra payload
        name,
        company,
      },
      (message) => {
        console.log(message, 'message from hook');
      },
    );
  }, []);
  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Text>SatisMeter Integration</Text>
    </View>
  );
};

export default App;
App.js

NativeModules.SatisMeter.hook (userId, writeKey, traits, callback)

  • userId - unique id of user
  • writeKey - write key of the SatisMeter App
  • traits - extra data that needs to be sent with user review
  • callback - a callback is triggered on successful connection of the app with SatisMeter.

And run the app on iOS simulator,

npx react-native run-ios
iOS Simulator

🎉 We have successfully integrated the SDK on our iOS App :)`

Let’s integrate the SDK on Android now,

You can refer to the documentation for Android SDK integration here.

Step 1.
Create java class SatisMeterModule.java & SatisMeterPackage.java

Setting up the project in Android Studio

Step 2.
Update SatisMeterModule.java to look like this:

package com.rn_bridge_satismeter;


import android.app.Activity;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
import com.satismeter.SatisMeter;

import java.util.HashMap;

public class SatisMeterModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

    public SatisMeterModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "SatisMeter";
    }

    @ReactMethod
    public void hook(String userId, String writeKey, ReadableMap traits, Callback callback) {
        final Activity activity = getCurrentActivity();
        callback.invoke("SatisMeter installation successful... userId: " + userId + " writeKey: " + writeKey);

        HashMap<String, Object> traitsMap = new HashMap();
        if (traits != null) {
            ReadableMapKeySetIterator iterator = traits.keySetIterator();
            while (iterator.hasNextKey()) {
                String key = iterator.nextKey();
                ReadableType type = traits.getType(key);
                if (type == ReadableType.String) {
                    traitsMap.put((String) key, (String) traits.getString(key));
                }
            }
        }

        SatisMeter.identify(activity, writeKey, userId, traitsMap);
    }
}
SatisMeterModule.java
  • getName() to specify the native module’s name.
  • All native module methods meant to be invoked from JavaScript must be annotated with @ReactMethod.

Step 3.
Update SatisMeterPackage.java to look like this:

package com.rn_bridge_satismeter;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;

public class SatisMeterPackage implements ReactPackage {
    @Override
    public List<NativeModule>  createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(new SatisMeterModule(reactContext));
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
SatisMeterPackage.java
  • This is used to register SatismeterModule with react-native.
  • React Native invokes the method createNativeModules() on a ReactPackage in order to get the list of native modules to register.

Step 4.
Add package to MainApplication.java,

 @Override
 protected List<ReactPackage> getPackages() {
     @SuppressWarnings("UnnecessaryLocalVariable")
     List<ReactPackage> packages = newPackageList(this).getPackages();

     packages.add(new SatisMeterPackage()); //<----- Add this line
     return packages;
}
MainApplication.java
  • To register Satismeter module we also need to add SatismeterPackage to the list of packages returned in ReactNativeHost's getPackages() method.

Step 5.
Add SatisMeter SDK under dependencies in app/build.gradle,

dependencies {
    ...
    // Satismeter
    implementation 'com.satismeter:satismeter:1.5.1'
    ...
}
app/build.gradle

We don’t need to do any changes on App.js, everything will work just fine.

And run the app on Android emulator,

npx react-native run-android

🎉 We have successfully integrated the SDK on our Android App too :)


Thanks for reading.
I hope you enjoyed this article and it helped you in some way.

You can find the code for this tutorial in this repo.