Agregar anuncios nativos a una app de Android

La API de anuncios nativos te permite crear una experiencia personalizada para los anuncios que muestras en tu aplicación. Cuando utilices la API de anuncios nativos, en lugar de un anuncio listo para mostrarse recibirás un grupo de propiedades de anuncios, como un título, una imagen y una llamada a la acción, que tendrás que utilizar para crear una vista personalizada donde se muestre el anuncio.

Asegúrate de completar las guías de primeros pasos para Audience Network y Android antes de continuar.

En esta guía implementaremos la siguiente ubicación de anuncios nativos. Crearás un anuncio nativo con los siguientes componentes:

Vista n.° 1: icono del anuncio

Vista n.° 2: título del anuncio

Vista n.° 3: etiqueta "Publicidad"

Vista n.º 4: AdOptionsView

Vista n.º 5: MediaView

Vista n.° 6: contexto social

Vista n.° 7: cuerpo del anuncio

Vista n.° 8: botón de llamada a la acción




Pasos del anuncio nativo

Paso 1: solicitar un anuncio nativo

Paso 2: crear el diseño de tu anuncio nativo

Paso 3: completar tu diseño usando los metadatos del anuncio

Paso 4: usar MediaView

Paso 5: cargar el anuncio sin autocaché

Inicializar el SDK de Audience Network

Este método se agregó en la versión 5.1 del SDK de Audience Network para Android.

La inicialización explícita del SDK de Audience Network para Android es obligatoria a partir de la versión 5.3.0. Consulta este documento sobre cómo inicializar el SDK de Audience Network para Android.

Antes de crear un objeto de anuncio y cargar anuncios, debes inicializar el SDK de Audience Network. Se recomienda hacerlo durante el inicio de la aplicación.

public class YourApplication extends Application {
    ...
    @Override
    public void onCreate() {
        super.onCreate();
        // Initialize the Audience Network SDK
        AudienceNetworkAds.initialize(this);       
    }
    ...
}

Paso 1: solicitar un anuncio nativo

Agrega el siguiente código en la parte superior de la actividad para importar el SDK de anuncios de Facebook:

import com.facebook.ads.*;

A continuación, crea una instancia del objeto NativeBannerAd, crea AdListener y llama a loadAd() con el agente de escucha de anuncios:

private final String TAG = "NativeAdActivity".getClass().getSimpleName();
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object.
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        @Override
        public void onMediaDownloaded(Ad ad) {
            // Native ad finished downloading all assets
            Log.e(TAG, "Native ad finished downloading all assets.");
        }

        @Override
        public void onError(Ad ad, AdError adError) {
        // Native ad failed to load
            Log.e(TAG, "Native ad failed to load: " + adError.getErrorMessage());
        }

        @Override
        public void onAdLoaded(Ad ad) {
            // Native ad is loaded and ready to be displayed
            Log.d(TAG, "Native ad is loaded and ready to be displayed!");
        }

        @Override
        public void onAdClicked(Ad ad) {
            // Native ad clicked
            Log.d(TAG, "Native ad clicked!");
        }

        @Override
        public void onLoggingImpression(Ad ad) {
            // Native ad impression
            Log.d(TAG, "Native ad impression logged!");
        }
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());
}

Más adelante agregaremos código al método onAdLoaded().

Paso 2: crear el diseño de tu anuncio nativo

El siguiente paso es extraer los metadatos del anuncio y utilizar sus propiedades para crear la interfaz de usuario nativa personalizada. Puedes crear una vista personalizada en un .xml de diseño o agregar elementos en el código.

Consulta nuestras normas para anuncios nativos cuando diseñes anuncios nativos en tu app.

En el diseño de la actividad activity_main.xml, agrega un contenedor para tu Native Ad. El contenedor debe ser com.facebook.ads.NativeAdLayout, que es un contenedor adicional a FrameLayout con más funcionalidades, que nos permite generar un proceso de creación de informes de anuncios nativos sobre el anuncio.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:paddingTop="50dp">
    ...
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="50dp">

        <com.facebook.ads.NativeAdLayout
             android:id="@+id/native_ad_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical" />
     </ScrollView>
    ...
</RelativeLayout>

Crea un diseño personalizado native_banner_ad_unit.xml para tu anuncio nativo:



El siguiente es un ejemplo de diseño personalizado para anuncio nativo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ad_unit"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
        android:paddingTop="10dp">

        <com.facebook.ads.MediaView
            android:id="@+id/native_ad_icon"
            android:layout_width="35dp"
            android:layout_height="35dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="5dp"
            android:paddingRight="5dp">

        <TextView
            android:id="@+id/native_ad_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:textColor="@android:color/black"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/native_ad_sponsored_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:textColor="@android:color/darker_gray"
            android:textSize="12sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/ad_choices_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:orientation="horizontal" />

    </LinearLayout>

    <com.facebook.ads.MediaView
        android:id="@+id/native_ad_media"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical">

            <TextView
                android:id="@+id/native_ad_social_context"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="@android:color/darker_gray"
                android:textSize="12sp" />

            <TextView
                android:id="@+id/native_ad_body"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:lines="2"
                android:textColor="@android:color/black"
                android:textSize="12sp" />

        </LinearLayout>

        <Button
            android:id="@+id/native_ad_call_to_action"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:background="#4286F4"
            android:paddingLeft="3dp"
            android:paddingRight="3dp"
            android:textColor="@android:color/white"
            android:textSize="12sp"
            android:visibility="gone" />

    </LinearLayout>

</LinearLayout>

Paso 3: completar tu diseño usando los metadatos del anuncio

Situación 1: el anuncio se muestra de inmediato una vez que se carga correctamente. Modifica el método onAdLoaded() anterior para recuperar las propiedades de Native Banner Ad's y que se muestre de la siguiente manera:

private NativeAdLayout nativeAdLayout;
private LinearLayout adView;
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
        @Override
        public void onAdLoaded(Ad ad) {
            // Race condition, load() called again before last ad was displayed
            if (nativeAd == null || nativeAd != ad) {
                return;
            }
            // Inflate Native Ad into Container
            inflateAd(nativeAd);
        }
        ...
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());
}

private void inflateAd(NativeAd nativeAd) {

    nativeAd.unregisterView();

    // Add the Ad view into the ad container.
    nativeAdLayout = findViewById(R.id.native_ad_container);
    LayoutInflater inflater = LayoutInflater.from(NativeAdActivity.this);
    // Inflate the Ad view.  The layout referenced should be the one you created in the last step.
    adView = (LinearLayout) inflater.inflate(R.layout.native_ad_layout_1, nativeAdLayout, false);
    nativeAdLayout.addView(adView);

    // Add the AdOptionsView
    LinearLayout adChoicesContainer = findViewById(R.id.ad_choices_container);
    AdOptionsView adOptionsView = new AdOptionsView(NativeAdActivity.this, nativeAd, nativeAdLayout);
    adChoicesContainer.removeAllViews();
    adChoicesContainer.addView(adOptionsView, 0);

    // Create native UI using the ad metadata.
    MediaView nativeAdIcon = adView.findViewById(R.id.native_ad_icon);
    TextView nativeAdTitle = adView.findViewById(R.id.native_ad_title);
    MediaView nativeAdMedia = adView.findViewById(R.id.native_ad_media);
    TextView nativeAdSocialContext = adView.findViewById(R.id.native_ad_social_context);
    TextView nativeAdBody = adView.findViewById(R.id.native_ad_body);
    TextView sponsoredLabel = adView.findViewById(R.id.native_ad_sponsored_label);
    Button nativeAdCallToAction = adView.findViewById(R.id.native_ad_call_to_action);

    // Set the Text.
    nativeAdTitle.setText(nativeAd.getAdvertiserName());
    nativeAdBody.setText(nativeAd.getAdBodyText());
    nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
    nativeAdCallToAction.setVisibility(nativeAd.hasCallToAction() ? View.VISIBLE : View.INVISIBLE);
    nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
    sponsoredLabel.setText(nativeAd.getSponsoredTranslation());

    // Create a list of clickable views
    List<View> clickableViews = new ArrayList<>();
    clickableViews.add(nativeAdTitle);
    clickableViews.add(nativeAdCallToAction);

    // Register the Title and CTA button to listen for clicks.
    nativeAd.registerViewForInteraction(
            adView, nativeAdMedia, nativeAdIcon, clickableViews);
}

El SDK registrará la impresión y controlará el clic de manera automática. Ten en cuenta que debes registrar la vista del anuncio con la instancia NativeBannerAd para activarla. Para que se pueda hacer clic en todos los elementos, registra la vista de la siguiente manera:

registerViewForInteraction(View view, MediaView adMediaView, MediaView adIconView)

Al utilizar "registerViewForInteraction" con "NativeAds", el SDK verifica que la llamada se realiza en el hilo principal para evitar condiciones de carrera. Realizamos nuestra verificación mediante Preconditions.checkIsOnMainThread(). Asegúrate de que tu implementación se ajuste a esta norma, ya que la app se bloqueará si intentas llamar a "registerViewForInteraction" desde un hilo en segundo plano.

Situación 2: mostrar el anuncio varios segundos o minutos después de que se haya cargado correctamente. Comprueba si el anuncio se invalidó antes de que se muestre.

En caso de que el anuncio no se muestre de forma automática después de cargarse, el desarrollador es responsable de verificar si el anuncio fue invalidado. Una vez que se carga satisfactoriamente, el anuncio es válido por 60 minutos. Si muestras un anuncio invalidado, no recibirás el pago. Debes hacer una llamada a isAdInvalidated() para validar el anuncio.

Te recomendamos que sigas el modelo que aparece a continuación, pero no copies el código en tu proyecto, ya que es solo un ejemplo:

private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());

    // Here is just an example for displaying the ad with delay
    // Please call this method at appropriate timing in your project
    showNativeAdWithDelay();
}

private void showNativeAdWithDelay() {
    /**
     * Here is an example for displaying the ad with delay;
     * Please do not copy the Handler into your project
     */
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        public void run() {
            // Check if nativeAd has been loaded successfully
            if(nativeAd == null || !nativeAd.isAdLoaded()) {
                return;
            }
            // Check if ad is already expired or invalidated, and do not show ad if that is the case. You will not get paid to show an invalidated ad.
            if(nativeAd.isAdInvalidated()) {
                return;
            }
            inflateAd(nativeAd); // Inflate NativeAd into a container, same as in previous code examples
        }
    }, 1000 * 60 * 15); // Show the ad after 15 minutes
}

Controlar el área en la que se puede hacer clic

Para lograr una mejor experiencia de usuario y mejores resultados, siempre debes considerar controlar la zona interactiva de tu anuncio para evitar clics involuntarios. Para obtener más información sobre el cumplimiento con el espacio en blanco donde no se puede hacer clic, consulta la Política del SDK de Audience Network.

Para tener un control más preciso de las áreas en las que se puede hacer clic, puedes usar registerViewForInteraction(View view, AdIconView adIconView, List<View> clickableViews) para registrar una lista de vistas en las que se puede hacer clic. Por ejemplo, si quieres que solo se pueda hacer clic en el título del anuncio y en el botón de llamada a la acción del ejemplo anterior, puedes escribir lo siguiente:

@Override
public void onAdLoaded(Ad ad) {
    ...
    // Create a list of clickable views
    List<View> clickableViews = new ArrayList<>();
    clickableViews.add(nativeAdTitle);
    clickableViews.add(nativeAdCallToAction);

    // Register the Title and CTA button to listen for clicks.
    nativeAd.registerViewForInteraction(
            adView, nativeAdMedia, nativeAdIcon, clickableViews);
    ...
}

En aquellos casos en los que vuelvas a usar la vista para mostrar diferentes anuncios a lo largo del tiempo, asegúrate de llamar a unregisterView() antes de registrar la misma vista en una instancia diferente de NativeBannerAd.

Al ejecutar el código, deberías ver un anuncio nativo:

Paso 4: usar MediaView

Para mostrar una imagen de portada de anuncio nativo, debes usar MediaView de Meta Audience Network, que puede mostrar activos con imágenes y videos. Para acceder a nuestras normas de diseño para unidades de anuncios nativos con video, consulta aquí.

De forma predeterminada, los activos con imágenes y videos se almacenan previamente en caché al cargar anuncios nativos, lo cual permite que MediaView reproduzca videos inmediatamente después de que nativeAd termine de cargar.

private void loadNativeAd() {
    ...
    nativeAd.loadAd();
}

Además, puedes especificar explícitamente NativeAd.MediaCacheFlag.ALL al cargar anuncios nativos.

private void loadNativeAd() {
    ...
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withMediaCacheFlag(NativeAdBase.MediaCacheFlag.ALL)
                    .build());
}

Audience Network admite dos opciones de caché en los anuncios nativos, definidas en la enumeración NativeAd.MediaCacheFlag:

Constantes de caché Descripción

ALL

Almacenamiento previo en caché de todo (íconos, imágenes y videos), predeterminado

NONE

Sin almacenamiento previo en caché

Cuando se cargue un anuncio, las siguientes propiedades incluirán algún valor: title, icon, coverImage y callToAction. Es posible que otras propiedades sean nulas o estén vacías. Asegúrate de que tu código sea lo suficientemente sólido para ocuparse de estos casos.

Cuando no haya ningún anuncio para mostrar, se llamará a onError con un error.code. Si usas tu propia capa de informes o mediación personalizada, es posible que quieras comprobar el valor del código y detectar este caso. En este caso, puedes recurrir a otra red publicitaria, pero no puedes volver a solicitar un anuncio de inmediato.

Los metadatos del anuncio que recibes pueden almacenarse en la caché y volver a usarse en un plazo máximo de una hora. Si tienes pensado utilizar los metadatos después del transcurso de este período, realiza una llamada para cargar un nuevo anuncio.

Paso 5: cargar el anuncio sin autocaché

  • Es muy recomendable que dejes activado el almacenamiento del contenido multimedia en caché de forma predeterminada en todos los casos. No obstante, puedes anular la opción predeterminada mediante MediaCacheFlag.NONE en el método loadAd. Debes tener mucho cuidado si decides anular el almacenamiento en caché de contenido multimedia predeterminado.
private final String TAG = NativeAdActivity.class.getSimpleName();
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");
    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
    };

    // Request an ad without auto cache
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .withMediaCacheFlag(NativeAdBase.MediaCacheFlag.NONE)
                    .build());
}
  • Una vez que onAdLoaded se invoque correctamente en tu anuncio, podrás llamar manualmente al método downloadMedia para iniciar la descarga de todo el contenido multimedia del anuncio nativo cuando resulte apropiado.
@Override
public void onAdLoaded(Ad ad) {
    if (nativeAd == null || nativeAd != ad) {
        return;
    }

    nativeAd.downloadMedia();
}
  • Por último, puedes llamar al método registerViewForInteraction y mostrar el anuncio cuando el contenido multimedia se haya terminado de cargar en la devolución de llamada onMediaDownloaded.
@Override
public void onMediaDownloaded(Ad ad) {
    if (nativeAd == null || nativeAd != ad) {
        return;
    }

    inflateAd(nativeAd); // Inflate NativeAd into a container, same as in previous code examples
}

Si cargaste el anuncio sin el almacenamiento automático en caché y no llamaste manualmente a downloadMedia para iniciar la descarga, el contenido multimedia comenzará a descargarse únicamente cuando se llame a registerViewForInteraction. Todo el contenido multimedia debe cargarse y mostrarse para que la impresión sea válida.

Aceleración de hardware para los anuncios con video

Los anuncios con video en Audience Network requieren que se active la función de aceleración de hardware, ya que, de lo contrario, las reproducciones de video podrían mostrar una pantalla negra. Esto se aplica a:

  • Contenido de video en los anuncios nativos
  • Contenido de video en los anuncios intersticiales
  • Anuncios con video instream
  • Videos con premio

La aceleración de hardware se activa de forma predeterminada si el nivel de API objetivo es mayor o igual a 14 (Ice Cream Sandwich, Android 4.0.1), pero también puedes activar explícitamente esta función en la aplicación o actividad.

En la aplicación

En tu archivo de manifiesto de Android, agrega el siguiente atributo a la etiqueta <application> para activar la aceleración de hardware para toda la aplicación:

<application android:hardwareAccelerated="true" ...>

En la actividad

Si solo quieres activar la función para actividades concretas de tu aplicación, puedes agregar la siguiente función a la etiqueta <activity> en el archivo de manifiesto de Android. El siguiente ejemplo activará la aceleración de hardware para AudienceNetworkActivity, que se usa para mostrar anuncios intersticiales y videos con premio:

<activity android:name="com.facebook.ads.AudienceNetworkActivity" android:hardwareAccelerated="true" .../>

Próximos pasos

  • Consulta la guía Plantilla de anuncios nativos para agregar anuncios nativos a tu app.

  • Consulta nuestros ejemplos de códigos donde se muestra cómo utilizar anuncios nativos. La muestra NativeBannerAdSample está disponible como parte del SDK en la carpeta AudienceNetwork/samples. Importa el proyecto en tu entorno de desarrollo integrado y ejecútalo en un dispositivo o en el emulador.

Más recursos

Guía introductoria

Guía técnica para empezar a usar Audience Network

Ejemplos de código

Ejemplos de integración de anuncios de Audience Network

Preguntas frecuentes

Preguntas frecuentes sobre Audience Network

Plantilla de anuncios nativos

Un enfoque más práctico para la integración de anuncios nativos