โฆษณาเปิดแอป

โฆษณาเปิดแอปเป็นรูปแบบโฆษณาพิเศษสําหรับผู้เผยแพร่โฆษณาที่ต้องการสร้างรายได้จากหน้าจอโหลดของแอป โฆษณาเปิดแอปสามารถปิดได้ทุกเมื่อ และออกแบบมาเพื่อแสดงเมื่อผู้ใช้นําแอปของคุณไปไว้ที่เบื้องหน้า

โฆษณาเปิดแอปจะแสดงองค์ประกอบแบรนด์ขนาดเล็กๆ โดยอัตโนมัติเพื่อให้ผู้ใช้รู้ว่ากำลังอยู่ในแอปของคุณ ตัวอย่างลักษณะของโฆษณาเปิดแอปมีดังนี้

ข้อกำหนดเบื้องต้น

  • ปลั๊กอิน Flutter 0.13.6 ขึ้นไป
  • ทําตามขั้นตอนเริ่มต้นใช้งานให้เสร็จสมบูรณ์ แอป Flutter ควรนําเข้าปลั๊กอิน Flutter ของ Google Mobile Ads ไว้แล้ว

ทดสอบด้วยโฆษณาทดสอบเสมอ

เมื่อสร้างและทดสอบแอป โปรดใช้โฆษณาทดสอบแทนโฆษณาเวอร์ชันที่ใช้งานจริง หากไม่ดำเนินการดังกล่าวอาจส่งผลให้บัญชีถูกระงับ

วิธีที่ง่ายที่สุดในการโหลดโฆษณาทดสอบคือการใช้รหัสหน่วยโฆษณาทดสอบเฉพาะสําหรับโฆษณาที่มีการให้รางวัลของ Android และ iOS ดังนี้

Android

ca-app-pub-3940256099942544/9257395921

iOS

ca-app-pub-3940256099942544/5575463023

โฆษณาเหล่านี้ได้รับการกําหนดค่ามาเป็นพิเศษให้แสดงโฆษณาทดสอบสําหรับคําขอทุกรายการ และคุณใช้โฆษณาเหล่านี้ในแอปของคุณเองได้ขณะเขียนโค้ด ทดสอบ และแก้ไขข้อบกพร่อง เพียงอย่าลืมแทนที่รหัสดังกล่าวด้วยรหัสหน่วยโฆษณาของคุณเองก่อนเผยแพร่แอป

การใช้งาน

ขั้นตอนหลักในการผสานรวมโฆษณาเปิดแอปมีดังนี้

  1. สร้างคลาสยูทิลิตีที่โหลดโฆษณาก่อนที่คุณต้องแสดงโฆษณา
  2. โหลดโฆษณา
  3. ลงทะเบียนเพื่อรับการติดต่อกลับและแสดงโฆษณา
  4. สมัครรับ AppStateEventNotifier.appStateStream เพื่อแสดงโฆษณาขณะที่เหตุการณ์อยู่เบื้องหน้า

สร้างคลาสยูทิลิตี

สร้างคลาสใหม่ชื่อ AppOpenAdManager เพื่อโหลดโฆษณา คลาสนี้จะจัดการตัวแปรอินสแตนซ์เพื่อติดตามโฆษณาที่โหลดและรหัสหน่วยโฆษณาสําหรับแต่ละแพลตฟอร์ม

import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'dart:io' show Platform;

class AppOpenAdManager {
  
  String adUnitId = Platform.isAndroid
    ? 'ca-app-pub-3940256099942544/9257395921'
    : 'ca-app-pub-3940256099942544/5575463023';
  
  AppOpenAd? _appOpenAd;
  bool _isShowingAd = false;

  /// Load an AppOpenAd.
  void loadAd() {
    // We will implement this below.
  }

  /// Whether an ad is available to be shown.
  bool get isAdAvailable {
    return _appOpenAd != null;
  }
}

โหลดโฆษณา

โฆษณาเปิดแอปต้องพร้อมใช้งานก่อนที่ผู้ใช้จะเข้าสู่แอปของคุณ ให้ใช้คลาสยูทิลิตีเพื่อส่งคําขอโฆษณาก่อนถึงเวลาที่คุณต้องแสดงโฆษณา

การโหลดโฆษณาจะเสร็จสมบูรณ์โดยใช้เมธอด load ในคลาส AppOpenAd เมธอดการโหลดต้องใช้รหัสหน่วยโฆษณา โหมดการวางแนว ออบเจ็กต์ AdRequest และตัวแฮนเดิลการเสร็จสมบูรณ์ซึ่งจะเรียกใช้เมื่อการโหลดโฆษณาสําเร็จหรือไม่สําเร็จ ออบเจ็กต์ AppOpenAd ที่โหลดจะแสดงเป็นพารามิเตอร์ใน Completion Handler ตัวอย่างต่อไปนี้แสดงวิธีโหลด AppOpenAd

public class AppOpenAdManager {
  ...

  /// Load an AppOpenAd.
  void loadAd() {
    AppOpenAd.load(
      adUnitId: adUnitId,
      adRequest: AdRequest(),
      adLoadCallback: AppOpenAdLoadCallback(
        onAdLoaded: (ad) {
          _appOpenAd = ad;
        },
        onAdFailedToLoad: (error) {
          print('AppOpenAd failed to load: $error');
          // Handle the error.
        },
      ),
    );
  }
}

แสดงโฆษณาและจัดการการเรียกกลับแบบเต็มหน้าจอ

ก่อนแสดงโฆษณา ให้ลงทะเบียน FullScreenContentCallback สําหรับเหตุการณ์โฆษณาแต่ละรายการที่ต้องการฟัง

public class AppOpenAdManager {
  ...

  public void showAdIfAvailable() {
    if (!isAdAvailable) {
      print('Tried to show ad before available.');
      loadAd();
      return;
    }
    if (_isShowingAd) {
      print('Tried to show ad while already showing an ad.');
      return;
    }
    // Set the fullScreenContentCallback and show the ad.
    _appOpenAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdShowedFullScreenContent: (ad) {
        _isShowingAd = true;
        print('$ad onAdShowedFullScreenContent');
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        print('$ad onAdFailedToShowFullScreenContent: $error');
        _isShowingAd = false;
        ad.dispose();
        _appOpenAd = null;
      },
      onAdDismissedFullScreenContent: (ad) {
        print('$ad onAdDismissedFullScreenContent');
        _isShowingAd = false;
        ad.dispose();
        _appOpenAd = null;
        loadAd();
      },
    );
  }
}

หากผู้ใช้กลับมาที่แอปหลังจากออกจากแอปไปโดยคลิกโฆษณาเปิดแอป ให้ตรวจสอบว่าผู้ใช้ไม่เห็นโฆษณาเปิดแอปอื่น

รอรับเหตุการณ์ที่แสดงอยู่เบื้องหน้าของแอป

หากต้องการรับการแจ้งเตือนเกี่ยวกับเหตุการณ์ที่แสดงอยู่เบื้องหน้าของแอป คุณต้องสมัครรับข้อมูล AppStateEventNotifier.appStateStream และฟังเหตุการณ์ foreground

import 'package:app_open_example/app_open_ad_manager.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

/// Listens for app foreground events and shows app open ads.
class AppLifecycleReactor {
  final AppOpenAdManager appOpenAdManager;

  AppLifecycleReactor({required this.appOpenAdManager});

  void listenToAppStateChanges() {
    AppStateEventNotifier.startListening();
    AppStateEventNotifier.appStateStream
        .forEach((state) => _onAppStateChanged(state));
  }

  void _onAppStateChanged(AppState appState) {
    // Try to show an app open ad if the app is being resumed and
    // we're not already showing an app open ad.
    if (appState == AppState.foreground) {
      appOpenAdManager.showAdIfAvailable();
    }
  }
}

ตอนนี้คุณเพิ่มการเริ่มต้น AppLifecycleReactor และเริ่มตรวจหาการเปลี่ยนแปลงวงจรชีวิตของแอปได้แล้ว เช่น จากหน้าแรก

import 'package:app_open_example/app_open_ad_manager.dart';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'app_lifecycle_reactor.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'App Open Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'App Open Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

/// Example home page for an app open ad.
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  late AppLifecycleReactor _appLifecycleReactor;

  @override
  void initState() {
    super.initState();
    
    AppOpenAdManager appOpenAdManager = AppOpenAdManager()..loadAd();
    _appLifecycleReactor = AppLifecycleReactor(
      appOpenAdManager: appOpenAdManager);
  }

พิจารณาการหมดอายุของโฆษณา

โปรดเพิ่มการประทับเวลาลงใน AppOpenAdManagerเพื่อให้ตรวจสอบได้ว่าโฆษณาโหลดไปนานเท่าใดแล้ว เพื่อไม่ให้แสดงโฆษณาที่หมดอายุ จากนั้นใช้การประทับเวลาดังกล่าวเพื่อตรวจสอบว่าโฆษณายังมีผลอยู่หรือไม่

/// Utility class that manages loading and showing app open ads.
class AppOpenAdManager {
  ...
  
  /// Maximum duration allowed between loading and showing the ad.
  final Duration maxCacheDuration = Duration(hours: 4);

  /// Keep track of load time so we don't show an expired ad.
  DateTime? _appOpenLoadTime;
  
  ...

  /// Load an AppOpenAd.
  void loadAd() {
    AppOpenAd.load(
      adUnitId: adUnitId,
      orientation: AppOpenAd.orientationPortrait,
      adRequest: AdRequest(),
      adLoadCallback: AppOpenAdLoadCallback(
        onAdLoaded: (ad) {
          print('$ad loaded');
          _appOpenLoadTime = DateTime.now();
          _appOpenAd = ad;
        },
        onAdFailedToLoad: (error) {
          print('AppOpenAd failed to load: $error');
        },
      ),
    );
  }

  /// Shows the ad, if one exists and is not already being shown.
  ///
  /// If the previously cached ad has expired, this just loads and caches a
  /// new ad.
  void showAdIfAvailable() {
    if (!isAdAvailable) {
      print('Tried to show ad before available.');
      loadAd();
      return;
    }
    if (_isShowingAd) {
      print('Tried to show ad while already showing an ad.');
      return;
    }
    if (DateTime.now().subtract(maxCacheDuration).isAfter(_appOpenLoadTime!)) {
      print('Maximum cache duration exceeded. Loading another ad.');
      _appOpenAd!.dispose();
      _appOpenAd = null;
      loadAd();
      return;
    }
    // Set the fullScreenContentCallback and show the ad.
    _appOpenAd!.fullScreenContentCallback = FullScreenContentCallback(...);
    _appOpenAd!.show();
  }
}

การเริ่มแอปแบบ Cold Start และหน้าจอการโหลด

เอกสารประกอบที่ผ่านมาจะถือว่าคุณแสดงโฆษณาเปิดแอปเฉพาะเมื่อผู้ใช้แสดงแอปของคุณอยู่เบื้องหน้าเมื่อแอปหยุดทำงานชั่วคราวในหน่วยความจํา "Cold Start" เกิดขึ้นเมื่อแอปของคุณเปิดขึ้นแต่ก่อนหน้านี้ไม่ได้หยุดไว้ชั่วคราวในหน่วยความจำ

ตัวอย่างของ Cold Start คือเมื่อผู้ใช้เปิดแอปเป็นครั้งแรก เมื่อใช้ Cold Start จะไม่มีโฆษณาเปิดแอปที่โหลดไว้ก่อนหน้านี้ซึ่งพร้อมแสดงทันที ความล่าช้าระหว่างที่คุณขอโฆษณาและได้รับโฆษณาอาจทําให้ผู้ใช้ใช้แอปได้เพียงช่วงสั้นๆ ก่อนที่จะเห็นโฆษณาที่ไม่ตรงบริบท ไม่ควรใช้วิธีนี้เนื่องจากเป็นประสบการณ์ที่ไม่ดีสำหรับผู้ใช้

วิธีที่เหมาะสมในการใช้โฆษณาเปิดแอปเมื่อเปิดแอปเป็นครั้งแรกคือการใช้หน้าจอการโหลดเพื่อโหลดชิ้นงานเกมหรือแอป และแสดงเฉพาะโฆษณาจากหน้าจอการโหลด หากแอปโหลดเสร็จแล้วและส่งผู้ใช้ไปยังเนื้อหาหลักของแอป โปรดอย่าแสดงโฆษณา

แนวทางปฏิบัติแนะนำ

โฆษณาเปิดแอปช่วยให้คุณสร้างรายได้จากหน้าจอการโหลดของแอป เมื่อแอปเปิดใช้งานครั้งแรก และระหว่างการเปลี่ยนแอป แต่อย่าลืมคำนึงถึงแนวทางปฏิบัติแนะนำเพื่อให้ผู้ใช้เพลิดเพลินกับการใช้แอปของคุณ แนวทางปฏิบัติแนะนำที่ควรทำมีดังนี้

  • แสดงโฆษณาเปิดแอปครั้งแรกหลังจากที่ผู้ใช้ใช้แอป 2-3 ครั้ง
  • แสดงโฆษณาเปิดแอปในช่วงเวลาที่ผู้ใช้รอให้แอปโหลด
  • หากคุณมีหน้าจอโหลดอยู่ใต้โฆษณาเปิดแอปและหน้าจอโหลดโหลดเสร็จสมบูรณ์ก่อนที่โฆษณาจะปิด คุณอาจต้องการปิดหน้าจอโหลดใน onAdDismissedFullScreenContent event handler

ตัวอย่างที่สมบูรณ์ใน GitHub

การเปิดแอป