Annunci apertura app

Questa guida è destinata ai publisher che integrano gli annunci apertura app utilizzando l'SDK Google Mobile Ads per Android.

Gli annunci apertura app sono un formato di annuncio speciale destinato ai publisher che vogliono monetizzare le schermate di caricamento delle app. Gli annunci apertura app possono essere chiusi in qualsiasi momento e sono progettati per essere mostrati quando gli utenti portano la tua app in primo piano.

Gli annunci apertura app mostrano automaticamente una piccola area di branding in modo che gli utenti sappiano che si trovano nella tua app. Ecco un esempio di annuncio apertura app:

A livello generale, questi sono i passaggi importanti:

  1. Estendi la classe Application per inizializzare l'SDK Google Mobile Ads.
  2. Creare una classe di utilità che carichi un annuncio prima di doverlo visualizzare.
  3. Carica un annuncio.
  4. Ascolta ActivityLifecycleCallbacks.
  5. Mostra l'annuncio e gestisci i callback.
  6. Implementa e registra l'interfaccia LifecycleObserver per mostrare un annuncio durante gli eventi in primo piano.

Prerequisiti

  • SDK Google Mobile Ads 19.4.0 o versioni successive.
  • Segui le istruzioni di configurazione nella Guida introduttiva.

Effettua sempre test con annunci di prova

Quando crei e testi le tue app, assicurati di utilizzare annunci di prova anziché annunci di produzione pubblicati. In caso contrario, l'account verrà sospeso.

Il modo più semplice per caricare gli annunci di prova è utilizzare il nostro ID unità pubblicitaria di prova dedicato per gli annunci apertura app:

/21775744923/example/app-open

È stato appositamente configurato per restituire annunci di prova per ogni richiesta e puoi utilizzarlo nelle tue app durante la programmazione, i test e il debug. Assicurati di sostituirlo con il tuo ID unità pubblicitaria prima di pubblicare l'app.

Per ulteriori informazioni sul funzionamento degli annunci di prova dell'SDK Mobile Ads, consulta la pagina Annunci di prova.

Estendi la classe Application

Crea una nuova classe che estende la classe Application e aggiungi il seguente codice per inizializzare l'SDK Google Mobile Ads.

Java

/** Application class that initializes, loads and show ads when activities change states. */
public class MyApplication extends Application {

  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
  }
}

Kotlin

/** Application class that initializes, loads and show ads when activities change states. */
class MyApplication : Application() {

  override fun onCreate() {
    super.onCreate()
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
  }
}

L'SDK verrà inizializzato e verrà fornito lo scheletro in cui ti registrerai in seguito per gli eventi di primo piano delle app.

Poi, aggiungi il seguente codice al tuo AndroidManifest.xml:

<application
    android:name="com.google.android.gms.example.appopendemo.MyApplication" ...>
...
</application>

Assicurati di fare riferimento al nome effettivo del pacchetto.

Implementazione della classe di utilità

L'annuncio dovrebbe essere pubblicato rapidamente, pertanto è preferibile caricarlo prima di averne bisogno. In questo modo, l'annuncio sarà pronto da essere pubblicato non appena l'utente accede all'app. Implementa una classe di utilità per effettuare richieste di annunci in anticipo rispetto a quando devi mostrare l'annuncio.

Crea un nuovo corso chiamato AppOpenAdManager all'interno di MyApplication corso e compilalo come segue:

Java

public class MyApplication extends Application {
  ...
  /** Inner class that loads and shows app open ads. */
  private class AppOpenAdManager {
    private static final String LOG_TAG = "AppOpenAdManager";
    private static final String AD_UNIT_ID = "/21775744923/example/app-open";

    private AppOpenAd appOpenAd = null;
    private boolean isLoadingAd = false;
    private boolean isShowingAd = false;

    /** Constructor. */
    public AppOpenAdManager() {}

    /** Request an ad. */
    private void loadAd(Context context) {
      // We will implement this below.
    }

    /** Check if ad exists and can be shown. */
    private boolean isAdAvailable() {
      return appOpenAd != null;
    }
  }
}

Kotlin

private const val String LOG_TAG = "AppOpenAdManager"
private const val String AD_UNIT_ID = "/21775744923/example/app-open"

public class MyApplication extends Application {
  ...
  /** Inner class that loads and shows app open ads. */
  private inner class AppOpenAdManager {
    private var appOpenAd: AppOpenAd? = null
    private var isLoadingAd = false
    var isShowingAd = false

    /** Request an ad. */
    fun loadAd(context: Context) {
      // We will implement this below.
    }

    /** Check if ad exists and can be shown. */
    private fun isAdAvailable(): Boolean {
      return appOpenAd != null
    }
  }
}

Ora che hai una classe di utilità, puoi creare un'istanza nella tua classe MyApplication:

Java

public class MyApplication extends Application {

  private AppOpenAdManager appOpenAdManager;

  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
    appOpenAdManager = new AppOpenAdManager(this);
  }
}

Kotlin

class MyApplication : Application() {

  private lateinit var appOpenAdManager: AppOpenAdManager

  override fun onCreate() {
    super.onCreate()
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
    appOpenAdManager = AppOpenAdManager()
  }
}

Carica un annuncio

Nel prossimo passaggio dovrai compilare il metodo loadAd().

Java

private class AppOpenAdManager {
  ...
  /** Request an ad. */
  public void loadAd(Context context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return;
    }

    isLoadingAd = true;
    AdRequest request = new AdRequest.Builder().build();
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        new AppOpenAdLoadCallback() {
          @Override
          public void onAdLoaded(AppOpenAd ad) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.");
            appOpenAd = ad;
            isLoadingAd = false;
          }

          @Override
          public void onAdFailedToLoad(LoadAdError loadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.getMessage());
            isLoadingAd = false;
          }
        });
  }
  ...
}

Kotlin

private inner class AppOpenAdManager {
  ...
  /** Request an ad. */
  fun loadAd(context: Context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return
    }

    isLoadingAd = true
    val request = AdRequest.Builder().build()
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        object : AppOpenAdLoadCallback() {

          override fun onAdLoaded(ad: AppOpenAd) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.")
            appOpenAd = ad
            isLoadingAd = false
          }

          override fun onAdFailedToLoad(loadAdError: LoadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.message)
            isLoadingAd = false;
          }
        })
  }
  ...
}

AppOpenAdLoadCallback dispone di metodi che vengono chiamati al termine del caricamento di AppOpenAd.

Tenere traccia dell'attività corrente

Per mostrare l'annuncio, è necessario un contesto Activity. Per tenere traccia dell'attività più recente utilizzata dall'utente, implementa Application.ActivityLifecycleCallbacks nel tuo corso Application.

Java

public class MyApplication extends Application implements ActivityLifecycleCallbacks {

  private Activity currentActivity;

  ...

  /** ActivityLifecycleCallback methods. */
  @Override
  public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

  @Override
  public void onActivityStarted(Activity activity) {
    // Updating the currentActivity only when an ad is not showing.
    if (!appOpenAdManager.isShowingAd) {
      currentActivity = activity;
    }
  }

  @Override
  public void onActivityResumed(Activity activity) {}

  @Override
  public void onActivityStopped(Activity activity) {}

  @Override
  public void onActivityPaused(Activity activity) {}

  @Override
  public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {}

  @Override
  public void onActivityDestroyed(Activity activity) {}
}

Kotlin

class MyApplication : Application(), Application.ActivityLifecycleCallbacks {

  private var currentActivity: Activity? = null

  ...

  /** ActivityLifecycleCallback methods. */
  override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

  override fun onActivityStarted(activity: Activity) {
    // Updating the currentActivity only when an ad is not showing.
    if (!appOpenAdManager.isShowingAd) {
      currentActivity = activity
    }
  }

  override fun onActivityResumed(activity: Activity) {}

  override fun onActivityPaused(activity: Activity) {}

  override fun onActivityStopped(activity: Activity) {}

  override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

  override fun onActivityDestroyed(activity: Activity) {}
}

Se monitori l'attività in corso, hai a disposizione un contesto per mostrare l'annuncio. Ora devi registrare questa interfaccia utilizzando il metodo registerActivityLifecycleCallbacks.

Java

public class MyApplication extends Application {
  ...
  @Override
  public void onCreate() {
    super.onCreate();
    this.registerActivityLifecycleCallbacks(this);
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
    appOpenAdManager = new AppOpenAdManager();
  }
}

Kotlin

class MyApplication : Application() {
  ...
  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
    appOpenAdManager = AppOpenAdManager()
  }
}

registerActivityLifecycleCallbacks ti consente di ascoltare tutti gli eventi Activity. Se ascolti l'inizio e l'eliminazione delle attività, puoi tenere traccia di un riferimento all'Activity attuale, che utilizzerai poi per presentare il tuo annuncio apertura app.

Mostrare l'annuncio e gestire gli eventi di callback a schermo intero

Il seguente codice indica quando mostrare e successivamente ricaricare un annuncio.

Java

public class MyApplication extends Application {
  ...
  /** Interface definition for a callback to be invoked when an app open ad is complete. */
  public interface OnShowAdCompleteListener {
    void onShowAdComplete();
  }

  private class AppOpenAdManager {
    ...

    /** Shows the ad if one isn't already showing. */
    public void showAdIfAvailable(
        @NonNull final Activity activity,
        @NonNull OnShowAdCompleteListener onShowAdCompleteListener){
      // If the app open ad is already showing, do not show the ad again.
      if (isShowingAd) {
        Log.d(LOG_TAG, "The app open ad is already showing.");
        return;
      }

      // If the app open ad is not available yet, invoke the callback then load the ad.
      if (!isAdAvailable()) {
        Log.d(LOG_TAG, "The app open ad is not ready yet.");
        onShowAdCompleteListener.onShowAdComplete();
        loadAd(activity);
        return;
      }

      appOpenAd.setFullScreenContentCallback(
          new FullScreenContentCallback() {

            @Override
            public void onAdDismissedFullScreenContent() {
              // Called when fullscreen content is dismissed.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, "Ad dismissed fullscreen content.");
              appOpenAd = null;
              isShowingAd = false;

              onShowAdCompleteListener.onShowAdComplete();
              loadAd(activity);
            }

            @Override
            public void onAdFailedToShowFullScreenContent(AdError adError) {
              // Called when fullscreen content failed to show.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, adError.getMessage());
              appOpenAd = null;
              isShowingAd = false;

              onShowAdCompleteListener.onShowAdComplete();
              loadAd(activity);
            }

            @Override
            public void onAdShowedFullScreenContent() {
              // Called when fullscreen content is shown.
              Log.d(LOG_TAG, "Ad showed fullscreen content.");
            }
          });
      isShowingAd = true;
      appOpenAd.show(activity);
    }
    ...
  }
}

Kotlin

class MyApplication : Application() {
  ...
  /** Interface definition for a callback to be invoked when an app open ad is complete. */
  interface OnShowAdCompleteListener {
    fun onShowAdComplete()
  }

  private inner class AppOpenAdManager {
    ...

    /** Shows the ad if one isn't already showing. */
    fun showAdIfAvailable(
        activity: Activity,
        onShowAdCompleteListener: OnShowAdCompleteListener) {
      // If the app open ad is already showing, do not show the ad again.
      if (isShowingAd) {
        Log.d(LOG_TAG, "The app open ad is already showing.")
        return
      }

      // If the app open ad is not available yet, invoke the callback then load the ad.
      if (!isAdAvailable()) {
        Log.d(LOG_TAG, "The app open ad is not ready yet.")
        onShowAdCompleteListener.onShowAdComplete()
        loadAd(activity)
        return
      }

      appOpenAd?.setFullScreenContentCallback(
          object : FullScreenContentCallback() {

            override fun onAdDismissedFullScreenContent() {
              // Called when full screen content is dismissed.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, "Ad dismissed fullscreen content.")
              appOpenAd = null
              isShowingAd = false

              onShowAdCompleteListener.onShowAdComplete()
              loadAd(activity)
            }

            override fun onAdFailedToShowFullScreenContent(adError: AdError) {
              // Called when fullscreen content failed to show.
              // Set the reference to null so isAdAvailable() returns false.
              Log.d(LOG_TAG, adError.message)
              appOpenAd = null
              isShowingAd = false

              onShowAdCompleteListener.onShowAdComplete()
              loadAd(activity)
            }

            override fun onAdShowedFullScreenContent() {
              // Called when fullscreen content is shown.
              Log.d(LOG_TAG, "Ad showed fullscreen content.")
            }
          })
      isShowingAd = true
      appOpenAd?.show(activity)
    }
    ...
  }
}

L'FullScreenContentCallback gestisce eventi come quando l'annuncio viene presentato, non viene presentato o quando viene ignorato. Se un utente torna alla tua app dopo averla abbandonata facendo clic su un annuncio apertura app, si assicura che non venga visualizzato un altro annuncio apertura app.

Ascolta gli eventi in primo piano delle app

Aggiungere le librerie al file Gradle

Per ricevere notifiche relative agli eventi in primo piano delle app, devi registrare un LifecycleObserver. Innanzitutto, modifica il file build.gradle a livello di applicazione per includere le librerie LifecycleObserver:

apply plugin: 'com.android.application'

dependencies {
   implementation 'androidx.appcompat:appcompat:1.3.0'
   implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

   implementation 'com.google.android.gms:play-services-ads:23.2.0'

   def lifecycle_version = "2.3.1"
   implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
   implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
   annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
}

Implementare l'interfaccia LifecycleObserver

Puoi rimanere in ascolto degli eventi in primo piano nella tua classe Application implementando l'interfaccia LifecycleObserver.

Java

public class MyApplication extends Application
    implements ActivityLifecycleCallbacks, LifecycleObserver { {
  ...
  @Override
  public void onCreate() {
    super.onCreate();
    this.registerActivityLifecycleCallbacks(this);
    new Thread(
            () -> {
              // Initialize the Google Mobile Ads SDK on a background thread.
              MobileAds.initialize(this, initializationStatus -> {});
            })
        .start();
    ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    appOpenAdManager = new AppOpenAdManager();
  }

  /** LifecycleObserver method that shows the app open ad when the app moves to foreground. */
  @OnLifecycleEvent(Event.ON_START)
  protected void onMoveToForeground() {
    // Show the ad (if available) when the app moves to foreground.
    appOpenAdManager.showAdIfAvailable(currentActivity);
  }

  /** Show the ad if one isn't already showing. */
  private void showAdIfAvailable(@NonNull final Activity activity) {
      showAdIfAvailable(
          activity,
          new OnShowAdCompleteListener() {
            @Override
            public void onShowAdComplete() {
              // Empty because the user will go back to the activity that shows the ad.
            }
          });
  }
}

Kotlin

class MyApplication : Application(),
    Application.ActivityLifecycleCallbacks, LifecycleObserver {
  ...
  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
    val backgroundScope = CoroutineScope(Dispatchers.IO)
    backgroundScope.launch {
      // Initialize the Google Mobile Ads SDK on a background thread.
      MobileAds.initialize(this@MyApplication) {}
    }
    ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    appOpenAdManager = AppOpenAdManager()
  }

  /** LifecycleObserver method that shows the app open ad when the app moves to foreground. */
  @OnLifecycleEvent(Lifecycle.Event.ON_START)
  fun onMoveToForeground() {
    // Show the ad (if available) when the app moves to foreground.
    currentActivity?.let {
      appOpenAdManager.showAdIfAvailable(it)
    }
  }

  /** Show the ad if one isn't already showing. */
  fun showAdIfAvailable(activity: Activity) {
    showAdIfAvailable(
        activity,
        object : OnShowAdCompleteListener {
          override fun onShowAdComplete() {
            // Empty because the user will go back to the activity that shows the ad.
          }
        })
  }
}

Se registri il tuo LifecycleObserver, l'app riceverà un avviso in caso di avvio e l'utilizzo in primo piano dell'app e potrà mostrare l'annuncio al momento opportuno.

Considera la scadenza dell'annuncio

Per assicurarti di non pubblicare un annuncio scaduto, aggiungi un metodo a AppOpenAdManager per verificare il tempo trascorso dal caricamento del riferimento dell'annuncio. Poi, utilizza questo metodo per verificare se l'annuncio è ancora valido.

Java

private class AppOpenAdManager {
  ...
  /** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
  private long loadTime = 0;

  /** Request an ad. */
  public void loadAd(Context context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return;
    }

    isLoadingAd = true;
    AdRequest request = new AdRequest.Builder().build();
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        new AppOpenAdLoadCallback() {
          @Override
          public void onAdLoaded(AppOpenAd ad) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.");
            appOpenAd = ad;
            isLoadingAd = false;
            loadTime = (new Date()).getTime();
          }

          @Override
          public void onAdFailedToLoad(LoadAdError loadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.getMessage());
            isLoadingAd = false;
          }
        });
  }
  ...

  /** Utility method to check if ad was loaded more than n hours ago. */
  private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
    long dateDifference = (new Date()).getTime() - this.loadTime;
    long numMilliSecondsPerHour = 3600000;
    return (dateDifference < (numMilliSecondsPerHour * numHours));
  }

  /** Check if ad exists and can be shown. */
  public boolean isAdAvailable() {
    return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4);
  }
}

Kotlin

private inner class AppOpenAdManager {
  ...
  /** Keep track of the time an app open ad is loaded to ensure you don't show an expired ad. */
  private var loadTime: Long = 0

  /** Request an ad. */
  fun loadAd(context: Context) {
    // Do not load ad if there is an unused ad or one is already loading.
    if (isLoadingAd || isAdAvailable()) {
      return
    }

    isLoadingAd = true
    val request = AdRequest.Builder().build()
    AppOpenAd.load(
        context, AD_UNIT_ID, request,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        object : AppOpenAdLoadCallback() {

          override fun onAdLoaded(ad: AppOpenAd) {
            // Called when an app open ad has loaded.
            Log.d(LOG_TAG, "Ad was loaded.")
            appOpenAd = ad
            isLoadingAd = false
            loadTime = Date().time
          }

          override fun onAdFailedToLoad(loadAdError: LoadAdError) {
            // Called when an app open ad has failed to load.
            Log.d(LOG_TAG, loadAdError.message)
            isLoadingAd = false;
          }
        })
  }
  ...

  private fun wasLoadTimeLessThanNHoursAgo(numHours: Long): Boolean {
    val dateDifference: Long = Date().time - loadTime
    val numMilliSecondsPerHour: Long = 3600000
    return dateDifference < numMilliSecondsPerHour * numHours
  }

  private fun isAdAvailable(): Boolean {
    return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4)
  }
}

Avvii a freddo e schermate di caricamento

Finora nella documentazione si presuppone che pubblichi annunci apertura app solo quando gli utenti hanno messo in primo piano la tua app quando è sospesa in memoria. I "avvii a freddo" si verificano all'avvio dell'app, ma in precedenza non era stata sospesa in memoria.

Un esempio di avvio a freddo è quando un utente apre la tua app per la prima volta. Con gli avvii a freddo, non avrai un annuncio apertura app caricato in precedenza che sia pronto per essere mostrato immediatamente. Il ritardo tra la richiesta di annuncio e la ricezione di un annuncio di ritorno può creare una situazione in cui gli utenti sono in grado di utilizzare brevemente la tua app prima di essere sorpresi da un annuncio fuori contesto. Questo dovrebbe essere evitato perché offre un'esperienza utente negativa.

Il modo migliore per utilizzare gli annunci apertura app durante gli avvii a freddo è utilizzare una schermata di caricamento per caricare gli asset di gioco o app e mostrare l'annuncio solo dalla schermata di caricamento. Se l'app ha completato il caricamento e l'utente è indirizzato ai contenuti principali dell'app, non mostrare l'annuncio.

Best practice

Gli annunci apertura app ti consentono di monetizzare la schermata di caricamento della tua app al primo avvio e durante il passaggio da un'app all'altra. Tuttavia, è importante tenere presenti le best practice in modo che gli utenti possano utilizzare l'app. È consigliabile:

  • Mostra il tuo primo annuncio apertura app dopo che gli utenti hanno utilizzato l'app alcune volte.
  • Mostra gli annunci apertura app nei momenti in cui gli utenti attendono il caricamento dell'app.
  • Se sotto l'annuncio apertura app è presente una schermata di caricamento che termina il caricamento prima che l'annuncio venga ignorato, puoi scegliere di ignorare la schermata di caricamento nel metodo onAdDismissedFullScreenContent().

Esempi su GitHub

Passaggi successivi

Esplora i seguenti argomenti: