How to Build React Native Wrappers for Native SDKs

How to Build React Native Wrappers for Native SDKs

React native is an open-source framework for cross-platform mobile development that lets us build mobile apps using Javascript. It works by providing a bridge that facilitates the communication between Javascript and native modules. In this post, we discuss How to Build React Native Wrappers for Native SDKs

Create the library

The easiest way to get started on writing a new library is to use react-native-create-library. It creates a boilerplate with everything you need to get you started on writing a RN library. Install it globally using:

npm install -g react-native-create-library

react-native-create-library --package-identifier com.mcro.rnonfido --platforms android,ios onfido-sdk

We opt in only for android and ios since not only there's no windows phone SDK, but it is also pointless since Microsoft announced it's ending support for it. Next, we need to do a bit of renaming. Running the above command produces the following:

This is image title

The reason we named the library onfido-sdk and not react-native-onfido-sdk is because react-native-create-library generates all files using RN prefix and it would've been redundant to have files named such as RNReactNativeOnfidoSdk. To rename our directory, we just need to manually run:

mv onfido-sdk react-native-onfido-sdk

We're all set now, time to hook up the SDKs. Before we go into details, let's recap the challenges that we're trying to tackle:

1. Integrate native SDKs in out wrapper library

2. Expose methods from Native to Javascript side

3. Extend the functionality of these SDKs. Because we need a separate screen for having custom document types, we need to implement native screens for each platform. We could've implemented this screen in Javascript, but in that case the developer would be responsible to render it from React Native depending on the navigation library used and manually handle all selections.

4. Combine the native screens (newly added ones and those coming from Onfido SDK) with React Native

iOS

There are two ways of including a library in a project:

  1. manually, by copying the sdk in the project
  2. using a dependency manager

Advantages of the second option are obvious, but we won't go into details in this article. Onfido SDK is available through Cocoapods, so we'll leverage the capabilities of .podspec file, which react-native-create-library created for us, to specify the Onfido dependency. We can update this file to load the details in a nicer fashion, reading them from our package.json:

require 'json'

package = JSON.parse(File.read(File.join(__dir__, 'package.json')))

Pod::Spec.new do |s|
  s.name           = 'react-native-onfido-sdk'
  s.version        = package['version']
  s.summary        = package['description']
  s.description    = package['description']
  s.license        = package['license']
  s.author         = package['author']
  s.homepage       = package['homepage']
  s.source         = ...

  s.requires_arc   = true
  s.platform       = :ios, '11.0'

  s.preserve_paths = 'LICENSE', 'README.md', 'package.json', 'index.js'
  s.source_files   = './*.{h,m}'

  s.dependency 'React'
  s.dependency 'Onfido'
end

At this point, we're pretty much set with our dependencies, we can start writing native modules for exposing what we need to Javascript. The header and the implementation are already created for us (RNOnfidoSdk.h and RNOnfidoSdk.m). In our case, we needed to expose a method that would present the Onfido flow, so we implemented the following RCT_EXPORT_METHOD:

RCT_EXPORT_METHOD(startSDK:(id)json successCallback:(RCTResponseSenderBlock)successCallback errorCallback:(RCTResponseErrorBlock)errorCallback) {
    RNOnfidoSdk *sdk = [[RNOnfidoSdk alloc] initWithParams:json successCallback:successCallback errorCallback:errorCallback];
    [sdk run];
}

After we're done with the implementation of the exposed methods and our custom document types view controller, let's see what options we have for presenting native view controllers in the React Native app. On iOS there are two ways for navigating to a new screen: modally or by pushing it in a UINavigationController. If we look into AppDelegate.m of any React Native app, we'll see that we have a UIViewController set as root for the window object. By default, all view controllers have the ability to present some other view controller, but we can push a view controller only in the context of a UINavigationController. With that being said, we're kind of constrained to present the entire navigation stack to the Onfido flow, unless we make some changes to the app that uses our library. We can update AppDelegate.m and change the rootViewController to be a UINavigationController:

UIViewController *rootViewController = [UIViewController new];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navigationController;

Of course this will add a navigation bar in the app, but we can easily hide it.

This way, we can update our exposed method that launches the SDK to have a new parameter, that will be iOS only, for letting the users of the library choose whether they want to present the flow as a modal stack, or push it. We can add a helper method in our library for launching the flow like this:

- (void) displayOnfidoFlow: (UIViewController *) viewController {
    // Get view controller on which to present the flow
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    self->_rootViewController = (UINavigationController *)window.rootViewController;

    NSDictionary *dictionary = [RCTConvert NSDictionary:self->_params];
    BOOL presentModally = dictionary[@"presentModally"];
    if (presentModally) {
        [self->_rootViewController presentViewController:viewController animated:true completion:nil];
    } else {
        [(UINavigationController *) self->_rootViewController pushViewController:viewController animated:true];
    }
}

Another challenge that we had was to bundle the assets in the library. In order to do this you need to create a new resource bundle by adding a new bundle. We named it Resources, you can name it anyway you like:

This is image title

Next, set the Base SDK iOS for this bundle, since we'll build our library for iOS:

This is image title

Next step is to add the new bundle as a target dependency for your initial target:

This is image title

Now if you want to add some .xcassets or .xib files you just need to make sure they have the bundle as target dependency.

The last step in bundling the assets is to update the same .podspec file with the path for this bundle:

require 'json'

package = JSON.parse(File.read(File.join(__dir__, 'package.json')))

Pod::Spec.new do |s|
  s.name           = 'react-native-onfido-sdk'
  s.version        = package['version']
  s.summary        = package['description']
  s.description    = package['description']
  s.license        = package['license']
  s.author         = package['author']
  s.homepage       = package['homepage']
  s.source         = ...

  s.requires_arc   = true
  s.platform       = :ios, '11.0'

  s.preserve_paths = 'LICENSE', 'README.md', 'package.json', 'index.js'
  s.source_files   = 'ios/*.{h,m}'

  # ADD THIS
  s.resource_bundles = {
    'Resources' => ['./*.xcassets']
  }

  s.dependency 'React'
  s.dependency 'Onfido'
end

Now these assets can be accesed both inside and ourside of the library like this:

- (UIImage *) getImageNamed: (NSString *)imageName {
    NSString *resourcePath = [NSBundle.mainBundle pathForResource:@"Resources" ofType:@"bundle"];
    NSBundle *resourcesBundle = [NSBundle bundleWithPath:resourcePath];
    return [UIImage imageNamed:imageName inBundle:resourcesBundle compatibleWithTraitCollection:nil];
}

In this case imageName can be any image that we have in our assets catalog.

Android

While for iOS we used Cocoapods for getting the Onfido SDK in our library, we can do the same for Android using Gradle Dependency Manager. Open android/build.gradle and add the following in dependencies:

dependencies {
    implementation 'com.facebook.react:react-native:+'

    # ADD THIS
    implementation 'com.onfido.sdk.capture:onfido-capture-sdk:+'
}

If we're running gradle sync now, it will throw an error and that is because com.onfido.sdk.capture:onfido-capture-sdk has not been approved yet to be included in JCenter; we need to instruct Gradle to search for the package on Bintray. In the same file, update repositories configuration:

repositories {
  ...
  maven {
    url  "https://dl.bintray.com/onfido/maven"
  }
}

We've managed to integrate the SDK in our library, next step is to write the modules that will be accessed over the bridge.

When it comes to extend the SDK functionality with our custom document types screen, things are less complicated on Android than on iOS. For our particular case, we just need to create a new activity and depending on the parameters that are passed in from Javascript side, we'll know which activity to start.

Let's take a look over our exposed method:

@ReactMethod
  public void startSDK(ReadableMap params, Callback successCallback, Callback errorCallback) {
    Activity currentActivity = getCurrentActivity();
    mSuccessCallback = successCallback;
    mErrorCallback = errorCallback;
    mParams = params;

    if (currentActivity == null) {
      mErrorCallback.invoke(E_ACTIVITY_DOES_NOT_EXIST);
      return;
    }
    HashMap paramsMap = params.toHashMap();

    if (this.isCustomFlow(paramsMap)) { // if user wants custom document type checks
      Intent intent = new Intent(currentActivity, OnfidoCustomDocumentTypesActivity.class);
      int[] documentTypes = this.getDocumentTypes(paramsMap);
      intent.putExtra("documentTypes", documentTypes);
      currentActivity.startActivityForResult(intent, REQUEST_CODE_DOCUMENT_TYPE); // start Onfido SDK in onActivityResult
    } else {
      OnfidoConfig onfidoConfig = this.getOnfidoConfig(paramsMap);
      client.startActivityForResult(currentActivity, REQUEST_CODE_ONFIDO, onfidoConfig);
    }
  }

Final thoughts

Hopefully, this will give you a starting point on how to create a React Native wrapper for existing native SDKs. We haven't covered how to actually write and expose methods over the bridge, since that is very well covered in React Native documentation, but instead we focused on integrating the SDKs in our library and extending the functionality to our needs.

You can see this example fully implemented on our Github, as well as an example that you can check as a demo: https://github.com/MCROEngineering/react-native-onfido-sdk

Thank you!

react react-native javascript SDKs

What's new in Bootstrap 5 and when Bootstrap 5 release date?

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Random Password Generator Online

HTML Color Picker online | HEX Color Picker | RGB Color Picker

Build a simple React Native Pokemon app with React-Navigation

As we start learning new technologies we want to start building something or work on a simple project to get a better understanding of the technology.

Getting Started with React Native in 2020: Build Your First App

Getting Started with React Native in 2020: Build Your First App. How To Code Your First Mobile App Using React Native. Learn how to build your first React Native app with important basic concepts. Learn the basics of React Native, a JavaScript Native Mobile App compiler. We look into components, events, props and passing them and more.

React Native App Development Company in New York

Hire top react native app development company in New York to build and develop custom react native mobile apps for Android & iOS with the latest features.

React Native App Development Company in New York

Hire top react native app development company in New York to build and develop custom react native mobile apps for Android & iOS with the latest features.

Learn how to use the React Native Navigation Library

In this tutorial, you'll learn how to use the React Native Navigation library. Learn how to set up React Native Navigation and use the stack and tab navigation. Learn how to load icons from React Native Vector Icons instead of using image icons.