Android Integration
To integrate the Android SDK’s within your React Native app, open the Android folder inside your React Native project using Android Studio and follow the steps listed below.
Steps
Resources
Add our Maven Repository and the Artifactory Credentials
- Locate the file gradle.properties in your pc under ~/.gradle/gradle.properties.
- If the file does not exist create one and add the following credentials to it replacing the placeholder with the right values.
nativeArtifactoryUsername=placeholder
nativeArtifactoryPassword=placeholder
If you do not have these credentials yet then get in touch with CarTrawler.
Add the CarTrawler Dependency to build.gradle
Please use the version number sent to you by the CarTrawler team
implementation "com.cartrawler.android:car-rental:$latestVersion"
If not migrated yet, it is recommended to migrate the project to Android X: Migration guide
Expose Methods to React Native
Inside your Android project, create a new class that extends ReactContextBaseJavaModule, this class will be the Module that we will expose methods to the React Native side.
/**
* Expose Java to JavaScript. Methods annotated with [ReactMethod] are exposed.
*/
class CTSDKStarterModule(reactContext: ReactApplicationContext?) :
ReactContextBaseJavaModule(reactContext) {
/**
* @return the name of this module. This will be the name used to `require()` this module
* from JavaScript.
*/
override fun getName(): String {
return "CTSDKStarterModule"
}
//Example of method we can expose to Javascript
@ReactMethod
fun startBookingFlow() {
val activity = currentActivity
if (activity != null) {
val intent = Intent(activity, CTFlowActivity::class.java)
activity.startActivity(intent)
}
}
}
Create a class that implements ReactPackage and overrides the ‘createNativeModules’ method, so we can add our new module to the modules list.
/**
* Exposes [CTSDKStarterModule] and [EventEmitterModule] to JavaScript.
* One [ReactPackage] can expose any number of [NativeModule]s.
*/
internal class CTSDKStarterReactPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
val modules: MutableList<NativeModule> = ArrayList()
modules.add(CTSDKStarterModule(reactContext))
modules.add(EventEmitterModule(reactContext))
return modules
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
Update MainApplication to include the new package. The one created above.
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new CTSDKStarterReactPackage());
return packages;
}
- Save, clean and rebuild project.
Access Functions in JavaScript
We should now be able to access the function created inside the Module, on the Javascript side.
...
import {
NativeModules
} from 'react-native';
const ctSDKStarterModule = NativeModules.CTSDKStarterModule;
export default class CTSDKDemoComponent extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={() => {
ctSDKStarterModule.startBookingFlow()
}
}
title='Start Booking flow'
/>
</View>
</View>
);
}
}
...
Receive Events from the SDK in JavaScript
To send information back to Javascript such as a booking result, we create another class that extends ReactContextBaseJavaModule on the Android side.
class EventEmitterModule(reactContext: ReactApplicationContext?) :
ReactContextBaseJavaModule(reactContext) {
override fun initialize() {
super.initialize()
eventEmitter = reactApplicationContext.getJSModule(
RCTDeviceEventEmitter::class.java
)
}
/**
* @return the name of this module. This will be the name used to `require()` this module
* from JavaScript.
*/
override fun getName(): String {
return "EventEmitter"
}
override fun getConstants(): Map<String, Any>? {
val constants: MutableMap<String, Any> = HashMap()
constants["MyEventName"] = "BookingEvent"
return constants
}
companion object {
private lateinit var eventEmitter: RCTDeviceEventEmitter
/**
* To pass a JavaScript object instead of a simple string, create a [WritableNativeMap] and populate it.
*/
fun emitEvent(message: String) {
eventEmitter.emit("BookingEvent", message)
}
}
}
On the Javascript side we can then subscribe to this event:
const eventEmitter = new NativeEventEmitter(eventEmitterModule);
eventEmitter.addListener("BookingEvent", (params) => {
alert("Hello from React Native side, the booking details were received"+ "\n\n" + params);
});
Initiate the Flow
To trigger the CarTrawler flow and send the result back to the React Native side, create an activity in your Android project called CTFlowActivity.kt.
class CTFlowActivity : ReactActivity() {
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.ctflow_activity)
init()
}
private fun init() {
val partnerImplementationID = "your-implementation-id-here"
val environment = CTSdkEnvironment.DEVELOPMENT // CTSdkEnvironment.PRODUCTION
CartrawlerSDK.init(partnerImplementationID, environment)
val sdkDataClientIdXYZ = CTSdkData.Builder(clientId = clientId)
.country(twoLetterISOCountry = "IE")
.currency(currency = "EUR")
//.<any other options you need to initialise the builder here>
CartrawlerSDK.start(
activity = this,
requestCode = YOUR_REQUEST_CODE_HERE,
ctSdkData = sdkDataClientIdXYZ.build(),
flow = Standalone()
)
findViewById<View>(R.id.go_back_button).setOnClickListener { onBackPressed() }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val gson = GsonBuilder().setPrettyPrinting().create()
if (resultCode == RESULT_OK && requestCode == YOUR_REQUEST_CODE_HERE) {
val reservationExtra =
data?.getParcelableExtra<ReservationDetails>(CartrawlerSDK.RESERVATION_DETAILS)
if (reservationExtra != null) {
reservation = gson.toJson(reservationExtra)
sendBookingResult()
}
} else if (resultCode == RESULT_CANCELED) {
this@CTFlowActivity.finish()
}
}
private fun sendBookingResult() {
EventEmitterModule.emitEvent(reservation)
}
}
After completing the above steps and running your project, you will be able to initiate the CarTrawler booking flow from your React Native project and receive booking details once the flow is complete.
Sample Code and Resources
- Sample code
- More details on Native Modules
- SDK Migration guide to 14.0.2