Enode Developers

Link SDKs in React Native

In this guide we will walk you through the steps to integrate the Link SDKs in a React Native context.

You can integrate Enode’s Link SDKs for iOS and Android into your React Native app by making them accessible through the Native Modules system.

Using this guide, you will:

  1. Ensure that you have the prerequisites to get started
  2. Expose the Link SDKs in iOS and/or Android as native modules
  3. Import the exposed native modules into your React Native app

Copy linkPrerequisites

  • An existing React Native application
  • Existing iOS or Android projects within your React Native app
  • A server that calls Link UserAPI with API version 2024-01-01. You should be able to generate a linkToken to pass back to your React Native client

Copy linkImplement the iOS native module

Copy linkSet up your Xcode project

Open the iOS project in your React Native app (found under /ios/*.xcworkspace) in Xcode. Follow the Set up your Xcode project steps from our iOS SDK guide to add LinkKit by extracting the SDK archive, importing the framework, and configuring Bluetooth access.

Copy linkSet up a native module

Copy linkCreate the Swift implementation file

In your main iOS project folder (next to AppDelegate), create a file called LinkUIModule.swift.

Copy linkCreate a bridging header

At this point, Xcode may prompt you to create a bridging header since you are about to mix Swift and Objective-C (it also may already exist). If it does not exist, manually create one called YourProjectName-Bridging-Header.h in that same project folder. Ensure the file contains the following:

// YourProjectName-Bridging-Header.h
#import "React/RCTBridgeModule.h"

Copy linkImplement the SDK in Swift

Back in LinkUIModule.swift, add your implementation:

The bulk of this is the reference implementation from the iOS Link SDK guide alongside some React Native specific details:

//  LinkUIModule.swift

import Foundation
import LinkKit

@objc(LinkUIModule)
class LinkUIModule: NSObject {
  private var handler: Handler?

  @objc
  static func requiresMainQueueSetup() -> Bool {
    return true
  }

  @objc
  func show(_ token: String, callback: @escaping RCTResponseSenderBlock) {
    let vc = RCTPresentedViewController()
    self.handler = Handler(linkToken: token) { (code: LinkResultCode, errMsg: String?) in
      callback([ code.rawValue, errMsg as Any ])
    }

    self.handler?.present(from: vc!)
  }
}
  • requiresMainQueueSetup implemented to return true to tell React Native to initialize the module on the main thread
  • Adding and invoking a callback in the handler's completion handler, whose argument will be available in JavaScript
  • Presenting LinkKit UI from the instance of RCTPresentedViewController()

Copy linkExpose your Swift implementation to React Native

Create a new file called LinkUIModule.m and add the following. This makes your Swift implementation available in JavaScript and tells React Native to use the main queue when calling your method since it involves UI operations.

//  LinkUIModule.m

#import "React/RCTBridgeModule.h"
@interface RCT_EXTERN_MODULE(LinkUIModule, NSObject)
- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}

RCT_EXTERN_METHOD(show:(NSString *)token callback:(RCTResponseSenderBlock)callback)
@end

Copy linkImplement the Android native module

Copy linkImport the SDK to your project

Open the Android project in your React Native app (found under /android), ideally in Android Studio. Follow our Android SDK guide to include the SDK in your app’s build.gradle. (In a React Native app, you should add the dependency in /android/app/build.gradle.)

Copy linkConfigure your project

Copy linkSDK versions

If necessary, you may have to increase your compile SDK version and your minimum SDK version. For example, in /android/gradle.properties set:

android.compileSdkVersion=34
android.minSdkVersion=24

Copy linkKotlin + Java

If your app has a mix of Java and Kotlin, you’ll also need to configure your project to support both. Add this to your /android/app/build.gradle (after you declare your dependencies):

apply plugin: "kotlin-android"

Then add this to you /android/build.gradle's:

dependencies {
  ...
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}

Copy linkStyles

The Link SDK makes use of a few style attributes. Follow the guide for our Android SDK to ensure that you are defining and applying your styles to avoid theming errors.

Copy linkSet up a native module

Copy linkCreate the Kotlin implementation file

Create a new Link UI module file as a Kotlin class within your Android project under /android/app/src/main/java/com/your-app-name/LinkUIModule.kt. This contains the main native implementation of our Link SDK. Add the following code, which adapts the sample from the main Android SDK guide for React Native:

package com.your-app-name

import android.content.Intent
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 io.enode.link.LinkKit

const val LINK_UI_REQUEST = 99

class LinkUIModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
  private var linkResultCallback: Callback? = null;

  private val activityEventListener =
    object : BaseActivityEventListener() {
        override fun onActivityResult(
            activity: Activity?,
            requestCode: Int,
            resultCode: Int,
            intent: Intent?
        ) {
            if (requestCode == LINK_UI_REQUEST) {
                if (resultCode == Activity.RESULT_OK) {
                    linkResultCallback?.invoke("success")
                } else {
                    val errorCode = intent?.getStringExtra(LinkKit.ERROR_CODE)
                    val errorDetails = intent?.getStringExtra(LinkKit.ERROR_DETAILS)
                    linkResultCallback?.invoke(errorCode, errorDetails)
                }
                linkResultCallback = null
            }
        }
    }

    override fun getName() = "LinkUIModule"

    init {
      reactContext.addActivityEventListener(activityEventListener)
    }

    @ReactMethod
    fun show(token: String, callback: Callback) {
      val activity = currentActivity

      if (activity == null) {
          callback.invoke("implementationError", "Unable to get current activity")
          return
      }

      try {
        linkResultCallback = callback
        val intent = Intent(activity, LinkKit::class.java)
        intent.putExtra(LinkKit.INTENT_LINK_TOKEN, token);
        activity.startActivityForResult(intent, LINK_UI_REQUEST, null)
      }  catch (e: RuntimeException) {
        callback.invoke("implementationError", "RuntimeException whilst launching LinkKit")
      }
    }
}

Copy linkExpose your Kotlin implementation to React Native

You need to register your module as a ReactPackage in order to use it in JavaScript. Create a separate Kotlin class under /android/app/src/main/java/com/your-app-name/LinkUIPackage.kt and add the following to it:

package com.your-app-name

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class LinkUIPackage : ReactPackage {

  override fun createViewManagers(
    reactContext: ReactApplicationContext
  ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

  override fun createNativeModules(
    reactContext: ReactApplicationContext
  ): MutableList<NativeModule> = listOf(LinkUIModule(reactContext)).toMutableList()
}

Next, add this package to the list exposed by React. In your project’s /android/app/src/main/java/com/your-app-name/MainApplication.[kt|java] file, find where getPackages() is implemented and be sure to add the Link UI package to it. It should resemble the following (for more information, see React Native docs):

@Override
protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  packages.add(new LinkUIPackage());
  return packages;
}

Copy linkUse the SDKs in React Native

Now that you have exposed the iOS and Android Link SDKs as native modules, you can use them in React Native.

First, create a link session on your server and make sure the resulting linkToken is available in your React Native app. (For Android, remember to supply an app deeplink as your redirect URI.)

Next, decide where you want to show Link UI and import NativeModules there:

import { NativeModules } from "react-native";

NativeModules.LinkUIModule will call native modules you just set up.

The following is a complete example of a LinkUI React component. If you followed this guide and implemented the same module interface across iOS and Android, the following implementation will be universal across both platforms.

import { Button, View, NativeModules } from "react-native";

export default function LinkUI({ token }) {
  const linkUI = NativeModules.LinkUIModule;
  return (
    <View>
      <Button
        title="Connect your EV"
        onPress={() => {
          linkUI.show(token, (code, errMsg) => {
            switch (code) {
              case "success":
                // handle success
                console.log("success!");
                break;

              case "cancelledByUser":
                // handle cancellation
                console.log("cancelled!");
                break;
              default:
                // handle other error kinds
                console.log(
                  `something went wrong: code=${code}, errMsg=${
                    errMsg ?? "[n/a]"
                  }`
                );
                break;
            }
          });
        }}
      />
    </View>
  );
}

The callback takes two arguments:

  1. code: one of string result codes:

    • success: linking succeded
    • missingLinkToken: required token parameter was not sent
    • malformedLinkToken: the linkToken supplied was malformed
    • dismissedViaDismissFunction: Link UI was dismissed by you (e.g., by calling dismiss() function on Handler instance on iOS)
    • cancelledByUser: Link UI was dismissed by the user (e.g., tapping "Close")
    • backendError: Enode was unable to complete linking due to a service error
    • earlyExitRequestedFromFrontend: Link UI itself initiated the closing of the modal
  2. errMsg (optional): human-readable message string that comes with malformedLinkToken, backendError, earlyExitRequestedFromFrontend codes

Copy linkTroubleshooting

  • If you are using Expo with eas build and our SwiftPM package, you should ensure that you are running your builds on a server image that runs Xcode 15+. For example, you can add this to your iOS configuration in eas.json:

    {
      "build": {
        ...
        "development": {
          "ios": {
            ...
            "image": "macos-ventura-13.6-xcode-15.2"
          }
        },
      },
    }
    
  • When launching LinkSDK on the Android emulator you may run into the issue Unable to load script. Make sure you are either running a Metro server or that your bundle is packaged correctly for release or alternatively the issue CLEARTEXT communication to 10.0.2.2 not permitted by network security policy. This issue happens because Link SDK has a limitation over cleartext communication which blocks the communication between the emulator and your machine. To work around:

    1. Create a new file network_security_config.xml in the android/app/src/main/res/xml/ directory.

    2. Add the following contents in the XML file:

      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
          <domain-config cleartextTrafficPermitted="true">
              <domain includeSubdomains="true">10.0.2.2</domain>
          </domain-config>
      </network-security-config>
      
    3. In AndroidManifest.xml, reference this new configuration as follows:

      <application
          android:networkSecurityConfig="@xml/network_security_config"
          ...>
      
    4. For security reasons, you should not enable cleartext communication in your release builds; only for debug builds.

Copy linkOther ways to integrate

Link SDK for iOS

Integrating with the Link SDK for iOS

Link SDK for Android

Integrating with the Link SDK for Android

Was this article helpful?