Flutter Integration
This example demonstrates how to integrate the Hubble Gift Card Store SDK in a Flutter application.
import 'dart:convert'; // Required for jsonDecodeimport 'package:flutter/material.dart';import 'package:webview_flutter/webview_flutter.dart';import 'package:url_launcher/url_launcher.dart';
class HubbleWebView extends StatefulWidget { const HubbleWebView({Key? key}) : super(key: key);
@override State<HubbleWebView> createState() => _HubbleWebViewState();}
class _HubbleWebViewState extends State<HubbleWebView> { late final WebViewController _controller; bool _isWebViewReady = false;
@override void initState() { super.initState(); _initWebView(); }
void _initWebView() { final params = { 'authToken': 'authToken', // your auth token 'clientId': 'id_given_by_hubble', 'clientSecret': 'secret_given_by_hubble', 'env': 'debug', 'wrapPlt': 'flutter', // 'page': 'transactions', // optional initial page to load, default is home };
final baseUrl = 'https://vouchers.dev.myhubble.money/classic'; // prod baseUrl is https://vouchers.myhubble.money/classic final sourceUrl = '$baseUrl?clientId=${params['clientId']}&clientSecret=${params['clientSecret']}&token=${params['authToken']}&wrap-plt=${params['wrapPlt']}&env=${params['env']}&page=${params['page']}';
_controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setBackgroundColor(Colors.white) ..setNavigationDelegate( NavigationDelegate( onPageStarted: (String url) { print('Page started loading: $url'); }, onPageFinished: (String url) { setState(() { _isWebViewReady = true; }); print('Page finished loading: $url'); }, onWebResourceError: (WebResourceError error) { print('Web resource error: ${error.description}'); }, onNavigationRequest: (NavigationRequest request) { if (request.url.startsWith(baseUrl)) { return NavigationDecision.navigate; } else { _launchURL(request.url); return NavigationDecision.prevent; } }, ), ) ..addJavaScriptChannel( 'FlutterHost', onMessageReceived: (JavaScriptMessage message) { _handleEvent(message.message); }, ) ..loadRequest(Uri.parse(sourceUrl)); }
Future<void> _launchURL(String url) async { final uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { print('Could not launch $url'); } }
void _handleEvent(String jsonString) { try { final eventData = jsonDecode(jsonString) as Map<String, dynamic>; final String? action = eventData['action'] as String?;
// Check for the 'close' action first for an early exit. if (action == 'close') { print("Received 'close' action from WebView. Popping screen."); Navigator.of(context).pop(); return; }
// If it's not a close action, proceed with logging other events. final String? event = eventData['event'] as String?; final Map<String, dynamic>? properties = eventData['properties'] as Map<String, dynamic>?;
if (event != null) { _logEvent(event, properties ?? {}); }
} catch (e) { print('Error handling event from WebView: $e'); print('Received message: $jsonString'); } }
void _logEvent(String eventType, Map<String, dynamic> eventParams) { // Your implementation of sending events to analytics print('Analytics Event Type: $eventType'); print('Analytics Event Params: $eventParams'); }
@override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { if (!_isWebViewReady) return true;
if (await _controller.canGoBack()) { await _controller.goBack(); return false; } return true; }, child: Scaffold( body: SafeArea( child: WebViewWidget(controller: _controller), ), ), ); }}