fplink_flutter 1.0.0-alpha01
fplink_flutter: ^1.0.0-alpha01 copied to clipboard
FpLink SDK for Flutter
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fplink_flutter/fplink_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: FplinkWebViewTest(),
);
}
}
class FplinkWebViewTest extends StatefulWidget {
const FplinkWebViewTest({super.key});
@override
State<FplinkWebViewTest> createState() => _FplinkWebViewTestState();
}
class _FplinkWebViewTestState extends State<FplinkWebViewTest> {
late final WebViewController _controller;
StreamSubscription? _deeplinkSubscription; // RN의 unsubscribe 역할
@override
void initState() {
super.initState();
// ✅ 1. [에어브릿지 방식] 중앙 딥링크 리스너 등록
// 모든 성공 신호(일반 딥링크, 클릭 트래킹 결과)가 이쪽으로 모입니다.
_deeplinkSubscription = Fplink.setOnDeeplinkReceived((data) {
debugPrint('🔗 [Dart 중앙핸들러] 수신: ${data.link}');
// 알림창 띄우기 (RN의 Alert.alert와 동일)
_showDeepLinkAlert(data.link, data.scheme ?? '없음');
// 실제 앱이라면 여기서 Navigator.push 등으로 화면 이동 수행
});
// ✅ 웹뷰 컨트롤러 설정
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
// ✅ 2. 웹뷰 내 클릭 가로채기 (RN의 onShouldStartLoadWithRequest)
onNavigationRequest: (NavigationRequest request) async {
final String url = request.url;
// Fplink.click 호출 (플러터는 await를 사용하여 비동기 결과를 직접 확인 가능)
final bool isHandled = await Fplink.click(
url,
onSuccess: () {
// 성공 콜백 (필요 시 사용)
debugPrint('✅ SDK 처리 성공:');
},
);
if (isHandled) {
debugPrint('🚀 SDK가 트래킹 링크를 인식했습니다. 웹뷰 로딩을 중단합니다.');
// 로딩 중단 (RN의 return false와 동일)
return NavigationDecision.prevent;
}
debugPrint('🌐 일반 링크입니다. 웹뷰에서 계속 로드합니다.');
// 로딩 허용 (RN의 return true와 동일)
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse('https://www.google.com')); // 테스트 주소
}
@override
void dispose() {
// ✅ 3. 언마운트 시 리스너 해제 (RN의 클린업 함수 역할)
_deeplinkSubscription?.cancel();
super.dispose();
}
// 딥링크 수신 알림 함수
void _showDeepLinkAlert(String link, String scheme) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('딥링크 수신'),
content: Text('URL: $link\n스킴: $scheme'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('확인'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
// Header (RN의 스타일을 구현)
Container(
height: 70,
padding: const EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Color(0xFFF8F8F8),
border: Border(bottom: BorderSide(color: Color(0xFFDDDDDD))),
),
child: const Text(
'Fplink WebView Test',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
// WebView
Expanded(
child: WebViewWidget(controller: _controller),
),
],
),
),
);
}
}