Integrasi Mobile•Flutter SDK
Implementasi Native Flutter
Panduan integrasi lengkap untuk aplikasi **Flutter** menggunakan package resmi webview_flutter versi 4+.
1. Tambahkan Dependencies (pubspec.yaml)
pubspec.yaml
dependencies:
flutter:
sdk: flutter
webview_flutter: ^4.10.0
permission_handler: ^11.3.1
geolocator: ^13.0.12. Screen Widget Lengkap (qoin_webview_screen.dart)
Kode berikut menangani inisialisasi WebView, pemasangan JavaScript Channel, izin lokasi, injeksi Signature & Palette, serta penutupan layar saat transaksi selesai.
lib/screens/qoin_webview_screen.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:permission_handler/permission_handler.dart';
class QoinWebviewScreen extends StatefulWidget {
final String baseUrl;
final String signature;
final String palette;
const QoinWebviewScreen({
Key? key,
required this.baseUrl,
required this.signature,
this.palette = 'original',
}) : super(key: key);
@override
State<QoinWebviewScreen> createState() => _QoinWebviewScreenState();
}
class _QoinWebviewScreenState extends State<QoinWebviewScreen> {
late final WebViewController _controller;
bool _isLoading = true;
@override
void initState() {
super.initState();
_initPermissionsAndWebview();
}
Future<void> _initPermissionsAndWebview() async {
// 1. Minta izin lokasi GPS sebelum webview dibuka
await Permission.locationWhenInUse.request();
// 2. Konfigurasi Controller Webview
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.white)
..addJavaScriptChannel(
'QoinBridge',
onMessageReceived: (JavaScriptMessage message) {
_handleWebviewMessage(message.message);
},
)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String url) {
setState(() => _isLoading = false);
_injectPostMessage();
},
),
)
..loadRequest(Uri.parse('${widget.baseUrl}/'));
}
void _injectPostMessage() {
final payload = jsonEncode({
'Signature': widget.signature,
'Palette': widget.palette,
});
// Pasang polyfill bridge agar window.postMessage di webview diteruskan ke channel Flutter
const bridgeScript = """
window.addEventListener('message', function(event) {
if (window.QoinBridge) {
var data = typeof event.data === 'string' ? event.data : JSON.stringify(event.data);
window.QoinBridge.postMessage(data);
}
});
""";
_controller.runJavaScript(bridgeScript);
_controller.runJavaScript("window.postMessage($payload, '*');");
// Retry kirim ulang 500ms kemudian
Future.delayed(const Duration(milliseconds: 500), () {
_controller.runJavaScript("window.postMessage($payload, '*');");
});
}
void _handleWebviewMessage(String messageText) {
try {
final data = jsonDecode(messageText);
if (data is Map<String, dynamic>) {
// Tangkap sinyal penutupan
if (data['close'] == true) {
Navigator.of(context).pop(data);
}
}
} catch (e) {
debugPrint('Format pesan non-JSON: $messageText');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
WebViewWidget(controller: _controller),
if (_isLoading)
const Center(child: CircularProgressIndicator(color: Colors.amber)),
],
),
),
);
}
}Tips Hasil Navigator Pop
Saat
Navigator.of(context).pop(data) terpanggil, screen pemanggil akan menerima Map kembalian. Cek result['STATUS'] == 'TRUE' untuk mengupdate state aplikasi kamu!