AdStage DeepLink Flutter Plugin
AdStage 딥링크 기능을 Flutter 앱에서 사용할 수 있도록 하는 플러그인입니다.
🚀 에어브릿지 방식 - 중요한 설정
⚠️ 반드시 MainActivity에서 AdStage API 키를 설정해야 합니다!
이 플러그인은 라이프사이클 문제를 해결하기 위해 에어브릿지 방식을 사용합니다. MainActivity에서는 간단히 API 키만 설정하고, 딥링크 처리는 Flutter 플러그인에서 담당합니다.
📋 필수 설정
0. iOS 자동 의존성 관리
iOS에서는 CocoaPods를 통해 자동으로 의존성이 관리됩니다:
AdapterAdStage 3.0.1- CocoaPods를 통해 자동 설치- 더 이상 수동 Framework 추가가 필요하지 않습니다
# ios/nbase_ad_flutter_sdk.podspec (자동 포함됨)
s.dependency 'AdapterAdStage', '3.0.1'
⚠️ iOS 필수 설정: Apollo SPM 추가
중요: NBase.xcframework에서 Apollo 모듈이 필요하므로 반드시 Swift Package Manager로 추가해야 합니다.
1. Xcode에서 프로젝트 열기
cd ios && open Runner.xcworkspace
2. Package Dependencies 추가
- Runner 프로젝트 선택
- Package Dependencies 탭 클릭
- + 버튼 클릭
- Add Package Dependency 선택
- URL 입력:
https://github.com/apollographql/apollo-ios.git - Up to Next Major:
1.0.0선택 - Add Package 클릭
3. Package Products 추가
Choose Package Products for apollo-ios.git 에서:
- Apollo →
Runner타겟에 추가 ✅ - ApolloAPI →
Runner타겟에 추가 ✅ - 나머지는
None으로 설정
4. 확인
Package Dependencies에 다음이 추가되었는지 확인:
✅ apollo-ios (1.x.x)
└── Apollo (Runner)
└── ApolloAPI (Runner)
1. Android MainActivity 설정
android/app/src/main/kotlin/.../MainActivity.kt 파일을 다음과 같이 수정하세요:
package com.example.your_app
import android.content.Intent
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import com.nbase.sdk.AdStage
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ⚠️ 필수: AdStage API Key 설정 (에어브릿지 방식)
AdStage.setApiKey("your-api-key-here")
Log.d("AdStage", "✅ API Key 설정 완료 (에어브릿지 방식)")
// 딥링크 Intent 처리 (선택사항 - 플러그인에서 자동 처리됨)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent?) {
intent?.data?.let { uri ->
Log.d("AdStage", "🔗 MainActivity에서 딥링크 수신: $uri")
// Flutter 플러그인에서 자동으로 처리됨
}
}
}
2. iOS AppDelegate 설정 (선택사항)
ios/Runner/AppDelegate.swift 파일을 다음과 같이 수정하세요:
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// ⚠️ 필수: AdStage API Key 설정 (에어브릿지 방식)
// 주의: Apollo SPM 추가 후에만 이 코드가 동작합니다
// AdStage.shared.setApiKey("your-api-key-here")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
참고: iOS에서는 Flutter 플러그인이 자동으로 API 키를 설정하므로 AppDelegate 설정은 선택사항입니다.
2. iOS 설정 (AppDelegate 수정 불필요!)
✅ 새로운 방식: iOS에서는 AppDelegate 수정이 전혀 필요 없습니다!
플러그인이 자동으로 모든 초기화와 딥링크 처리를 담당합니다.
특징:
- ✅ AppDelegate 수정 없음 - 기존 AppDelegate 그대로 사용
- ✅ 자동 초기화 - Flutter 플러그인에서 모든 설정 자동 처리
- ✅ Runtime 로딩 - NBase SDK를 동적으로 로드하여 컴파일 의존성 제거
- ✅ 완전 자동화 - API 키 설정부터 딥링크 처리까지 플러그인에서 담당
// ✅ AppDelegate.swift 수정 불필요!
// 기존 AppDelegate 그대로 사용하면 됩니다.
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
🎯 모든 초기화는 플러그인에서 자동 처리:
- API 키 설정
- NBase SDK 동적 로딩
- 딥링크 리스너 등록
- URL Scheme 처리
- Universal Link 처리
3. iOS Info.plist 설정
**ios/Runner/Info.plist**에 딥링크 스킴 추가:
<!-- AdStage 딥링크 스킴 설정 -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.adstage.deeplink</string>
<key>CFBundleURLSchemes</key>
<array>
<string>adstage</string>
<string>com.nbase.main</string>
</array>
</dict>
</array>
4. Android AndroidManifest.xml 설정
**android/app/src/main/AndroidManifest.xml**에 딥링크 스킴 추가:
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- 기본 인텐트 필터 -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- AdStage 딥링크 처리 -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="your_app_scheme" /> <!-- 🔑 여기에 실제 앱 스킴 입력 -->
</intent-filter>
<!-- AdStage 웹 딥링크 처리 -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="your_domain.adg.im" /> <!-- 🔑 여기에 실제 도메인 입력 -->
</intent-filter>
</activity>
🔧 Flutter 사용법
1. 패키지 설치
dependencies:
adstage_deeplink: ^1.0.0
2. 기본 사용법
import 'package:adstage_deeplink/adstage_deeplink.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
StreamSubscription<AdStageDeepLinkEvent>? _deepLinkSubscription;
@override
void initState() {
super.initState();
// 자동으로 Flutter 리스너 설정
WidgetsBinding.instance.addPostFrameCallback((_) {
_setupFlutterListener();
});
}
Future<void> _setupFlutterListener() async {
try {
// 🎯 크로스 플랫폼 방식: 플러그인에서 모든 초기화 자동 처리
// - Android: MainActivity에서 AdStage.setApiKey() 이미 완료
// - iOS: 플러그인에서 Runtime 로딩 및 API 키 설정 자동 처리
await AdstageDeeplink.initialize(
apiKey: 'your_api_key_here', // iOS에서 사용, Android에서는 무시됨
);
print('AdStage 초기화 완료 (크로스 플랫폼)');
} catch (e) {
print('AdStage 초기화 실패: $e');
}
}
void _setupDeepLinkListener() {
_deepLinkSubscription = AdstageDeeplink.onDeepLinkReceived.listen(
(event) {
print('딥링크 수신: ${event.path}');
print('파라미터: ${event.parameters}');
// 딥링크에 따른 화면 네비게이션
_navigateToScreen(event.path, event.parameters);
},
onError: (error) {
print('딥링크 수신 오류: $error');
},
);
}
void _navigateToScreen(String path, Map<String, dynamic> parameters) {
// 실제 앱에서는 라우터/네비게이션 로직 구현
switch (path) {
case '/product':
// 상품 상세 페이지로 이동
final productId = parameters['product_id'];
Navigator.pushNamed(context, '/product', arguments: productId);
break;
case '/event':
// 이벤트 페이지로 이동
Navigator.pushNamed(context, '/event');
break;
default:
// 기본 홈 페이지
Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false);
}
}
@override
void dispose() {
_deepLinkSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AdStage DeepLink Demo',
home: MyHomePage(),
);
}
}
🌟 주요 기능
1. 딥링크 생성
Future<void> createDeepLink() async {
try {
final result = await AdstageDeeplink.createDeepLink(
name: 'Product Deep Link',
description: 'Link to product page',
shortPath: 'product123',
channel: 'social',
campaign: 'summer_sale',
parameters: {
'product_id': '12345',
'category': 'electronics',
'user_id': 'user_67890',
},
androidPackageName: 'com.example.myapp',
androidAppScheme: 'myapp',
iosAppStoreId: '123456789',
iosAppScheme: 'myapp',
webUrl: 'https://myapp.com/product/12345',
);
print('딥링크 생성 완료: ${result.shortUrl}');
} catch (e) {
print('딥링크 생성 실패: $e');
}
}
2. 프로모션 열기
Future<void> openPromotion() async {
try {
final result = await AdstageDeeplink.openPromotion(
bannerType: 'NATIVE',
targetAudience: 'new_user',
deviceType: 'HIGH_END',
region: 'KR',
limit: 10,
showTodayButton: true,
);
print('프로모션 열기 완료: ${result.url}');
} catch (e) {
print('프로모션 열기 실패: $e');
}
}
3. 이벤트 추적
Future<void> trackEvent() async {
try {
await AdstageDeeplink.trackEvent(
eventName: 'product_view',
eventData: {
'product_id': '12345',
'category': 'electronics',
'price': '299000',
},
);
print('이벤트 추적 완료');
} catch (e) {
print('이벤트 추적 실패: $e');
}
}
🛠️ 디버깅 팁
1. 로그 확인
# Android 로그 확인
adb logcat | grep -E "(AdstageDeeplinkPlugin|MainActivity|NBaseSDK:AdStage)"
# Flutter 로그 확인
flutter logs
2. 딥링크 테스트
# ADB를 통한 딥링크 테스트
adb shell am start -W -a android.intent.action.VIEW -d "myapp://product/12345" com.example.myapp
# 웹 딥링크 테스트
adb shell am start -W -a android.intent.action.VIEW -d "https://mydomain.adg.im/product123" com.example.myapp
🎯 새로운 방식의 장점
✅ 크로스 플랫폼 지원: Android & iOS 완벽 지원
✅ iOS AppDelegate 수정 불필요: 플러그인에서 Runtime 로딩으로 모든 것 자동 처리
✅ 완벽한 라이프사이클 처리: 앱 시작 시점부터 딥링크 처리
✅ Install Referrer 지원: 첫 설치 시 자동 처리 (Android)
✅ 백그라운드→포그라운드: 모든 상황에서 딥링크 처리
✅ 자동 초기화: Flutter 앱 시작과 동시에 리스너 등록
✅ 직접 처리: Flutter 플러그인에서 바로 네이티브 SDK 접근
✅ 간단한 네이티브 코드: processPendingDeepLink 같은 복잡한 메소드 불필요
✅ Universal Link 지원: iOS Universal Link 완벽 지원
✅ URL Scheme 지원: Android Intent & iOS URL Scheme 지원
✅ 타이밍 문제 해결: 네이티브 ↔ Flutter 간 완벽한 동기화
✅ 성능 최적화: 네이티브 수준의 빠른 처리
✅ 안정성: 검증된 에어브릿지 방식 사용
✅ 컴파일 의존성 제거: iOS Runtime 로딩으로 framework 링킹 문제 해결
✅ 완전 자동화: 개발자가 네이티브 코드 수정할 필요 없음
🔄 간단해진 구조 (v2.1)
🤖 Android (간단함):
🚀 새로운 방식:
1. MainActivity.onCreate() ← AdStage.setApiKey() (API 키 설정만)
2. Flutter 플러그인 시작 ← AdstageDeeplink.initialize() (리스너 등록)
3. 플러그인이 Activity Intent 직접 접근 ← activity.getIntent()
4. Flutter 얼럿 표시 🎨 ← 완벽한 딥링크 수신!
🍎 iOS (더 간단함):
🚀 새로운 방식:
1. AppDelegate ← 수정 불필요! (기존 그대로 사용)
2. Flutter 플러그인 시작 ← AdstageDeeplink.initialize() (런타임 로딩 + API 키 설정)
3. 플러그인이 URL 자동 처리 ← Runtime SDK 접근
4. Flutter 얼럿 표시 🎨 ← 완벽한 딥링크 수신!
vs 기존 방식 (복잡함):
❌ 기존 방식:
1. MainActivity.onCreate() ← AdStage.setApiKey() + handleDeepLinkIntent()
2. AppDelegate ← import NBase + AdStage.setApiKey() + 컴파일 의존성 문제
3. Flutter 플러그인 ← processPendingDeepLink() 리플렉션 호출
4. MainActivity ← 저장된 Intent 재처리
5. Flutter 얼럿 표시
핵심 개선:
- ❌ processPendingDeepLink() 메소드 불필요
- ❌ pendingIntent 저장 불필요
- ❌ 리플렉션 호출 불필요
- ❌ iOS AppDelegate 수정 불필요
- ❌ 컴파일 의존성 문제 완전 해결
- ✅ Flutter 플러그인에서 직접
activity.getIntent()접근 - ✅ iOS Runtime 로딩으로
NSClassFromString()동적 접근 - ✅ MainActivity는 API 키 설정만 담당 (깔끔)
📚 API 문서
새로운 방식 (권장)
AdstageDeeplink.initialize()
static Future<void> initialize({required String apiKey})
크로스 플랫폼 초기화 메소드. Android와 iOS에서 각각 최적화된 방식으로 동작합니다.
플랫폼별 동작:
- Android: MainActivity에서 AdStage.setApiKey()가 이미 호출되었으므로 리스너만 등록
- iOS: 플러그인에서 Runtime 로딩으로 NBase SDK 접근 후 API 키 설정
특징:
- ✅ 크로스 플랫폼: Android & iOS 모두 지원
- ✅ iOS AppDelegate 수정 불필요: Runtime 로딩으로 자동 처리
- ✅ 대기 중인 딥링크 자동 처리: Cold Start 딥링크 완벽 지원
- ✅ 타이밍 문제 완전 해결: 네이티브 ↔ Flutter 동기화
- ✅ 컴파일 의존성 제거: iOS에서 import 없이 동적 접근
// 크로스 플랫폼 초기화
await AdstageDeeplink.initialize(
apiKey: 'your_api_key_here', // iOS에서 사용, Android에서는 무시됨
);
기존 방식 (하위 호환성)
AdstageDeeplink.setupListener()
static Future<void> setupListener()
하위 호환성을 위한 메소드. 내부적으로 initialize()를 호출합니다.
참고: API 키가 없으므로 iOS에서는 제대로 동작하지 않을 수 있습니다.
// 하위 호환성을 위해 지원 (권장하지 않음)
await AdstageDeeplink.setupListener();
공통 API
AdstageDeeplink.onDeepLinkReceived
static Stream<AdStageDeepLinkEvent> get onDeepLinkReceived
딥링크 이벤트를 수신하는 스트림입니다.
AdstageDeeplink.onDeepLinkReceived.listen((event) {
print('딥링크 수신: ${event.path}');
print('파라미터: ${event.parameters}');
});
AdStageDeepLinkEvent
class AdStageDeepLinkEvent {
final String type; // 이벤트 타입 (예: 'deeplink')
final String path; // 딥링크 경로
final Map<String, String> parameters; // 쿼리 파라미터
final String eventType; // 이벤트 종류 ('OPEN' 또는 'INSTALL')
}
🤝 기술 지원
문의사항이 있으시면 다음으로 연락주세요:
- 이메일: [email protected]
- 문서: https://docs.adstage.io
📄 라이센스
MIT License
🧪 딥링크 테스트 방법
🎉 v2.1 업데이트: 이제 Flutter 플러그인에서 직접 Activity Intent를 처리하여 더욱 간단하고 안정적입니다!
1. ADB 명령어로 딥링크 테스트
# AdStage 스킴 테스트 (기본)
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://test" \
com.example.adstage_deeplink_example
# 파라미터가 포함된 딥링크 테스트
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://campaign/123?utm_source=test&utm_campaign=flutter&user_id=12345" \
com.example.adstage_deeplink_example
# NBase 스킴 테스트
adb shell am start -W -a android.intent.action.VIEW \
-d "com.nbase.main://product?id=456&category=electronics" \
com.example.adstage_deeplink_example
# 🧊 Cold Start 테스트 (앱 완전 종료 상태에서)
adb shell am force-stop com.example.adstage_deeplink_example
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://cold_start_test?timestamp=$(date +%s)" \
com.example.adstage_deeplink_example
# iOS 딥링크 테스트 (시뮬레이터)
xcrun simctl openurl booted "adstage://ios_test?platform=ios×tamp=$(date +%s)"
# iOS 딥링크 테스트 (실제 디바이스 - Safari에서)
# Safari에서 다음 URL 입력:
# adstage://ios_device_test?platform=ios&source=safari
2. 🎯 예상되는 결과
딥링크 수신 시 Flutter 얼럿이 자동으로 표시됩니다:
🎨 Flutter 얼럿 (어플리케이션 레벨)
- 제목: "🔗 딥링크 수신" (아이콘 포함)
- 상세 정보:
- 타입:
deeplink - 경로: 딥링크 경로 (예:
/test,/campaign/123) - 이벤트 타입:
OPEN(일반) 또는INSTALL(첫 설치) - 파라미터: 딥링크에 포함된 모든 쿼리 파라미터
- 타입:
- 버튼: "로그 출력", "확인"
📱 추가 피드백
- SnackBar: 하단에 초록색 성공 메시지
- 콘솔 로그: 각 단계별 상세 로그 출력
3. 🔍 로그 확인
# 전체 AdStage 관련 로그
adb logcat | grep -E "(MainActivity|AdstageDeeplinkPlugin|NBaseSDK:AdStage)"
# MainActivity 로그만
adb logcat | grep "MainActivity"
# Flutter 플러그인 로그만
adb logcat | grep "AdstageDeeplinkPlugin"
4. 📱 다양한 시나리오 테스트
# 1. 앱이 실행 중일 때 (Warm Start)
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://warm_start?scenario=running" \
com.example.adstage_deeplink_example
# 2. 앱이 백그라운드에 있을 때
# (먼저 홈 버튼을 눌러 앱을 백그라운드로 보낸 후)
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://background_to_foreground?scenario=background" \
com.example.adstage_deeplink_example
# 3. 앱이 완전히 종료된 상태에서 (Cold Start)
adb shell am force-stop com.example.adstage_deeplink_example
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://cold_start?scenario=terminated" \
com.example.adstage_deeplink_example
# 4. 복잡한 파라미터 테스트
adb shell am start -W -a android.intent.action.VIEW \
-d "adstage://test?user_id=12345&product_id=67890&campaign=summer_sale&utm_source=facebook&utm_medium=social&custom_param=special_value" \
com.example.adstage_deeplink_example
5. ✅ 성공 지표
다음 사항들이 모두 확인되면 정상 동작:
- 앱 자동 시작: 딥링크 클릭 시 앱이 즉시 실행됨
- Flutter 얼럿: 상세한 딥링크 정보가 예쁘게 표시됨
- 로그 출력: 각 단계별 로그가 정상적으로 출력됨
- SnackBar: 하단에 초록색 성공 메시지 표시됨
- Cold Start 지원: 앱이 완전히 종료된 상태에서도 정상 동작
6. 🐛 트러블슈팅
만약 딥링크가 동작하지 않는다면:
# 1. 앱이 설치되어 있는지 확인
adb shell pm list packages | grep adstage_deeplink_example
# 2. Intent Filter가 제대로 등록되었는지 확인
adb shell dumpsys package com.example.adstage_deeplink_example | grep -A 5 -B 5 "adstage"
# 3. 앱을 완전히 재설치
flutter clean
flutter build apk
flutter install
🐛 iOS 초기화 실패 디버깅 가이드
iOS에서 "AdStage 클래스를 찾을 수 없다"는 오류가 발생할 때 다음 단계를 따라 해결하세요:
1. 상세 디버깅 로그 확인
Flutter 앱을 실행하고 Xcode 콘솔에서 다음 로그를 확인하세요:
// 초기화 시도 시 나타나는 로그들
🔧 [AdStage] NBase SDK 초기화 시작...
🔍 [AdStage] 클래스 시도: AdStage
🔍 [AdStage] 클래스 시도: NBase.AdStage
🔍 [AdStage] 클래스 시도: AdStageManager
// ... 더 많은 디버깅 정보
2. Framework 링킹 확인
콘솔에서 다음을 확인하세요:
# Xcode 콘솔에서 확인할 내용
📦 Main Bundle: /path/to/app
📱 로드된 이미지 수: XXX
✅ Framework 발견: /path/to/NBase.framework
✅ Framework 발견: /path/to/AdapterAdStage.framework
만약 Framework가 발견되지 않으면:
3. CocoaPods 재설치
cd ios
rm -rf Pods
rm Podfile.lock
pod install --repo-update
4. Framework 파일 확인
# 플러그인 폴더에서 framework 파일이 있는지 확인
ls -la ~/.pub-cache/hosted/pub.dev/adstage_deeplink-*/ios/Frameworks/
# 또는 로컬에서
ls -la ios/Frameworks/
# 다음 파일들이 있어야 함:
# - NBase.xcframework/
# - AdapterAdStage.xcframework/
5. iOS Deployment Target 확인
ios/Podfile에서:
platform :ios, '15.0' # 최소 15.0이어야 함
6. 수동 Framework 추가 (최후 수단)
- Xcode에서 프로젝트 열기
- Runner 타겟 선택
- General → Frameworks, Libraries, and Embedded Content
- + 버튼 클릭
- Add Other... → Add Files
- 다음 framework 파일들 추가:
NBase.xcframeworkAdapterAdStage.xcframework
- Embed & Sign으로 설정
7. 에러별 해결 방법
"모든 AdStage 클래스명 시도 실패"
❌ [AdStage] 모든 클래스명 시도 실패
❌ [AdStage] 가능한 원인:
- NBase.xcframework가 앱에 제대로 링크되지 않음
- AdapterAdStage.xcframework가 앱에 제대로 링크되지 않음
해결 방법: CocoaPods 재설치 후 Clean Build
"Framework 발견되지 않음"
📱 로드된 이미지 수: 150
❌ Framework 발견되지 않음
해결 방법: 수동 Framework 추가
"shared 메서드 미지원"
⚠️ [AdStage] shared 메서드 미지원: AdStage
해결 방법: Framework 버전 확인 및 업데이트
8. 최종 테스트
정상 동작 시 다음과 같은 로그가 출력됩니다:
✅ [AdStage] 클래스 발견: AdStage -> <NBase.AdStage>
✅ [AdStage] NSObject 타입 캐스팅 성공: AdStage
✅ [AdStage] shared 셀렉터 응답 가능: AdStage
✅ [AdStage] shared 인스턴스 획득 성공: AdStage
🔍 [AdStage] 사용 가능한 메서드 확인:
✅ setApiKey:
✅ setUnifiedListener:
✅ createDeepLink
✅ handleDeepLink:
✅ handleUniversalLink:
✅ [AdStage] API key 설정 완료
✅ [AdStage] 리스너 설정 완료
9. 문제 신고
위 모든 단계를 시도해도 문제가 해결되지 않으면, 다음 정보와 함께 문의하세요:
- iOS 버전
- Xcode 버전
- Flutter 버전
- 전체 콘솔 로그
- Podfile.lock 내용