visual_reward 1.3.0 copy "visual_reward: ^1.3.0" to clipboard
visual_reward: ^1.3.0 copied to clipboard

Tenqube Visual Reward SDK for Flutter. A reward-ad webview SDK built on flutter_inappwebview for Android and iOS.

Flutter #

Flutter InAppWebView 기반 리워드 광고 SDK입니다.

요구사항 #

  • Flutter 3.24+
  • Dart 3.5+
  • iOS 13.0+
  • Android minSdk 21 (Flutter 3.35+ 앱은 기본값이 24)

설치 #

pub.dev #

dependencies:
  # visual_reward SDK
  visual_reward: ^1.2.0

  # GMA SDK — 호스트가 지정한 버전을 그대로 사용합니다. SDK 는 버전을 강제하지 않습니다.
  # 이 플러그인이 양 플랫폼에 GMA 를 링크하며, 별도 네이티브 설정(gradle·Podfile)은 필요 없습니다.
  google_mobile_ads: ^9.0.0

광고 엔진(Rewarded/Interstitial)은 visual_reward 가 자체 보유하고 초기화까지 책임집니다. 호스트가 제공해야 하는 것은 위의 GMA SDK 와 AdMob App ID 뿐입니다 — 아래 「GMA SDK」 절을 참고하세요.

GMA 버전별 동작 #

호스트 GMA 광고 기능
google_mobile_ads 5.3.x 이상 정상 동작
google_mobile_ads 5.3.x 미만 비활성 (로그로 안내, 크래시 없음)
미링크 비활성 (로그로 안내, 크래시 없음)

App ID #

  • 호스트 앱에 AdMob/Ad Manager App ID가 필요합니다. ID가 없는 경우 요청주시기 바랍니다.
  • App ID가 누락되면 앱 시작 시 크래시가 발생합니다.
  1. AndroidManifest.xml

    <application>
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
    </application>
    
  2. Info.plist

    <!-- App ID 누락 시 시작 크래시 (AdMob 또는 Ad Manager App ID) -->
    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy</string>
    
    <!-- IDFA/ATT 사용 목적 문자열 -->
    <key>NSUserTrackingUsageDescription</key>
    <string>맞춤형 광고 제공을 위해 기기 식별자를 사용합니다.</string>
    
    <!-- SKAdNetwork (Google 제공 식별자) -->
    <key>SKAdNetworkItems</key>
    <array><!-- ... --></array>
    

    ATT 권한 요청은 SDK가 웹뷰 로드 전 네이티브 ATTrackingManager로 자동 처리합니다. 이미 권한이 결정된 경우 팝업 없이 즉시 진행하며, NSUserTrackingUsageDescription이 없으면 요청을 스킵하고 바로 로드합니다.

app-ads.txt #

  • 앱 스토어 등록정보의 개발자 웹사이트 도메인 루트 app-ads.txt에 전달받은 목록을 그대로 복사하여 게시해주세요.

시퀀스 다이어그램 #

sequenceDiagram
    title interaction VisualReward SDK

    participant A as Host App
    participant B as VisualReward SDK
    participant C as VisualReward 서버
    participant D as WebView 화면

    A->>B: initialize(appKey, ...)
    B->>C: config 요청
    C-->>B: config 응답
    B-->>A: onSuccess()

    A->>B: setUserId(userId)

    A->>B: open(serviceName, ...)
    B->>D: 웹뷰 열기

    D->>B: 웹뷰 닫힘
    B-->>A: onClose

사용법 #

디버그 설정 #

  • initialize() 전에 호출합니다.

    import 'package:visual_reward/visual_reward.dart';
    
    VisualReward.setDebugEnabled(kDebugMode);
    

초기화 #

  • main() 또는 앱 시작 시 한 번만 호출합니다.

    import 'package:flutter/widgets.dart';
    import 'package:visual_reward/visual_reward.dart';
    
    var rewardReady = false;
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
    
      // 광고 엔진(GMA 초기화 포함)까지 이 호출이 함께 수행합니다.
      // 호스트는 MobileAds 를 직접 초기화하지 않습니다 — SDK 가 대신 수행하고 완료를 기다립니다.
      // 필요한 것은 App ID 뿐입니다.
      VisualReward.initialize(
        appKey: 'tq_live_xxx',                // 발급된 app_key
        adTestMode: false,                    // true 면 테스트 광고만 노출
        timeout: const Duration(seconds: 5),  // 기본값
        onSuccess: () => rewardReady = true,
        onFailure: (e) { /* 초기화 실패 */ },
      );
    
      runApp(const MyApp());
    }
    
  • VisualReward.initialize 파라미터

    파라미터 타입 필수 설명 기본값
    appKey String ✅ stage별 app_key 발급 요청이 필요합니다.
    adTestMode bool 테스트 광고 노출 여부. 광고 엔진 첫 초기화 시점의 값만 적용됩니다 false
    timeout Duration 초기화 완료 대기 시간. 초과 시 VisualRewardInitializeTimeoutError 발생 Duration(seconds: 5)
    onSuccess VoidCallback? 초기화 성공 콜백 null
    onFailure void Function(VisualRewardError)? 초기화 실패 콜백 null

    onSuccess/onFailure 는 리워드 설정 로드 결과에 대한 콜백입니다. 광고 엔진 초기화는 백그라운드에서 진행되며 실패해도 리워드 기능은 정상 동작합니다(광고만 비활성). 광고 엔진 상태는 VisualReward 로그 태그로 확인할 수 있습니다.

    광고용 도메인은 앱이 지정하지 않습니다. appKey 로 조회하는 서버 설정의 ezoic.adDomain 값을 사용하며, 설정에 값이 없으면 광고 기능만 비활성됩니다.

    동의 관리(TCF v2 / GPP / US Privacy)는 SDK 가 SharedPreferences(Android) · UserDefaults(iOS) 에서 자동으로 읽습니다. 디버그 로그는 setDebugEnabled() 값이 광고 엔진에도 함께 적용됩니다.

    Rewarded / Interstitial 광고는 웹 페이지가 요청합니다. 호스트가 광고를 직접 로드·표시하는 코드는 필요하지 않습니다.

사용자 설정 #

  • 로그인 후 또는 사용자가 변경될 때 호출합니다. open() 전에 반드시 호출해야 합니다.

    VisualReward.setUserId(user.id);
    

웹뷰 열기 #

  • initialize() 후에 호출합니다.

    import 'package:visual_reward/visual_reward.dart';
    
    VisualReward.open(
      context: context,
      serviceName: 'reward_home',
      locale: 'ko',
      extra: null,
      onClose: () { /* 웹뷰 닫힘 */ },
      onError: (e) { /* 열기 실패 */ },
    );
    
  • open 파라미터

    파라미터 타입 필수 설명 기본값
    context BuildContext ✅ 화면을 열 BuildContext
    serviceName String ✅ 사용 서비스별 serviceName 전달 예정입니다.
    locale String? BCP 47 (RFC 5646) 언어 서브태그(ISO 639-1, 2자리 소문자)를 사용 "ko"
    extra String? 포스트백 추가 데이터 (JSON serialize된 문자열) null
    onClose VoidCallback? 웹뷰가 닫힐 때 호출되는 콜백 null
    onError void Function(VisualRewardError)? 에러 발생 시 호출되는 콜백 null

AdPopcorn 브릿지 등록 #

  • AdPopcorn SDK(adpopcornssp_flutter)를 사용하는 경우 open 호출 전에 등록합니다.

    import 'package:adpopcornssp_flutter/adpopcornssp_flutter.dart';
    
    VisualReward.setAdPopcornBridgeHandler(AdPopcornInAppWebViewBridgeHandler());
    

호스트 WebView 브릿지 #

호스트 앱이 직접 소유한 WebView 의 웹 페이지에서 리워드 웹뷰를 열 수 있습니다. 리워드 웹뷰(SDK 소유)에는 필요 없습니다 — 이미 자체 브릿지를 갖고 있습니다.

1. 네이티브: 브릿지 부착 #

import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:visual_reward/visual_reward.dart';

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

  @override
  State<HostWebViewPage> createState() => _HostWebViewPageState();
}

class _HostWebViewPageState extends State<HostWebViewPage> {
  InAppWebViewController? _controller;

  @override
  void dispose() {
    final controller = _controller;
    if (controller != null) VisualReward.detachWebBridge(controller);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return InAppWebView(
      initialUrlRequest: URLRequest(url: WebUri('https://your-page.example.com')),
      onWebViewCreated: (controller) {
        _controller = controller;
        // 페이지 로드 이전에 부착합니다.
        VisualReward.attachWebBridge(controller: controller, context: context);
      },
    );
  }
}
파라미터 타입 필수 설명
controller InAppWebViewController ✅ 브릿지를 붙일 호스트 WebView 컨트롤러
context BuildContext ✅ 리워드 웹뷰를 열 BuildContext

attachWebBridge 는 페이지 로드 이전에 호출해야 합니다. flutter_inappwebview 의 핸들러는 등록 이후에 만들어지는 문서에만 주입되므로, 이미 로드된 페이지에는 다시 로드하기 전까지 나타나지 않습니다.

detachWebBridge 를 잊지 마세요. 핸들러가 컨트롤러에 남아 있으면 사라진 화면의 BuildContext 로 리워드 웹뷰를 열려고 시도합니다.

initialize() · setUserId() 를 앱에서 부르지 않아도 됩니다. 웹에서 appKey·userId 를 넘기면 브릿지가 초기화 → 사용자 설정 → 웹뷰 열기를 한 번에 처리합니다.

2. 웹: 핸들러 호출 #

window.flutter_inappwebview.callHandler('visualRewardBridge', JSON.stringify({
  appKey: 'app_key',          // 필수 — 발급된 app_key
  userId: 'u-123',            // 필수 — 리워드 귀속 사용자
  serviceName: 'anyService',  // 필수 — 실행 serviceName(전달 예정)
  locale: 'ko',               // 선택 — 기본 "ko"
  extra: '',                  // 선택 — 포스트백 추가 데이터(JSON serialize된 문자열)
  adTestMode: false,          // 선택 — true 면 테스트 광고만 노출. 기본 false
  timeoutMs: 5000,            // 선택 — 설정 조회 대기 한도(ms). 기본 5000
}));

객체를 그대로 넘겨도 됩니다 — callHandler('visualRewardBridge', { appKey: 'app_key', ... }).

필드 타입 필수 설명 기본값
appKey string ✅ 발급된 app_key
userId string ✅ 리워드 귀속 사용자
serviceName string ✅ 실행 serviceName(전달 예정)
locale string BCP 47 언어 서브태그 "ko"
extra string 포스트백 추가 데이터 (JSON serialize된 문자열) ""
adTestMode boolean 테스트 광고 노출 여부 false
timeoutMs number 설정 조회 대기 한도(ms). 초과 시 INITIALIZE_TIMEOUT 5000

adTestMode 는 광고 엔진이 처음 초기화될 때의 값만 적용됩니다. 앱에서 이미 initialize() 로 초기화했거나 앞선 브릿지 호출로 초기화된 뒤라면 이후 값은 무시됩니다.

응답 콜백은 페이지에서 전역 객체로 등록합니다.

window.visualRewardCallback = {
  onClose: function () {},                // 리워드 웹뷰 닫힘
  onError: function (code, message) {},
};

onError 의 code 는 네이티브 에러 타입에 대응합니다.

code 의미
NETWORK_ERROR 설정 조회 네트워크 오류
INITIALIZE_TIMEOUT 초기화 완료 대기 시간 초과
INVALID_APP_KEY 존재하지 않는 app_key (404)
SERVER_ERROR 설정 서버 오류 (200/404 외 응답)
PARSE_ERROR 설정 응답 파싱 실패
NOT_INITIALIZED 초기화 전 열기 시도
USER_ID_NOT_SET userId 없이 열기 시도
INVALID_PAYLOAD 브릿지 자체 — 필수 키 누락·JSON 파싱 실패

브릿지가 주입됐는지 확인하고 호출하세요.

if (window.flutter_inappwebview && window.flutter_inappwebview.callHandler) {
  window.flutter_inappwebview.callHandler('visualRewardBridge', JSON.stringify({ /* ... */ }));
}

3. 호출 가능한 페이지 — 허용 오리진 #

appKey 로 조회한 설정의 allowedDomains 에 호출한 페이지의 오리진이 포함돼야 실행됩니다. 검증에 실패하면 아무 것도 하지 않고 로그만 남깁니다(어떤 app_key가 어떤 오리진을 허용하는지 탐색할 수 있는 신호를 웹에 주지 않기 위해 콜백도 호출하지 않습니다).

  • 오리진은 최상위 페이지 URL 로 판정합니다. 같은 오리진 iframe 은 통과합니다
  • 검증을 통과하기 전에는 SDK 상태(설정·사용자·광고 엔진)를 바꾸지 않습니다
  • file:// 로 로드한 페이지는 오리진 호스트가 비어 있어 항상 거부됩니다

에러 처리 #

에러 타입 #

타입 설명
VisualRewardNetworkError 네트워크 연결 실패
VisualRewardInitializeTimeoutError initialize() 호출 후 완료까지 타임아웃
VisualRewardInvalidAppKeyError 유효하지 않은 앱 키 (404)
VisualRewardServerError(statusCode) 서버 오류 (5xx)
VisualRewardParseError 응답 파싱 실패
VisualRewardNotInitializedError initialize() 호출 없이 open() 호출
VisualRewardUserIdNotSetError setUserId() 호출 없이 open() 호출

initialize 에러 처리 #

  • onFailure 콜백에서 에러 타입을 분기합니다.

    VisualReward.initialize(
      appKey: 'tq_live_xxx',
      timeout: const Duration(seconds: 5),
      onSuccess: () { /* SDK 준비 완료 */ },
      onFailure: (e) {
        if (e is VisualRewardNetworkError) {
          // 네트워크 연결 실패
        } else if (e is VisualRewardInitializeTimeoutError) {
          // 초기화 타임아웃
        } else if (e is VisualRewardInvalidAppKeyError) {
          // 존재하지 않는 앱 키
        } else if (e is VisualRewardServerError) {
          // 서버 오류: e.statusCode
        } else if (e is VisualRewardParseError) {
          // 응답 파싱 실패
        }
      },
    );
    

open 에러 처리 #

  • open()은 예외를 throw하지 않고 onError 콜백으로 에러를 전달합니다. 콜백에서 에러 타입을 분기합니다.

    VisualReward.open(
      context: context,
      serviceName: 'reward_home',
      locale: 'ko',
      extra: null,
      onError: (e) {
        if (e is VisualRewardNotInitializedError) {
          // initialize() 미호출
        } else if (e is VisualRewardUserIdNotSetError) {
          // setUserId() 미호출
        } else if (e is VisualRewardNetworkError) {
          // 네트워크 연결 실패
        } else if (e is VisualRewardServerError) {
          // 서버 오류: e.statusCode
        }
      },
    );
    
0
likes
0
points
460
downloads

Publisher

verified publishertenqube.com

Weekly Downloads

Tenqube Visual Reward SDK for Flutter. A reward-ad webview SDK built on flutter_inappwebview for Android and iOS.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_inappwebview

More

Packages that depend on visual_reward

Packages that implement visual_reward