Esta guía está destinada a los publicadores que integran anuncios para abrir la aplicación con el SDK de Google Mobile Ads.
Los anuncios de aplicación abierta son un formato de anuncio especial diseñado para los publicadores que desean monetizar sus pantallas de carga de aplicaciones. Los anuncios de aplicación abierta se pueden cerrar en cualquier momento y están diseñados para mostrarse cuando los usuarios llevan tu app al primer plano.
Los anuncios de aplicación abierta muestran automáticamente un pequeño área de desarrollo de la marca para que los usuarios sepan que están en tu app. A continuación, se muestra un ejemplo de cómo se ve un anuncio de aplicación abierta:
Requisitos previos
- Completa la guía de introducción.
Siempre realiza pruebas con anuncios de prueba
Cuando compiles y pruebes tus apps, asegúrate de usar anuncios de prueba en lugar de anuncios activos en fase de producción. De lo contrario, podría suspenderse tu cuenta.
La forma más sencilla de cargar anuncios de prueba es usar nuestro ID de unidad de anuncios de prueba exclusivo para anuncios abiertos de la app:
/21775744923/example/app-open
Se configuró de forma especial para mostrar anuncios de prueba para cada solicitud, y puedes usarlo en tus propias apps mientras codificas, pruebas y depuras. Solo asegúrate de reemplazarlo por tu propio ID de unidad de anuncios antes de publicar la app.
Para obtener más información sobre cómo funcionan los anuncios de prueba del SDK de anuncios de Google para dispositivos móviles, consulta Cómo habilitar anuncios de prueba.
Cómo extender la clase Application
Crea una clase nueva que extienda la clase Application
y agrega el siguiente código para inicializar el SDK de anuncios de Google para dispositivos móviles cuando se inicie tu app.
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) {}
}
}
}
Esto inicializa el SDK y proporciona el esqueleto en el que más adelante te registrarás para los eventos de puesta en primer plano de la app.
Luego, agrega el siguiente código a tu AndroidManifest.xml
:
<!-- TODO: Update to reference your actual package name. -->
<application
android:name="com.google.android.gms.example.appopendemo.MyApplication" ...>
...
</application>
Implementa tu componente de utilidad
Tu anuncio debe mostrarse rápidamente, por lo que es mejor cargarlo antes de necesitar mostrarlo. De esta manera, tendrás un anuncio listo para publicarse en cuanto el usuario ingrese a tu app.
Implementa un componente de utilidad AppOpenAdManager
para realizar solicitudes de anuncios antes de que necesites mostrar el anuncio.
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 later.
}
/** 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 later.
}
/** Check if ad exists and can be shown. */
private fun isAdAvailable(): Boolean {
return appOpenAd != null
}
}
}
Ahora que tienes una clase de utilidad, puedes crear una instancia en tu clase 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()
}
}
Carga un anuncio
El siguiente paso es completar el método loadAd()
y controlar las devoluciones de llamada de carga de anuncios.
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;
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;
}
});
}
// ...
}
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
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;
}
})
}
// ...
}
Cómo mostrar el anuncio y controlar los eventos de devolución de llamada de pantalla completa
La implementación más común de la aplicación abierta es intentar mostrar un anuncio de aplicación abierta cerca del lanzamiento de la aplicación, iniciar el contenido de la aplicación si el anuncio no está listo y precargar otro anuncio para la próxima oportunidad de apertura de la aplicación. Consulta la Guía de anuncios de aplicación abierta para ver ejemplos de implementación.
En el siguiente código, se muestra cómo mostrar un anuncio y, luego, volver a cargarlo:
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)
}
// ...
}
}
FullScreenContentCallback
controla eventos, como cuando se presenta el anuncio, no se presenta o se descarta.
Ten en cuenta el vencimiento de los anuncios
Para asegurarte de no mostrar un anuncio vencido, agrega un método a AppOpenAdManager
que verifique cuánto tiempo transcurrió desde que se cargó la referencia de tu anuncio. Luego, usa ese método para comprobar si el anuncio sigue siendo válido.
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;
// ...
/** 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;
// ...
/** Utility method to check if ad was loaded more than n hours ago. */
private fun wasLoadTimeLessThanNHoursAgo(numHours: Long): Boolean {
val dateDifference: Long = Date().time - loadTime
val numMilliSecondsPerHour: Long = 3600000
return dateDifference < numMilliSecondsPerHour * numHours
}
/** Check if ad exists and can be shown. */
private fun isAdAvailable(): Boolean {
return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4)
}
}
Hacer un seguimiento de la actividad actual
Para mostrar el anuncio, necesitarás un contexto Activity
. Para hacer un seguimiento de la actividad más reciente que se usa, regístrate en Application.ActivityLifecycleCallbacks
y, luego, impleméntala.
Java
public class MyApplication extends Application implements ActivityLifecycleCallbacks {
private Activity currentActivity;
@Override
public void onCreate() {
super.onCreate();
this.registerActivityLifecycleCallbacks(this);
// ...
}
/** ActivityLifecycleCallback methods. */
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {
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
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(this)
// ...
}
/** ActivityLifecycleCallback methods. */
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {
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) {}
}
registerActivityLifecycleCallbacks
te permite escuchar todos los eventos Activity
. Si escuchas cuándo se inician y destruyen las actividades, puedes hacer un seguimiento de una referencia al Activity
actual, que luego usarás para presentar el anuncio abierto de tu app.
Cómo detectar eventos de puesta en primer plano de la app
Agrega las bibliotecas a tu archivo Gradle
Para recibir notificaciones sobre los eventos que ocurren en primer plano en la app, debes registrar un DefaultLifecycleObserver
. Agrega su dependencia al archivo de compilación a nivel de la app:
Kotlin
dependencies { implementation("com.google.android.gms:play-services-ads:23.6.0") implementation("androidx.lifecycle:lifecycle-process:2.8.3") }
Groovy
dependencies { implementation 'com.google.android.gms:play-services-ads:23.6.0' implementation 'androidx.lifecycle:lifecycle-process:2.8.3' }
Implementa la interfaz de observador de ciclo de vida
Para escuchar eventos en primer plano, implementa la interfaz DefaultLifecycleObserver
.
Implementa el evento onStart
para mostrar el anuncio de aplicación abierta.
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.
}
})
}
}
Inicios en frío y pantallas de carga
Hasta ahora, la documentación supone que solo muestras anuncios de aplicación abierta cuando los usuarios ponen tu app en primer plano cuando está suspendida en la memoria. Los "inicios en frío" ocurren cuando se inicia tu app, pero no se suspendió anteriormente en la memoria.
Un ejemplo de inicio en frío es cuando un usuario abre tu app por primera vez. Con los inicios en frío, no tendrás un anuncio de aplicación abierta cargado con anterioridad que esté listo para mostrarse de inmediato. La demora entre el momento en que solicitas un anuncio y el momento en que lo recibes puede crear una situación en la que los usuarios puedan usar tu app brevemente antes de que se les muestre un anuncio fuera de contexto. Esto se debe evitar porque es una experiencia del usuario deficiente.
La forma preferida de usar anuncios de aplicación abierta en los inicios en frío es usar una pantalla de carga para cargar los recursos de tu juego o aplicación y mostrar solo el anuncio desde la pantalla de carga. Si la carga de la app se completó y envió al usuario al contenido principal de la app, no muestres el anuncio.
Prácticas recomendadas
Los anuncios de apertura de la aplicación te ayudan a monetizar la pantalla de carga de tu app, cuando esta se inicia por primera vez y durante los cambios de app, pero es importante tener en cuenta las prácticas recomendadas para que los usuarios disfruten de usarla. Te recomendamos que hagas lo siguiente:
- Muestra tu primer anuncio de aplicación abierta después de que los usuarios hayan utilizado tu aplicación unas cuantas veces.
- Muestra anuncios de aplicación abierta durante los momentos en los que, de otro modo, los usuarios estarían esperando que se cargue la app.
- Si tienes una pantalla de carga debajo del anuncio de aplicación abierta y esta termina de cargarse antes de que se descarte el anuncio, te recomendamos descartarla en el método
onAdDismissedFullScreenContent()
.
Ejemplos en GitHub
Próximos pasos
Explora los siguientes temas: