Starting custom activity in React Native with Expo

153 views Asked by At

I am currently working at a React Native application built with Expo and I wish to integrate the Braintree SDK Drop-in UI component to create a check-out section. Unfortunately, I can not figure out a way to start on button click an activity that opens the native drop-in UI with parameters passed from the React Native application.

I have tried multiple alternatives, first of which was writing an Expo module. I managed to pass data to the Expo module, but I was unable to start an activity from within the Expo module. Another alternative I tried was writing an activity and adding it to the AndroidManifest.xml file, and trying to then start said activity using the startAsyncActivity method from the Expo Intent-Launcher, but I couldn't get that to work either.

1

There are 1 answers

0
Alex Aelenei On BEST ANSWER

I actually managed to solve this by creating a local Expo module (using npx create-expo-module@latest --local), adding a view with a button, and when the button is clicked, I create a new intent using the given context, and start the custom activity. Below you can find some code samples:

MyModule.kt

package expo.modules.mymodule

import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition

class MyModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("MyModule")

    View(MyModuleView::class) {}
  }
}

MyModuleView.kt

package expo.modules.mymodule

import android.util.Log
import android.content.Context
import android.content.Intent
import android.util.TypedValue
import android.view.Gravity
import android.widget.Button
import expo.modules.mymodule.MyActivity
import expo.modules.kotlin.AppContext
import expo.modules.kotlin.views.ExpoView

class MyModuleView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
  internal val helloButton = Button(context).also {
    addView(it)
    it.text = "Checkout"
    it.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
    it.setOnClickListener {
      val myIntent = Intent(context, MyActivity::class.java)
      context.startActivity(myIntent);
    }
  }
}

MyActivity.kt

package expo.modules.mymodule

import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import com.braintreepayments.api.DropInClient
import com.braintreepayments.api.DropInListener
import com.braintreepayments.api.DropInRequest
import com.braintreepayments.api.DropInResult

import java.lang.Exception

class MyActivity : FragmentActivity(), DropInListener {
    private var dropInClient: DropInClient? = null;
    private var dropInRequest: DropInRequest? = null;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        dropInRequest = DropInRequest();
        dropInClient = DropInClient(this@MyActivity,"authorization_token");
        dropInClient!!.setListener(this@MyActivity);
    }

    override fun onStart() {
        super.onStart()
        dropInClient!!.launchDropIn(dropInRequest)
    }

    override fun onDropInSuccess(dropInResult: DropInResult) {
        val token = dropInResult.paymentMethodNonce!!.string;
        Log.d("TestApplication",token);
    }

    override fun onDropInFailure(error: Exception) {
        Log.d("TestApplication",error.toString());
    }
}

Also, in order to integrate the local module in the React Native application, I added the following lines to my package.json:

  "private": true,
  "expo": {
    "autolinking": {
      "nativeModulesDir": "./modules"
    }
  }