dfinery_plugin 1.0.0-rc.0
dfinery_plugin: ^1.0.0-rc.0 copied to clipboard
Dfinery plugin for Flutter
example/lib/main.dart
import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:dfinery_plugin/dfinery_plugin.dart';
import 'package:go_router/go_router.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Dfinery SDK 초기화
_initializeDfinerySDK();
runApp(MyApp(state: ApplicationState()));
}
/// Dfinery SDK 초기화 함수
void _initializeDfinerySDK() {
Map<String, dynamic> config = {
DFConfig.iosLogEnable: true,
DFConfig.androidLogEnable: true,
DFConfig.androidLogLevel: DFAndroidLogLevel.verbose,
DFConfig.androidNotificationIconName: 'ic_dfinery',
DFConfig.androidNotificationChannelId: 'dfinery',
};
Dfinery.initWithConfig(serviceId: "YOUR_SERVICE_ID", config: config);
}
// =============================================================================
// 🔥 DFINERY EVENT FUNCTIONS
// =============================================================================
/// 공통 아이템 데이터 생성
Map<String, dynamic> _createSampleItem({DateTime? customDate}) {
final item = {
DFEventProperty.itemId: '상품번호',
DFEventProperty.itemName: '상품이름',
DFEventProperty.itemCategory1: '식품',
DFEventProperty.itemCategory2: '과자',
DFEventProperty.itemPrice: 5000.0,
DFEventProperty.itemDiscount: 500.0,
DFEventProperty.itemQuantity: 5
};
if (customDate != null) {
item['custom_item_property'] = customDate;
}
return item;
}
/// 공통 아이템 리스트 생성
List<Map<String, dynamic>> _createSampleItems({DateTime? customDate}) {
return [_createSampleItem(customDate: customDate)];
}
// -----------------------------------------------------------------------------
// 👤 User Analytics Functions
// -----------------------------------------------------------------------------
void onLoginPressed() {
Dfinery.logEvent(eventName: DFEvent.login);
print('Login 함수가 호출되었습니다.');
}
void onLogoutPressed() {
Dfinery.logEvent(eventName: DFEvent.logout);
print('Logout 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// 🔄 Common Functions
// -----------------------------------------------------------------------------
void onSignUpPressed() {
final param = {
DFEventProperty.signChannel: 'Kakao',
};
Dfinery.logEvent(eventName: DFEvent.signUp, properties: param);
print('Sign Up 함수가 호출되었습니다.');
}
void onPurchasePressed() {
final param = {
DFEventProperty.items: _createSampleItems(),
DFEventProperty.orderId: '상품번호',
DFEventProperty.paymentMethod: 'BankTransfer',
DFEventProperty.totalPurchaseAmount: 25500.0,
DFEventProperty.deliveryCharge: 3000.0,
DFEventProperty.itemDiscount: 0
};
Dfinery.logEvent(eventName: DFEvent.purchase, properties: param);
print('Purchase 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// 🛒 Commerce Functions
// -----------------------------------------------------------------------------
void onViewHomePressed() {
Dfinery.logEvent(eventName: DFEvent.viewHome);
print('View Home 함수가 호출되었습니다.');
}
void onViewProductDetailPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.viewProductDetail, properties: param);
print('View Product Details 함수가 호출되었습니다.');
}
void onAddToCartPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.addToCart, properties: param);
print('Add to Cart 함수가 호출되었습니다.');
}
void onAddToWishListPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.addToWishList, properties: param);
print('Add to Wishlist 함수가 호출되었습니다.');
}
void onRefundPressed() {
final param = {
DFEventProperty.items: _createSampleItems(),
DFEventProperty.totalRefundAmount: 22500.0
};
Dfinery.logEvent(eventName: DFEvent.refund, properties: param);
print('Refund 함수가 호출되었습니다.');
}
void onViewSearchResultPressed() {
final param = {
DFEventProperty.items: _createSampleItems(),
DFEventProperty.keyword: '삼겹살'
};
Dfinery.logEvent(eventName: DFEvent.viewSearchResult, properties: param);
print('View Search Result 함수가 호출되었습니다.');
}
void onViewListPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.viewList, properties: param);
print('View List 함수가 호출되었습니다.');
}
void onViewCartPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.viewCart, properties: param);
print('View Cart 함수가 호출되었습니다.');
}
void onRemoveCartPressed() {
final param = {DFEventProperty.items: _createSampleItems()};
Dfinery.logEvent(eventName: DFEvent.removeCart, properties: param);
print('Remove Cart 함수가 호출되었습니다.');
}
void onShareProductPressed() {
final param = {
DFEventProperty.items: _createSampleItems(customDate: DateTime(2022, 4, 3)),
DFEventProperty.sharingChannel: 'Facebook',
'custom_property': DateTime(2022, 5, 6)
};
Dfinery.logEvent(eventName: DFEvent.shareProduct, properties: param);
print('Share Product 함수가 호출되었습니다.');
}
void onAddPaymentInfoPressed() {
Dfinery.logEvent(eventName: DFEvent.addPaymentInfo);
print('Add Payment Info 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// 🎯 Custom Event Functions
// -----------------------------------------------------------------------------
void onCustomEventPressed() {
final param = {
'is_logined': true,
'username': 'hello',
'visit_count': 1000,
'custom_list': [
{
'custom_map_1_date': DateTime(2022, 4, 3),
'custom_map_1_string': 'string',
'custom_map_1_int': 1,
'custom_map_1_double': 1000.0,
'custom_map_1_bool': true,
},
{
'custom_map_2_date': DateTime.now(),
'custom_map_2_string': 'string',
'custom_map_2_int': 0,
'custom_map_2_double': 1000.0,
'custom_map_2_bool': false
}
]
};
Dfinery.logEvent(eventName: 'custom_event_1', properties: param);
print('Custom Event 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// ⚙️ SDK Management Functions
// -----------------------------------------------------------------------------
void onEnableSDKPressed() {
Dfinery.enableSDK();
print('enableSDK 함수가 호출되었습니다.');
}
void onDisableSDKPressed() {
Dfinery.disableSDK();
print('disableSDK 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// 👥 User Properties Functions
// -----------------------------------------------------------------------------
void onSetUserProfilePressed() {
Dfinery.setUserProfile(
key: 'custom_user_profile_1',
value: DateTime(2022, 4, 3, 0, 13, 1, 123, 12));
print('setUserProfile 함수가 호출되었습니다.');
}
void onSetUserProfilesPressed() {
final arr = ['a', 'b', 'c', 'd', 'e'];
final now = DateTime.now();
final param = {
DFUserProfile.name: 'william',
DFUserProfile.gender: DFGender.male,
"custom_user_profile_1": now,
"custom_user_profile_2": arr
};
Dfinery.setUserProfiles(values: param);
print('setUserProfiles 함수가 호출되었습니다.');
}
// DFIdentity를 사용자 친화적인 이름으로 변환
String _identityToDisplayName(DFIdentity identity) {
switch (identity) {
case DFIdentity.externalId:
return 'External ID';
case DFIdentity.email:
return 'Email';
case DFIdentity.phoneNo:
return 'Phone Number';
case DFIdentity.kakaoUserId:
return 'Kakao User ID';
case DFIdentity.lineUserId:
return 'Line User ID';
}
}
// DFIdentity 선택 다이얼로그
Future<DFIdentity?> _showIdentitySelectionDialog(
BuildContext context, Map<DFIdentity, String> identityOptions) async {
return showDialog<DFIdentity>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Identity 선택'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: identityOptions.entries.map((entry) {
return ListTile(
title: Text(_identityToDisplayName(entry.key)),
subtitle: Text('값: ${entry.value}'),
onTap: () => Navigator.of(context).pop(entry.key),
);
}).toList(),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('취소'),
),
],
);
},
);
}
Future<void> onSetIdentityPressed(BuildContext context) async {
// DFIdentity 옵션과 샘플 값 매핑
final identityOptions = {
DFIdentity.externalId: 'user_12345',
DFIdentity.email: 'example@example.com',
DFIdentity.phoneNo: '01000000000',
DFIdentity.kakaoUserId: 'kakao_user_123',
DFIdentity.lineUserId: 'line_user_456',
};
// 사용자에게 DFIdentity 선택 다이얼로그 표시
final selectedIdentity =
await _showIdentitySelectionDialog(context, identityOptions);
if (selectedIdentity != null) {
final value = identityOptions[selectedIdentity]!;
Dfinery.setIdentity(key: selectedIdentity, value: value);
print(
'setIdentity 함수가 호출되었습니다: ${_identityToDisplayName(selectedIdentity)} = $value');
}
}
void onSetIdentitiesPressed() {
final param = {
DFIdentity.externalId: 'user_example',
DFIdentity.email: 'example@example.com',
DFIdentity.phoneNo: '01012345678'
};
Dfinery.setIdentities(values: param);
print('setIdentities 함수가 호출되었습니다.');
}
void onResetIdentityPressed() {
Dfinery.resetIdentity();
print('resetIdentity 함수가 호출되었습니다.');
}
// -----------------------------------------------------------------------------
// 🔔 Push Notification Functions
// -----------------------------------------------------------------------------
Future<void> onRequestNotificationPermissionPressed() async {
final status = await Permission.notification.request();
if (status.isGranted) {
print("알림 권한이 허용되었습니다.");
} else if (status.isDenied) {
print("알림 권한이 거부되었습니다.");
} else if (status.isPermanentlyDenied) {
print("알림 권한이 영구적으로 거부되었습니다. 설정에서 허용해주세요.");
await openAppSettings();
} else if (status.isRestricted) {
print("알림 권한이 제한되었습니다.");
}
print('requestMessagingPermission 함수가 호출되었습니다.');
}
void onGetPushTokenPressed() {
Dfinery.getPushToken().then((value) {
print('getPushToken: $value');
});
}
void onSetPushTokenPressed() {
Dfinery.getPushToken().then((value) {
if (value != null) {
Dfinery.setPushToken(pushToken: value);
print('setPushToken 함수가 호출되었습니다: $value.');
}
});
}
// =============================================================================
// 🏗️ UI COMPONENTS
// =============================================================================
// GoRouter 인스턴스 생성
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) {
return MyHomePage(title: 'Dfinery Flutter Example', state: state);
},
routes: <RouteBase>[],
),
],
errorBuilder: (BuildContext context, GoRouterState state) {
return Scaffold(
appBar: AppBar(title: const Text('Error')),
body: Center(
child: Text('페이지를 찾을 수 없습니다: ${state.error}'),
),
);
},
);
class MyApp extends StatelessWidget {
const MyApp({super.key, required this.state});
final ApplicationState state;
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Dfinery Flutter Example',
theme: ThemeData(primarySwatch: Colors.deepPurple),
routerConfig: _router,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title, required this.state});
final String title;
final GoRouterState state;
@override
MyHomeState createState() => MyHomeState();
}
class MyHomeState extends State<MyHomePage> with WidgetsBindingObserver {
late AppLinks _appLinks;
StreamSubscription<Uri>? _appLinksSubscription;
bool _hasHandledInitialLink = false; // 초기 딥링크 처리 여부 플래그
String? _initialLinkUri; // 초기 딥링크 URI 저장
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this);
_appLinks = AppLinks();
_initDeepLinks();
}
Future<void> _initDeepLinks() async {
// 앱이 처음 실행될 때 딥링크 확인
final Uri? initialUri = await _appLinks.getInitialLink();
if (initialUri != null) {
_hasHandledInitialLink = true;
_initialLinkUri = initialUri.toString();
debugPrint('Initial deep link detected: $initialUri');
_showDeepLinkAlert('앱 시작 딥링크', initialUri.toString());
// 초기 딥링크 처리 후 잠깐 지연하여 중복 방지
await Future.delayed(const Duration(milliseconds: 500));
}
// 앱이 실행 중일 때 딥링크 감지
_appLinksSubscription = _appLinks.uriLinkStream.listen(
(Uri uri) {
// 초기 딥링크가 처리되었고, 같은 URI인 경우 무시
if (_hasHandledInitialLink && _initialLinkUri == uri.toString()) {
debugPrint('중복 딥링크 무시: $uri');
return;
}
debugPrint('Deep link received while app running: $uri');
_showDeepLinkAlert('런타임 딥링크', uri.toString());
},
onError: (err) {
debugPrint('Deep link error: $err');
},
);
}
void _showDeepLinkAlert(String title, String deepLink) {
if (mounted) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('딥링크로 앱이 열렸습니다!'),
const SizedBox(height: 8),
const Text('URL:',
style: TextStyle(fontWeight: FontWeight.bold)),
SelectableText(
deepLink,
style: const TextStyle(fontSize: 12, color: Colors.blue),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('확인'),
),
],
);
},
);
}
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
_appLinksSubscription?.cancel();
super.dispose();
}
@override
void didUpdateWidget(covariant MyHomePage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.state != oldWidget.state) {
String newDeepLinkInfo =
"didUpdateWidget GoRouterState URI: ${widget.state.uri}";
print('didUpdateWidget (GoRouterState): ' + newDeepLinkInfo);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dfinery Demo',
theme: ThemeData(primarySwatch: Colors.deepPurple),
home: Scaffold(
appBar: AppBar(title: const Text('Dfinery Demo')),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text('LogEvent',
style: Theme.of(context).textTheme.headlineLarge),
// User Analytics Section
Text('UserAnalytics',
style: Theme.of(context).textTheme.headlineMedium),
const ElevatedButton(
onPressed: onLoginPressed, child: Text('Login')),
const ElevatedButton(
onPressed: onLogoutPressed, child: Text('Logout')),
// Common Section
Text('Common',
style: Theme.of(context).textTheme.headlineMedium),
const ElevatedButton(
onPressed: onSignUpPressed, child: Text('Sign Up')),
const ElevatedButton(
onPressed: onPurchasePressed, child: Text('Purchase')),
// Commerce Section
Text('Commerce',
style: Theme.of(context).textTheme.headlineMedium),
const ElevatedButton(
onPressed: onViewHomePressed, child: Text('View Home')),
const ElevatedButton(
onPressed: onViewProductDetailPressed,
child: Text('View Product Details')),
const ElevatedButton(
onPressed: onAddToCartPressed, child: Text('Add To Cart')),
const ElevatedButton(
onPressed: onAddToWishListPressed,
child: Text('Add To Wishlist')),
const ElevatedButton(
onPressed: onRefundPressed, child: Text('Refund')),
const ElevatedButton(
onPressed: onViewSearchResultPressed,
child: Text('View Search Result')),
const ElevatedButton(
onPressed: onViewListPressed, child: Text('View List')),
const ElevatedButton(
onPressed: onViewCartPressed, child: Text('View Cart')),
const ElevatedButton(
onPressed: onRemoveCartPressed, child: Text('Remove Cart')),
const ElevatedButton(
onPressed: onShareProductPressed,
child: Text('Share Product')),
const ElevatedButton(
onPressed: onAddPaymentInfoPressed,
child: Text('Add Payment Info')),
// Custom Event Section
Text('CustomEvent',
style: Theme.of(context).textTheme.headlineMedium),
const ElevatedButton(
onPressed: onCustomEventPressed,
child: Text('Custom Event')),
// SDK Management Section
Text('Dfinery',
style: Theme.of(context).textTheme.headlineMedium),
const ElevatedButton(
onPressed: onEnableSDKPressed, child: Text('enableSDK')),
const ElevatedButton(
onPressed: onDisableSDKPressed, child: Text('disableSDK')),
// User Properties Section
Text('DfineryProperties',
style: Theme.of(context).textTheme.headlineLarge),
const ElevatedButton(
onPressed: onSetUserProfilePressed,
child: Text('setUserProfile')),
const ElevatedButton(
onPressed: onSetUserProfilesPressed,
child: Text('setUserProfiles')),
ElevatedButton(
onPressed: () {
onSetIdentityPressed(context);
},
child: const Text('setIdentity')),
const ElevatedButton(
onPressed: onSetIdentitiesPressed,
child: Text('setIdentities')),
const ElevatedButton(
onPressed: onResetIdentityPressed,
child: Text('resetIdentity')),
// Push Notification Section
Text('Push Notification',
style: Theme.of(context).textTheme.headlineLarge),
const ElevatedButton(
onPressed: onRequestNotificationPermissionPressed,
child: Text('Request Notification Permission')),
const ElevatedButton(
onPressed: onGetPushTokenPressed,
child: Text('Get Push Token')),
const ElevatedButton(
onPressed: onSetPushTokenPressed,
child: Text('Set Push Token')),
],
),
),
),
),
);
}
}
class ApplicationState extends ChangeNotifier {
ApplicationState() {
init();
}
Future<void> init() async {
refreshPushToken();
refreshGoogleAdvertisingId();
createNotificationChannel();
}
void refreshPushToken() {
Future<String?> pushToken = Dfinery.getPushToken();
pushToken.then((value) {
if (value != null) {
Dfinery.setPushToken(pushToken: value);
}
}).catchError((error) {
print("error in refreshPushToken. ${error}");
});
}
void refreshGoogleAdvertisingId() {
Future<DFGetGoogleAdvertisingIdCallback?> advertisingIdInfo =
Dfinery.getGoogleAdvertisingId();
advertisingIdInfo.then((value) {
if (value != null) {
Dfinery.setGoogleAdvertisingId(
googleAdvertisingId: value.googleAdvertisingId,
isLimitAdTrackingEnabled: value.isLimitAdTrackingEnabled);
}
}).catchError((error) {
print("error in refreshGoogleAdvertisingId. ${error}");
});
}
void createNotificationChannel() {
Map<String, dynamic> properties = {
DFAndroidNotificationChannelProperty.id: 'dfinery',
DFAndroidNotificationChannelProperty.name: 'Default Notification Channel',
DFAndroidNotificationChannelProperty.importance:
DFAndroidNotificationChannelImportance.high,
DFAndroidNotificationChannelProperty.badge: true,
DFAndroidNotificationChannelProperty.sound: true,
DFAndroidNotificationChannelProperty.visibility:
DFAndroidNotificationChannelVisibility.public,
DFAndroidNotificationChannelProperty.vibration: true
};
Dfinery.createNotificationChannel(properties: properties);
}
}