Skip to main content

Flutter Integration

This guide covers how to integrate the Hubble SDK into a Flutter application using webview_flutter.

1. Setup the WebView

Add the required dependencies to your pubspec.yaml:

dependencies:
webview_flutter: ^4.0.0
url_launcher: ^6.0.0

Run flutter pub get after adding the dependencies.

2. Initialization

Build the SDK URL with your credentials:

ParameterRequiredDescription
clientIdYesClient ID provided by the Hubble team
appSecretYesApp secret provided by the Hubble team
tokenConditionalSSO token for the current user. Required unless lazy login is enabled.
appVersionNoApp version string. Defaults to "10000".
deviceIdNoDevice identifier for analytics.
final params = {
'clientId': 'id_given_by_hubble',
'appSecret': 'secret_given_by_hubble',
'token': 'your_sso_token',
};

final baseUrl = 'https://sdk.dev.myhubble.money/';
// prod: https://sdk.myhubble.money/

final sourceUrl = '$baseUrl?clientId=${params['clientId']}&appSecret=${params['appSecret']}&token=${params['token']}';

3. Load the WebView

Initialize the WebViewController and load the URL:

_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.white)
..setNavigationDelegate(NavigationDelegate(/* ... */))
..addJavaScriptChannel("FlutterHost",
onMessageReceived: (message) => _handleEvent(message.message),
)
..loadRequest(Uri.parse(sourceUrl));
JavaScript Channel Name Must Be "FlutterHost"

The SDK sends messages to a channel named "FlutterHost". If you use a different name, events will not be received.

4. Handling Navigation

Use the NavigationDelegate to control URL handling:

NavigationDelegate(
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith(baseUrl)
|| request.url.startsWith('https://api.razorpay.com')) {
return NavigationDecision.navigate;
} else {
launchUrl(Uri.parse(request.url), mode: LaunchMode.externalApplication);
return NavigationDecision.prevent;
}
},
)

Back Navigation

Use PopScope to handle the Android back button:

PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) async {
if (didPop) return;
if (await _controller.canGoBack()) {
await _controller.goBack();
} else {
if (context.mounted) Navigator.of(context).pop();
}
},
child: Scaffold(
body: SafeArea(child: WebViewWidget(controller: _controller)),
),
)

5. Handling Events

The SDK communicates with your application by sending events. There are two types:

Action Events

SDK lifecycle and navigation:

ActionWhen It FiresWhat You Should Do
app_readySDK has finished loadingShow the WebView / iframe. Hide your loading spinner.
closeUser tapped the close or back button in the SDKDismiss the WebView / iframe. Navigate the user back.
errorSDK failed to load (invalid credentials, network error, SSO failure)Hide the WebView. Show a user-friendly error with a retry option.
Always Handle the close Event

The close action is the only way the SDK tells your application that the user wants to leave. If you do not handle it, the user will be stuck inside the SDK with no way to navigate back. This is one of the most common integration issues.

Analytics Events

User interaction tracking:

{ "type": "analytics", "event": "payment_success", "properties": { "amount": 500 } }

Forward analytics events to your analytics provider (Mixpanel, CleverTap, Amplitude, etc.) to track SDK usage.

For a complete list of events, see the Full Events Reference.

Setting Up the Event Handler

Parse JSON messages from the FlutterHost channel:

void _handleEvent(String jsonString) {
try {
final data = jsonDecode(jsonString) as Map<String, dynamic>;
final type = data['type'] as String?;

if (type == 'action') {
final action = data['action'] as String?;
if (action == 'close') {
Navigator.of(context).pop();
} else if (action == 'app_ready') {
setState(() => _loading = false);
} else if (action == 'error') {
setState(() => _error = true);
}
} else if (type == 'analytics') {
final event = data['event'] as String?;
final properties = data['properties'] as Map<String, dynamic>?;
// Forward to your analytics provider
}
} catch (e) {
print('Error handling event: $e');
}
}

6. Payment Configuration

The Hubble SDK supports UPI and credit/debit card payments. Credit/debit card payments are not enabled by default - contact Hubble support to enable them.

UPI on Flutter

Flutter uses a WebView under the hood, so UPI configuration depends on the target platform:

In your NavigationDelegate, UPI scheme URLs should be launched externally using url_launcher.

Best Practices

  • Wrap in SafeArea: Always use SafeArea to avoid content being hidden behind the notch or system UI.
  • Dispose properly: The WebViewController is automatically disposed when the widget is removed from the tree.
  • Show a loading state: Use a Stack to overlay a loading spinner until app_ready fires.
  • Test on both platforms: Flutter WebView behavior can differ between iOS and Android. Test on both physical devices.