ReactNative - Android

This guide will help you integrate the ReadyRemitSDK into your React Native developed Android projects.

The SDK is compatible with Android versions 9 to 14.

Step 1 - Prepare your project

  1. Make sure that your app's minimum Android API level is 26 or higher. This can be found in the build.gradle file. Depending on your setup this might be defined in the build.gradle file at the Module level or at the Project level.
android {
    ..
		compileSdkVersion 33
    defaultConfig {
        ..
        minSdkVersion 26
      	targetSdkVersion 33
    }
  
   compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }

    composeOptions {
        kotlinCompilerExtensionVersion '1.3.2'
    }
  
  ..
}
  1. Add classpath dependencies to the build.gradle at the Project level
buildscript {
  ..
  ext {
    ..
    kotlinVersion = "1.7.20"
 }
  
 dependencies {
   ..
   classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
 }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter()
        maven { url 'https://maven.google.com' }
        maven { url "https://jitpack.io" }
    }
}
  1. Add the following apply statements to the top of your build.gradle file at the Module level:
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'

Step 2 - Install the ReadyRemit SDK

  1. Download the readyremit.aar from the Releases page on Github
  2. Add the .aar file to the folder your_app_root/app/libs
  3. Add the path as a dependency to your app's build.gradle file a the Module level:
dependencies {
  ..
  // ReadyRemit SDK
	implementation files('libs/readyremit.aar')

}
  1. Add missing third-party dependencies to your app's build.gradle file at the Module level:
dependencies {
    ..
		// Core
    implementation "androidx.core:core-ktx:1.10.0"

    // UI
    implementation "androidx.appcompat:appcompat:1.6.1"
    implementation "com.google.android.material:material:1.9.0"

    // Navigation
    implementation "androidx.navigation:navigation-fragment-ktx:2.6.0"
    implementation "androidx.navigation:navigation-ui-ktx:2.6.0"
    implementation "androidx.navigation:navigation-compose:2.6.0"

    // Compose
    implementation platform("androidx.compose:compose-bom:2023.06.01")
    implementation "androidx.compose.compiler:compiler:1.3.2"
    implementation "androidx.compose.runtime:runtime:1.3.2"
    implementation "androidx.compose.material:material:1.3.2"
    implementation "androidx.compose.ui:ui-tooling"
    implementation "androidx.compose.ui:ui-tooling-preview"
    implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0"

  	// PDFViewer
    implementation 'com.github.DImuthuUpe:AndroidPdfViewer:3.1.0-beta.1'

    // Kotlin
    implementation platform("org.jetbrains.kotlin:kotlin-bom:1.8.22")
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android"

    // OkHttp
    implementation "com.squareup.okhttp3:okhttp:4.11.0"
    implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"

    // Profiler
    implementation "com.localebro:okhttpprofiler:1.0.8"

    // Retrofit
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation "com.squareup.retrofit2:converter-moshi:2.9.0"

    // Moshi
    implementation "com.squareup.moshi:moshi:1.14.0"
    implementation "com.squareup.moshi:moshi-adapters:1.14.0"
    kapt "com.squareup.moshi:moshi-kotlin-codegen:1.14.0"

    // Dagger
    implementation "com.google.dagger:dagger:2.50"
    implementation "com.google.dagger:dagger-android:2.50"
    implementation "com.google.dagger:dagger-android-support:2.50"
    kapt "com.google.dagger:dagger-compiler:2.50"
    kapt "com.google.dagger:dagger-android-processor:2.50"

    // Mixpanel
    implementation "com.mixpanel.android:mixpanel-android:7.4.1"

    // Launch Darkly
    implementation "com.launchdarkly:launchdarkly-android-client-sdk:5.0.0"
 	  implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
}
  1. Set view binding to true in build features to your app's build.gradle file at the Module level:
android {
    ..
    buildFeatures {
        dataBinding true
        viewBinding true
     	  buildConfig true
        compose true
    }
}

Step 3 - Install required Visa sensory branding libraries

  1. Download visa-sensory-branding-sdk from Github
  2. Add the .aar file to the folder your_app_root/app/libs
  3. Add the path as a dependency to your app's build.gradle file a the Module level:
dependencies {
  ..
 	implementation files ('libs/visa-sensory-branding-2.0.aar') 
}

Step 4 - Create the React Native Bridge and Module

In React Native, a module facilitates communication and interaction between your React Native code and your native modules (Refer to the React Native documentation for more details).

In the root of your Android project in Android Studio, create the following file:

🚧

Remember

Remember to replace com.readyremit_demo with your actual package name.

📘

Copy/Paste

The ReadyRemitModule and ReadyRemitPackage code should be added to your project without modification.

package com.readyremit_demo // Put your package name here

import com.brightwell.readyremit.sdk.*
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.brightwell.readyremit.sdk.environment.Environment
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
import com.google.gson.Gson

class ReadyRemitModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    private val REQUEST_CODE = 10
    private val READYREMIT_AUTH_TOKEN_REQUESTED = "READYREMIT_AUTH_TOKEN_REQUESTED"
    private val READYREMIT_TRANSFER_SUBMITTED = "READYREMIT_TRANSFER_SUBMITTED"
    private val READYREMIT_SDK_CLOSE = "SDK_CLOSED"
  	private val READYREMIT_SDK_LAUNCHED = "SDK_LAUNCHED"
    private lateinit var _onAuthCallback: ReadyRemitAuthCallback
    private lateinit var _onTransferCallback: ReadyRemitTransferCallback

    override fun getName(): String {
        return "ReadyRemitModule"
    }

    @ReactMethod
        fun launch(environment: String, language: String = "en", style: ReadableMap? = null) {
      
        ReadyRemit.initialize(
            ReadyRemit.Config.Builder(currentActivity!!.application)
                                .useEnvironment(if(environment == "PRODUCTION") Environment.PRODUCTION else Environment.SANDBOX)
                .useAuthProvider { callback -> requestReadyRemitAccessToken(callback) }
                .useTransferSubmitProvider  { request, callback -> submitReadyRemitTransfer(request, callback) }
                .useLanguage(language)
                .build()
        )

				/**
         * Initiates the remittance process using ReadyRemit.
         *
         * @param1 activity -  The current activity of the application.
         * @param2 requestCode - The request code that will be returned in the `onActivityResult` function this can be a int.
         * @param3 theme - The theme to be applied when initiating the SDK, this should be a id (i.e. R.styles.ReadyRemit) or null to use the SDK default one.
         * @param4 languageCode -  The language code to be used on SDK, in locale format (e.g., "en_US", "es_MX").
         */
        ReadyRemit.remitFrom(currentActivity!!, REQUEST_CODE, null, language)
        
        ReadyRemit.setEventListener { event ->
            when (event) {
                SDKClosed -> {
                    reactApplicationContext
                        .getJSModule(RCTDeviceEventEmitter::class.java)
                        .emit(READYREMIT_SDK_CLOSE, null)
                }
                SDKLaunched -> {
                	reactApplicationContext
                        .getJSModule(RCTDeviceEventEmitter::class.java)
                        .emit(READYREMIT_SDK_LAUNCHED, null)
                }
            }
        }
    }

    @ReactMethod
    fun setAuthToken(token: String, errorAuthCode: String?) {
        if (token != "") {
            _onAuthCallback.onAuthSucceeded(ReadyRemitAuth(token, ""))
        } else {
            _onAuthCallback.onAuthFailed()
        }
    }

    private fun requestReadyRemitAccessToken(callback: ReadyRemitAuthCallback) {
			_onAuthCallback = callback
    	reactApplicationContext
				.getJSModule(RCTDeviceEventEmitter::class.java)
				.emit(READYREMIT_AUTH_TOKEN_REQUESTED, null)
    }

    @ReactMethod
    fun setTransferId(transferId: String? = "", errorCode: String? = "", errorMessage: String? = "") {
        if (transferId != "" && transferId != null) {
            _onTransferCallback.onTransferSucceeded(transferId)
        } else if (errorCode != null) {
            val error = ReadyRemitError(errorCode, errorMessage ?: "", errorMessage ?: "")
            _onTransferCallback.onTransferFailed(error)
        }
    }

    private suspend fun submitReadyRemitTransfer(
        request: ReadyRemitTransferRequest,
        callback: ReadyRemitTransferCallback
    ) {
            _onTransferCallback = callback

          var jsonRequest = Gson().toJson(request)

            reactApplicationContext
                .getJSModule(RCTDeviceEventEmitter::class.java)
                .emit(READYREMIT_TRANSFER_SUBMITTED, jsonRequest)
    }
}

To add the new module to your native application, you need to create a package with this new module.

Create the following file:

package com.readyremit_demo // Put your package name here

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

class ReadyRemitPackage : ReactPackage {
    override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
        return listOf(ReadyRemitModule(reactContext))
    }

    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
        return emptyList()
    }
}

To have access from your React Native app to your new ReadyRemitModule, you need to add the package in the main application:

@Override
protected List<ReactPackage> getPackages() {
  ..
  packages.add(new ReadyRemitPackage());
}

(Optional) Closing ReadyRemitSDK

If you wish to gracefully close the ReadyRemitSDK at any point in your code, please:

  1. Add this code to your ReadyRemitModule.kt
@ReactMethod
fun close() {
   ReadyRemit.close()
}
  1. Call this function in your React Native project:
ReadyRemitModule.close();

(Optional) Inactivity Detector

If you prefer to automatically close the ReadyRemitSDK when your users are inactive, you can add the following snippet into your ReadyRemitModule.kt

import android.os.Bundle  
import androidx.appcompat.app.AppCompatActivity  
import com.yourcompany.ReadyRemitSDK

class ReadyRemitModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    @ReactMethod
     fun launch(environment: String, language: String = "en", style: ReadableMap? = null) {
        ReadyRemit.initialize(
            ReadyRemit.Config.Builder(currentActivity!!.application)
                                .useEnvironment(if(environment == "PRODUCTION") Environment.PRODUCTION else Environment.SANDBOX)
                .useAuthProvider { callback -> requestReadyRemitAccessToken(callback) }
                .useTransferSubmitProvider  { request, callback -> submitReadyRemitTransfer(request, callback) }
                .useLanguage(language)
                .build()
        )

				 // Launch ReadyRemitSDK
        ReadyRemit.remitFrom(currentActivity!!, REQUEST_CODE, null, language)
        // Set inactivity timeout (e.g., 60 seconds)
    		ReadyRemit.close(60)
    }
}

(Optional) Style the ReadyRemit SDK

  1. In the root of your Android project create a new "Values Resource File" (ex: theme_readyremit.xml).
  2. Use the following code as a template and fill in any colors you'd like to override:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Theme.ReadyRemit" parent="Theme.ReadyRemit.Light">
        <item name="rrmBackgroundColor">#FEE598</item>
        <item name="rrmForegroundColor">#B7D7A9</item>
        <item name="rrmButtonTextColor">#D5A6BD</item>
        <item name="rrmButtonColor">#9801FF</item>
        <item name="rrmDangerColor">#44808E</item>
        <item name="rrmDangerLightColor">#6FA8DC</item>
        <item name="rrmDividerColor">#660000</item>
        <item name="rrmIconColor">#FE0100</item>
        <item name="rrmInputLineColor">#008761</item>
        <item name="rrmPrimaryColor">#9801FF</item>
        <item name="rrmPrimaryLightColor">#9801FF</item>
        <item name="rrmSuccessColor">#B55F07</item>
        <item name="rrmTextColor">#0100FE</item>
        <item name="rrmTextSecondaryColor">#00FEFE</item>
    </style>
</resources>
  1. Navigate to the project's resource folder. The path should be something like: MyProject/app/src/main/res
  2. Ensure that there is a folder named "values-night". If this folder doesn't exist, create it.
  3. Inside the "values-night" folder, create an XML file with the exact same name as the original theme used for the light mode.
  4. Open the project in Android Studio. In the res/values directory, you will find a directory for these themes. There will be one for light mode and one for dark mode (indicated by "night" tag).
  5. In the dark mode theme file, add the following structure:

🚧

Important

• Make sure to set the parent attribute to Theme.ReadyRemit.Dark.

• If you're only using the light mode in your application, you can copy the same colors from the theme used for the light mode. If you're using the dark mode, make the necessary color modifications here.

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
  <style name="Theme.ReadyRemit" parent="Theme.ReadyRemit.Dark"> 
    <item name="rrmBackgroundColor">#111111</item> 
    <item name="rrmForegroundColor">#1F1F1F</item> 
    <item name="rrmButtonTextColor">#FFFFFF</item>
    <item name="rrmButtonColor">#558CF4</item>
    <item name="rrmDangerColor">#AA220F</item> 
    <item name="rrmDangerLightColor">#201311</item> 
    <item name="rrmDividerColor">#313131</item> 
    <item name="rrmIconColor">#7E7E7E</item> 
    <item name="rrmInputLineColor">#505050</item> 
    <item name="rrmPrimaryColor">#558CF4</item> 
    <item name="rrmPrimaryLightColor">#83ACF7</item> 
    <item name="rrmSuccessColor">#008761</item> 
    <item name="rrmTextColor">#E3E3E3</item> 
    <item name="rrmTextSecondaryColor">#B0B0B0</item>
    <item name="rrmButtonColor">#558CF4</item>
  </style>
</resources> 
  1. Update the launch function inside ReadyRemitModule.kt to use the new theme.
ReadyRemit.remitFrom(currentActivity!!, REQUEST_CODE, R.style.ReadyRemit, language)

(For KYC users only) Implement KYC

If you wish to use the ReadyRemitSDK with the KYC feature enabled, you will need to ask your users for Camera permission, to do that, follow this guide

  1. Enable camera permission into your Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
  package="com.your.package">
    ..
   <uses-feature android:name="android.hardware.camera"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
</manifest>