React Native
Integrasikan Human Token Journey ke dalam aplikasi React Native Anda melalui modul native.
Integrasi ini menggunakan modul native yang mendelegasikan ke ASWebAuthenticationSession di iOS dan Custom Tabs di Android. Saat perjalanan selesai, modul native menyelesaikan promise dengan URL callback.
Prasyarat
- React Native 0.71 atau lebih baru
- Xcode 14+ untuk iOS
- Android Studio untuk Android
- Skema URL unik untuk aplikasi Anda (misalnya
myapp)
Langkah 1: Tentukan skema URL Anda
Pilih skema unik (misalnya myapp). Ini digunakan sebagai callbackUri saat membuat proses:
callbackUri: myapp://callback
Langkah 2: Buat bridge TypeScript
// src/modules/UnicoModule.ts
import { NativeModules } from 'react-native';
const { UnicoModule } = NativeModules;
if (!UnicoModule) {
throw new Error('UnicoModule not found. Make sure the native module is linked correctly.');
}
export const Unico = {
openSession: (url: string): Promise<string> => UnicoModule.openSession(url),
};
Langkah 3: Implementasikan modul native iOS
- Objective-C bridge
- Swift implementation
// ios/UnicoModule.m
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(UnicoModule, NSObject)
RCT_EXTERN_METHOD(openSession:(NSString *)url
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
@end
// ios/UnicoModule.swift
import AuthenticationServices
@objc(UnicoModule)
class UnicoModule: NSObject, ASWebAuthenticationPresentationContextProviding {
private var session: ASWebAuthenticationSession?
@objc func openSession(_ url: String,
resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock) {
guard let sessionURL = URL(string: url) else {
reject("INVALID_URL", "Invalid URL", nil)
return
}
DispatchQueue.main.async {
let newSession = ASWebAuthenticationSession(
url: sessionURL,
callbackURLScheme: "myapp"
) { callbackURL, error in
self.session = nil
if let callbackURL = callbackURL {
resolve(callbackURL.absoluteString)
} else {
reject("SESSION_ERROR", error?.localizedDescription ?? "Session cancelled", error)
}
}
newSession.presentationContextProvider = self
newSession.prefersEphemeralWebBrowserSession = true
newSession.start()
self.session = newSession
}
}
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first else {
return ASPresentationAnchor()
}
return window
}
@objc static func requiresMainQueueSetup() -> Bool { return true }
}
Langkah 4: Implementasikan modul native Android
Tambahkan dependensi ke android/app/build.gradle:
implementation("androidx.browser:browser:1.5.0")
// android/app/src/main/java/<your.package>/UnicoModule.kt
package com.yourapp
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import com.facebook.react.bridge.*
class UnicoModule(private val reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
private var pendingPromise: Promise? = null
override fun getName() = "UnicoModule"
@ReactMethod
fun openSession(url: String, promise: Promise) {
pendingPromise = promise
currentActivity?.runOnUiThread {
CustomTabsIntent.Builder().build()
.launchUrl(currentActivity!!, Uri.parse(url))
} ?: promise.reject("NO_ACTIVITY", "No current activity")
}
fun handleRedirectUrl(uri: Uri) {
if (uri.scheme == "myapp") {
pendingPromise?.resolve(uri.toString())
pendingPromise = null
}
}
}
// UnicoPackage.kt
package com.yourapp
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class UnicoPackage : ReactPackage {
override fun createNativeModules(ctx: ReactApplicationContext): List<NativeModule> =
listOf(UnicoModule(ctx))
override fun createViewManagers(ctx: ReactApplicationContext): List<ViewManager<*, *>> =
emptyList()
}
Daftarkan di MainApplication.kt:
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(UnicoPackage())
}
Tangani redirect di MainActivity.kt:
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
intent.data?.let { uri ->
if (uri.scheme == "myapp") {
val module = reactInstanceManager
.currentReactContext
?.getNativeModule(UnicoModule::class.java)
module?.handleRedirectUrl(uri)
}
}
}
Langkah 5: Konfigurasi AndroidManifest.xml
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<activity android:name=".MainActivity" ...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="callback" />
</intent-filter>
</activity>
Langkah 6: Mulai perjalanan
import { Unico } from './modules/UnicoModule';
const resultUrl = await Unico.openSession(processLink);
// resultUrl = myapp://callback?id=...
Ringkasan file
| File | Tujuan |
|---|---|
src/modules/UnicoModule.ts | Bridge TypeScript |
ios/UnicoModule.m | Deklarasi Objective-C |
ios/UnicoModule.swift | iOS — ASWebAuthenticationSession |
android/.../UnicoModule.kt | Android — Custom Tabs |
android/.../UnicoPackage.kt | Registrasi package |
android/.../MainApplication.kt | Integrasi package |
android/.../MainActivity.kt | Penanganan URL redirect |
AndroidManifest.xml | Intent filter |