Flutter
Integrasikan Human Token Journey ke dalam aplikasi Flutter Anda menggunakan Platform Channels.
Integrasi ini menggunakan MethodChannel untuk mendelegasikan ke ASWebAuthenticationSession di iOS dan Custom Tabs di Android. Tidak diperlukan paket eksternal.
Prasyarat
- Flutter 3.x 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 service Dart
// lib/services/unico_service.dart
import 'package:flutter/services.dart';
class UnicoService {
static const _channel = MethodChannel('unico_plugin');
Future<String?> openSession(String url) async {
try {
final result = await _channel.invokeMethod<String>('openSession', {'url': url});
if (result != null) {
final uri = Uri.parse(result);
return uri.queryParameters['id'];
}
return null;
} on PlatformException {
return null;
}
}
}
Langkah 3: Implementasikan plugin iOS
// ios/Runner/UnicoPlugin.swift
import Flutter
import AuthenticationServices
class UnicoPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPresentationContextProviding {
private var session: ASWebAuthenticationSession?
static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "unico_plugin", binaryMessenger: registrar.messenger())
let instance = UnicoPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
guard call.method == "openSession",
let args = call.arguments as? [String: Any],
let urlString = args["url"] as? String,
let url = URL(string: urlString) else {
result(FlutterMethodNotImplemented)
return
}
let newSession = ASWebAuthenticationSession(
url: url,
callbackURLScheme: "myapp"
) { callbackURL, error in
self.session = nil
if let callbackURL = callbackURL {
result(callbackURL.absoluteString)
} else {
result(FlutterError(code: "SESSION_ERROR",
message: error?.localizedDescription ?? "Session cancelled",
details: nil))
}
}
newSession.presentationContextProvider = self
newSession.prefersEphemeralWebBrowserSession = true
newSession.start()
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
}
}
Daftarkan di AppDelegate.swift:
UnicoPlugin.register(with: self.registrar(forPlugin: "UnicoPlugin")!)
Langkah 4: Implementasikan plugin Android
Tambahkan dependensi ke android/app/build.gradle:
implementation("androidx.browser:browser:1.5.0")
// android/app/src/main/kotlin/<your.package>/UnicoPlugin.kt
package com.yourapp
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class UnicoPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
private var channel: MethodChannel? = null
private var binding: ActivityPluginBinding? = null
private var pendingResult: MethodChannel.Result? = null
override fun onAttachedToEngine(flutterBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterBinding.binaryMessenger, "unico_plugin")
channel?.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "openSession") {
val url = call.argument<String>("url") ?: return result.error("MISSING_URL", "URL is required", null)
pendingResult = result
val activity = binding?.activity ?: return result.error("NO_ACTIVITY", "No activity", null)
CustomTabsIntent.Builder().build().launchUrl(activity, Uri.parse(url))
} else {
result.notImplemented()
}
}
fun handleRedirect(uri: Uri) {
if (uri.scheme == "myapp") {
pendingResult?.success(uri.toString())
pendingResult = null
}
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) { this.binding = binding }
override fun onDetachedFromActivity() { binding = null }
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { this.binding = binding }
override fun onDetachedFromActivityForConfigChanges() { binding = null }
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { channel = null }
}
Daftarkan di MainActivity.kt dan tangani redirect:
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine.plugins.add(UnicoPlugin())
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
intent.data?.let { uri ->
if (uri.scheme == "myapp") {
val plugin = flutterEngine?.plugins?.get(UnicoPlugin::class.java) as? UnicoPlugin
plugin?.handleRedirect(uri)
}
}
}
Langkah 5: Konfigurasi skema URL
- iOS
- Android
Tambahkan ke Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Tambahkan ke AndroidManifest.xml di dalam <activity> utama Anda:
<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>
Langkah 6: Mulai perjalanan
final unicoService = UnicoService();
final processId = await unicoService.openSession(processLink);
if (processId != null) {
// Journey completed — send processId to your backend via Get Process
} else {
// User canceled
}
Ringkasan file
| File | Tujuan |
|---|---|
lib/services/unico_service.dart | Service Dart MethodChannel |
ios/Runner/UnicoPlugin.swift | iOS — ASWebAuthenticationSession |
ios/Runner/AppDelegate.swift | Registrasi plugin |
android/.../UnicoPlugin.kt | Android — Custom Tabs |
android/.../MainActivity.kt | Registrasi plugin + penanganan redirect |
Info.plist | Skema URL iOS |
AndroidManifest.xml | Intent filter Android |