tagworks_sdk_flutter 1.1.5 copy "tagworks_sdk_flutter: ^1.1.5" to clipboard
tagworks_sdk_flutter: ^1.1.5 copied to clipboard

Official Flutter SDK for TagWorks, providing deep linking, event tracking, and user engagement features for Android and iOS.

example/lib/main.dart

import 'package:app_links/app_links.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
// import 'package:tagworks_sdk_flutter/navigation/TagWorksNavigatorObserver.dart';

import 'package:flutter/services.dart';
import 'package:tagworks_sdk_flutter/tagworks_sdk_v1_flutter.dart';
import 'package:webview_flutter/webview_flutter.dart';

// late final GoRouter router;
final DeepLinkHandler deepLinkHandler = DeepLinkHandler();
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

// Future<void> main() async {
//   WidgetsFlutterBinding.ensureInitialized();
//   TagWorksError.install();            // 크래시 로그 자동 수집
//   deepLinkHandler.start();            // 
//   runApp( MyApp());
// }

// class MyApp extends StatelessWidget {
//   const MyApp({super.key});

//   @override
//   Widget build(BuildContext context) {
//     return MaterialApp(
//       navigatorObservers: [
//         TagWorksNavigatorObserver(),    // 페이지 전환 자동 수집
//       ],
//       initialRoute: '/',
//       routes: {
//         '/':(_) => const HomeScreen(),
//         '/detail':(_)=> const DetailScreen(),
//       },
//     );
//   }
// }

// 앱 진입: Zone 가드·바인딩·에러 핸들러·초기 딥링크 조회 후 runApp.
Future<void> main() async {
  //
  TagWorksError.runZoneGuarded(() async {
    WidgetsFlutterBinding.ensureInitialized();
    TagWorksError.install();
    // deepLinkHandler.start();

    // 앱이 링크로 "처음" 열렸을 때(백그라운드가 아닌 콜드 스타트) 한 번만 받는 초기 딥링크.
    final DeeplinkResult? initial = await TagWorksDeeplinkPlugin.getInitialDeeplink();

    runApp(MyApp(initial));
  });
}

// 콜드 스타트 딥링크(initial)를 State로 넘겨 initState에서 라우팅.
class MyApp extends StatefulWidget  {
    final DeeplinkResult? initial;
  const MyApp(this.initial,{super.key});

  // _MyAppState에서 스트림 구독·초기 URL 라우팅 담당.
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // 앱 실행 중 이후 들어오는 딥링크(핫 스타트 등) 구독.
  StreamSubscription<DeeplinkResult>? _deeplinkSub;

  /// 스트림으로 들어온 딥링크 이벤트를 UI에 표시.
  final TextEditingController _deeplinkStreamLogController =
      TextEditingController(text: 'TagWorks 딥링크 스트림 대기 중…');

  // 초기 URL postFrame 라우팅 + 플러그인 딥링크 스트림 구독.
  @override
  void initState() {
    super.initState();

    final initialUrl = widget.initial?.deeplinkURL;
    final isTagWorksDeeplink = widget.initial?.isTagWorksDeeplink;
    if (initialUrl != null) {
      print('[deeplink] initState initialUrl=$initialUrl (postFrame에서 라우팅)');
      if (isTagWorksDeeplink != null && isTagWorksDeeplink) {
        // TagManager를 설정해 만든 딥링크인 경우,
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (mounted) _route(initialUrl);
        });
      } else {
        // TagManager를 설정해 만든 딥링크인 아닌 경우, 예외 처리
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (mounted) _route(initialUrl);
        });
      }
      // 첫 프레임 이후에 라우팅: Navigator가 MaterialApp에 붙은 뒤에 push 가능하도록.

    } else {
      print('[deeplink] initState 초기 URL 없음 initial=${widget.initial}');
    }

    // 런타임 딥링크 스트림 (앱이 이미 떠 있는 상태에서 링크로 재진입 등).
    _deeplinkSub = TagWorksDeeplinkPlugin.stream.listen((event) {
      print(
        '[deeplink] stream event isTagWorks=${event.isTagWorksDeeplink} '
        'url=${event.deeplinkURL}',
      );
      final head =
          '${DateTime.now().toIso8601String()}  $event';
      final lines = [head, ..._deeplinkStreamLogController.text.split('\n')];
      final capped = lines.take(30).join('\n');
      if (mounted) {
        setState(() {
          _deeplinkStreamLogController.text = capped;
          _deeplinkStreamLogController.selection =
              TextSelection.collapsed(offset: 0);
        });
      }
      final url = event.deeplinkURL;
      if (url == null) return;
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) _route(url);
      });
    });
  }

  // 딥링크 스트림 구독 해제.
  @override
  void dispose() {
    _deeplinkSub?.cancel();
    _deeplinkStreamLogController.dispose();
    super.dispose();
  }

  // URL에 'prod' 포함 여부로 홈/상세로 pushNamed 분기(데모).
  void _route(String url) {
    final goDetail = url.contains('prod');
    if (goDetail) {
      navigatorKey.currentState?.pushNamed('/detail');
    } else {
      navigatorKey.currentState?.pushNamed('/');
    }
  }

  // 전역 navigatorKey·옵저버·named routes로 MaterialApp 구성.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // 딥링크에서 Navigator에 직접 pushNamed 하기 위한 전역 키.
      navigatorKey: navigatorKey,
       navigatorObservers: [
        TagWorksNavigatorObserver(),
      ],
      initialRoute: '/',
      routes: {
        '/':(_) => const HomeScreen(),
        '/detail':(_)=> const DetailScreen(),
      },
      builder: (context, child) {
        final bottom = MediaQuery.paddingOf(context).bottom;
        return Stack(
          fit: StackFit.expand,
          children: [
            if (child != null) child,
            Positioned(
              left: 8,
              right: 8,
              bottom: 8 + bottom,
              child: Material(
                elevation: 8,
                borderRadius: BorderRadius.circular(8),
                child: Padding(
                  padding: const EdgeInsets.all(8),
                  child: TextField(
                    controller: _deeplinkStreamLogController,
                    readOnly: true,
                    maxLines: 5,
                    style: const TextStyle(fontSize: 12),
                    decoration: const InputDecoration(
                      labelText: 'TagWorksDeeplinkPlugin.stream',
                      border: OutlineInputBorder(),
                      isDense: true,
                    ),
                  ),
                ),
              ),
            ),
          ],
        );
      },
    );
  }
}

class DetailScreen extends StatelessWidget {
  static const routeName = '/detail';

  const DetailScreen({super.key});

  // 예시 상세 화면: 앱바 + 뒤로가기 버튼.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Detail'),
      ),
      body: Center(
        child: ElevatedButton(onPressed: () {
          Navigator.pop(context);
        }, child: const Text('Back')),
      ),
    );
    
  }
}


class DeepLinkHandler {
  final _appLinks = AppLinks();
  StreamSubscription<Uri>? _sub;
  StreamSubscription? _deeplinkSub;
  String initialLocation = '/';

  // app_links 스트림·초기 링크·TagWorks 이벤트 구독 시작.
  void start() {
    // 앱 실행 중 들어오는 링크 처리
    _sub = _appLinks.uriLinkStream.listen((uri) async {
      print('deeplink : ${uri}');
      if (defaultTargetPlatform == TargetPlatform.android) {
        await _handle(uri);
      }
    });

    // cold start (앱이 완전히 꺼진 상태에서 링크로 실행될 때)
    _appLinks.getInitialLink().then((uri) async {
      print('deeplink1 : ${uri}');
      if (uri != null) {
        await _handle(uri);
      } else {
        if (defaultTargetPlatform == TargetPlatform.android) {
          final deferred = await TagWorksDeeplinkPlugin.handleDeferredDeeplink();
          if (deferred.isTagWorksDeeplink && deferred.deeplinkURL != null) {
            initialLocation = deferred.deeplinkURL!;
            print('deeplink deferred : ${initialLocation}');
          }
        }
      }
    }).catchError((_) {});

    // 딥링크 처리 후 TagWorks로부터 랜딩페이지 파라미터 전달
    _deeplinkSub = TagWorksDeeplinkPlugin.stream.listen((event) {
      debugPrint('HomePage에서만 딥링크 처리: $event');
    });
  }

  // URI를 플러그인에 넘겨 TagWorks 딥링크 결과만 로그(Android 위주).
  Future<void> _handle(Uri uri) async {
    try {
      final result = await TagWorksDeeplinkPlugin.handleDeeplinkWithUri(uri.toString());
      if (result.isTagWorksDeeplink && result.deeplinkURL != null) {
        print('deeplink final: ${result.deeplinkURL}');
      }
    } catch (e) {
      // 예외 발생 시 처리
      print('딥링크 처리 중 오류 발생: $e');
    }
  }

  // app_links 및 TagWorks 이벤트 구독 취소.
  void dispose() {
    _sub?.cancel();
    _deeplinkSub?.cancel();
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  // 웹뷰·초기화 버튼 등 예제 UI 상태는 _HomeScreen에서 관리.
  @override
  State<HomeScreen> createState() => _HomeScreen();
}

class _HomeScreen extends State<HomeScreen> {
  String _platformVersion = 'Unknown';
  String? bannerUrl;
  late final WebViewController _controller;
  String _messageFromWeb = "";

  // StreamSubscription? _sub;
  // String? _latestLink;

  // WebView 채널·네비게이션 델리게이트 설정 후 데모 URL 로드.
  @override
  void initState() {
    super.initState();

    // 웹뷰 테스트

    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      // ..runJavaScript("""
      //   window.__TAGWORKS_SDK_READY = true;
      // """)
      ..addJavaScriptChannel(
        TagWorksPlugin.TAGWORKS_WEBVIEW_CHANNEL,
        // "TagWorksFT_JSInterfaces",
        onMessageReceived: (JavaScriptMessage message) async {
          setState(() {
            _messageFromWeb = message.message;
          });
          print("웹뷰 인터페이스 받은 메시지: ${_messageFromWeb}");
          await TagWorksPlugin.webInterfaceDidReceive(_messageFromWeb);
        },
      )
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (String url) async {
            debugPrint("✅ 페이지 로딩 완료: $url");
            await _controller.runJavaScript(
                TagWorksPlugin.TAGWORKS_WEBVIEW_ADD_SCRIPT
            );
            // await _controller.runJavaScript("""
            //   window.__TAGWORKS_SDK_READY = true;
            // """);
          },
        ),
      )
      ..loadRequest(Uri.parse("https://dxlab.obzen.com/html/bnk/BNK_Main.html"));
      // ..loadRequest(Uri.parse("http://192.168.20.53/g5/shop/"));
      // ..loadRequest(Uri.parse("http://192.168.24.185/rshop"));
  }

  // Flutter로 메시지 보내기
  // TagWorksJSInterface.postMessage("Hello from WebView!");

  // 예제에서 공유한 DeepLinkHandler 리소스 정리.
  @override
  void dispose() {
    // _sub?.cancel();
    deepLinkHandler.dispose();
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.

  // TagWorks 초기화·CMS·WebView 등 플러그인 데모 UI.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Row(children: [
                Expanded(
                    child: ElevatedButton(
                  onPressed: () async {
                    try {
                      await TagWorksPlugin.initializeTagWorks(
                        siteId: "165,b1VTZzuL",
                        baseUrl: "https://dxlab.obzen.com/tagworks/obzen",
                        isUseIntervals: false,
                        dispatchIntervalWithSeconds: 5,
                        sessionTimeOutWithSeconds: 5,
                        isManualDispatch: false,
                        // "dispatchRetryCount": 3,
                        appVersion: "1.5",
                        appName: "testapp",
                        isUseDynamicParameter: true,
                        deeplinkServerUrl: "https://dxlab.obzen.com/ozsmlinkg",
                        autoTrackingPage: true,
                        autoTrackingApplication: false,
                      );
                      //print('초기화$result');

                      final isInitialized = await TagWorksPlugin.isInitialize();
                      await TagWorksPlugin.enableTestTool(true);
                      
                      await TagWorksPlugin.setLogLevel(3);
                      await TagWorksPlugin.setOptOut(false);
                      await TagWorksPlugin.setUserId('ny2060');
                      final visitorId = await TagWorksPlugin.getVisitorId();
                      print('visitorId : ${visitorId}');
                      // final siteId = await TagWorksPlugin().getSiteId();
                      // print('siteId:${siteId}');

                      await TagWorksPlugin.setCommonDimensionWithString(3, '계좌관리');
                      await TagWorksPlugin.setCommonDimensionWithDouble(1, 00.9);
                      await TagWorksPlugin.setCommonDimensionWithDouble(11, 3.8888);

                      await TagWorksPlugin.setDynamicCommonDimensionWithString("사용자행동01", '계좌이체');
                      await TagWorksPlugin.setDynamicCommonDimensionWithDouble("사용자행동02", 50000.0);

                      final commonDimensions = await TagWorksPlugin.getCommonDimensions();
                      print('공용 디멘젼 : $commonDimensions');

                      final dynamicCommonDimensions = await TagWorksPlugin.getDynamicCommonDimensions();
                      print('공용 동적 디멘젼 : $dynamicCommonDimensions');

                      final commonDimensionsOfArray = await TagWorksPlugin.getCommonDimensionsOfArrayIndex();
                      print('공용 dimensionsOfArray : ${commonDimensionsOfArray}');

                      final dynamicCommonDimensionsOfArray = await TagWorksPlugin.getDynamicCommonDimensionsOfArrayIndex();
                      print('공용 동적 dimensionsOfArray : ${dynamicCommonDimensionsOfArray}');

                      final dim01 = await TagWorksPlugin.getCommonDimensionWithString(3);
                      print('공용 General : $dim01');

                      final dim02 = await TagWorksPlugin.getCommonDimensionWithDouble(11);
                      print('공용 Fact : $dim02');

                      final dim03 = await TagWorksPlugin.getDynamicCommonDimension("사용자행동01");
                      print('공용 동적 General : $dim03');

                      // await TagWorksPlugin().removeCommonDimensionInGeneralType(3);
                      await TagWorksPlugin.removeCommonDimensionInFactType(1);
                      // await TagWorksPlugin().removeCommonDimensionWithArrayIndex(1);

                      print('공통 디멘젼 : ${await TagWorksPlugin.getCommonDimensions()}');

                      // await TagWorksPlugin().removeAllCommonDimension();
                      // print('공통:${await TagWorksPlugin().getCommonDimensions()}');

                      await TagWorksPlugin.setCommonDimensionWithString(4, '통장');
                      await TagWorksPlugin.setCommonDimensionWithDouble(1, 3333.9);
                      await TagWorksPlugin.setCommonDimensionWithDouble(11, 99.00);

                      await TagWorksPlugin.sendReferrerEventWithOpenUrlString("https://www.naver.com");

                      /**
                       * dataBundle
                       */
                      await DataBundlePlugin.initialize();
                      //await DataBundlePlugin.initDataBundle(null);
                      // print(DataBundlePlugin.);
                      await DataBundlePlugin.putString(DataBundlePlugin.EVENT_TAG_NAME, StandardEvent.PAGE_VIEW);
                      await DataBundlePlugin.putString(DataBundlePlugin.EVENT_TAG_PARAM_PAGE_PATH, '/페이지경로');
                      await DataBundlePlugin.putString(DataBundlePlugin.EVENT_TAG_PARAM_TITLE, '페이지타이틀');
                      await DataBundlePlugin.putString(DataBundlePlugin.EVENT_TAG_PARAM_KEYWORD, '검색어');
                      await DataBundlePlugin.putString(DataBundlePlugin.EVENT_TAG_PARAM_CUSTOM_PATH, '/커스텀경로');
         
                      await DataBundlePlugin.putDimensionWithString(1, "계좌신청");
                      await DataBundlePlugin.putDimensionWithDouble(2, 0.999);

                      await DataBundlePlugin.putDynamicDimensionWithString("사용자행동11", "계좌조회");
                      await DataBundlePlugin.putDynamicDimensionWithDouble("사용자행동22", 998877);

                      final dimensions = await DataBundlePlugin.getDimensions();
                      print('개별 : ${dimensions} ');

                      final dynamicDimensions = await DataBundlePlugin.getDynamicDimensions();
                      print('개별 동적 : ${dynamicDimensions} ');

                      final arrayDimensions = await DataBundlePlugin.getDimensionsOfArrayIndex();
                      print('개별 arrayIndex : ${arrayDimensions} ');

                      final arrayDynamicDimensions = await DataBundlePlugin.getDynamicDimensionsOfArrayIndex();
                      print('개별 동적 arrayIndex : ${arrayDynamicDimensions} ');

                      final dataBundle = await DataBundlePlugin.getDataBundle();
                      print('getDataBundle: ${dataBundle} ');

                      await DataBundlePlugin.initDataBundle(dataBundle);
                      /**
                       * logEvent
                       */
                      await TagWorksPlugin.logEvent(TagWorksPlugin.EVENT_TYPE_PAGE, dataBundle);
                    } catch (e) {
                      print('Failed to initialize TagWorks: $e');
                    }
                  },
                  child: Text('Initialize TagWorks'),
                )),
                const SizedBox(height: 16),

                // === 새로 추가한 onCMS Popup 버튼 ===
                Expanded(
                    child: ElevatedButton(
                  onPressed: () async {
                    try {
                      await TagWorksPopupPlugin.onCMSPopup(
                        onCmsUrl: 'https://dxlab.obzen.com/oncms',
                        rcmdAreaCd: 'POPUP_TEST_AREA',
                        custId: '',
                      );
                      print('onCMS Popup 호출 성공');
                    } catch (e) {
                      print('onCMS Popup 호출 실패: $e');
                    }
                  },
                  child: const Text('Show CMS Popup'),
                )),
                Expanded(
                    child: ElevatedButton(
                  onPressed: () async {
                    // JavaScript 실행
                    await _controller.runJavaScript("""
                      if (window.__TAGWORKS_SDK_READY) {
                        window.TagWorksFT_JSInterfaces.postMessage("ABV");
                      }
                     """);
                  },
                  child: const Text('JSInterface Test'),
                )),
                  const SizedBox(width: 8),
                  // ⭐ 추가 버튼
                  Expanded(
                    child: ElevatedButton(
                      onPressed: () {
                        Navigator.pushNamed(context, '/detail');
                      },
                      child: const Text('화면 이동'),
                    ),
                  ),

              ]),

              const SizedBox(height: 24),
              Text('CMS Banner', style: TextStyle(fontWeight: FontWeight.bold)),
              SizedBox(
                height: 200, // ★ 꼭 사이즈를 주세요(없으면 0으로 안 보임)
                width: double.infinity,
                child: OnCmsBannerWidget(
                  onCmsUrl: 'https://dxlab.obzen.com/oncms',
                  rcmdAreaCd: 'BANNER_OBZ_AREA',
                  custId: '', // 필요 없으면 null
                  defaultImage: 'ic_banner_placeholder', // drawable에 넣어둔 이름
                ),
              ),

              // webview 테스트
              const SizedBox(height: 4),
              // WebView
              const Text('WebView', style: TextStyle(fontWeight: FontWeight.bold)),
              SizedBox(
                height: 500, // 웹뷰 화면 높이 지정
                child: WebViewWidget(controller: _controller),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
0
likes
105
points
311
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Official Flutter SDK for TagWorks, providing deep linking, event tracking, and user engagement features for Android and iOS.

Homepage
Repository

License

unknown (license)

Dependencies

flutter, plugin_platform_interface, webview_flutter

More

Packages that depend on tagworks_sdk_flutter

Packages that implement tagworks_sdk_flutter