Cómo agregar un banner y anuncios intercalados nativos de AdMob en una app de Flutter

En este codelab, implementarás un banner de AdMob y un anuncio intercalado nativo de AdMob en una app de Flutter.

Qué compilarás

En este codelab, se te guiará durante la implementación de un banner intercalado de AdMob y anuncios intercalados nativos de AdMob en una app de Flutter con el complemento de Flutter para anuncios de Google para dispositivos móviles.

Si, a medida que avanzas con este codelab, encuentras algún problema (errores de código, errores gramaticales, texto poco claro, etc.), infórmalo mediante el vínculo Informar un error que se encuentra en la esquina inferior izquierda del codelab.

Qué aprenderás

  • Cómo configurar el complemento de Flutter de anuncios de Google para dispositivos móviles
  • Cómo implementar un banner intercalado y anuncios recompensados en una app de Flutter

Requisitos

  • Android Studio 4.1 o versiones posteriores
  • Xcode 12 o versiones posteriores (para el desarrollo en iOS)

¿Cómo calificarías tu nivel de experiencia con AdMob?

Principiante Intermedio Avanzado

¿Cómo calificarías tu nivel de experiencia con Flutter?

Principiante Intermedio Avanzado

Cómo configurar el entorno de desarrollo de Flutter

  1. Instala el SDK de Flutter en tu equipo.
  2. Abre Android Studio e instala la extensión de Flutter para Android Studio.

Descarga el código

Descargar código fuente Ver repositorio en GitHub

Después de descargar el archivo ZIP, extrae su contenido. Tendrás una carpeta que se llama admob-inline-ads-in-flutter-main.

Como alternativa, puedes clonar el repositorio de GitHub desde la línea de comandos:

$ git clone https://github.com/googlecodelabs/admob-inline-ads-in-flutter

El repositorio contiene tres carpetas:

  • android_studio_folder.png starter: Es el código de inicio que compilarás en este codelab.
  • android_studio_folder.png complete: Es el código completo para este codelab (Java y Objective-C para código nativo).
  • android_studio_folder.png complete_kotlin_swift: Es el código completo para este codelab (Kotlin y Swift para código nativo).

Como Flutter es un SDK multiplataforma, debes agregar una app y bloques de anuncios para iOS y Android en AdMob.

Configuración para Android

A fin de realizar la configuración para Android, debes agregar una app para Android y crear bloques de anuncios.

Cómo agregar una app para Android

  1. En la consola de AdMob, haz clic en AGREGAR APP, en el menú de Apps.
  2. Cuando se te pregunte ¿Publicaste tu app en Google Play o App Store?, haz clic en NO.
  3. Ingresa AdMob inline ads en el campo del nombre de la app y selecciona Android como plataforma.

e4d968797610c8c0.png

  1. No es necesario habilitar las métricas del usuario para completar este codelab. Sin embargo, te recomendamos que los hagas porque te permite comprender el comportamiento del usuario con más detalle. Haz clic en AGREGAR para completar el proceso.

5204925f5c652b41.png

Cómo crear bloques de anuncios

Para agregar bloques de anuncios, haz lo siguiente:

  1. Selecciona la app Anuncios intercalados de AdMob en el menú de Apps, en la consola de AdMob.
  2. Haz clic en el menú de Bloques de anuncios.

Banner

  1. Haz clic en AGREGAR BLOQUE DE ANUNCIOS.
  2. Selecciona Banner como formato.
  3. Ingresa android-inline-banner en el campo Nombre del bloque de anuncios.
  4. Haz clic en CREAR BLOQUE DE ANUNCIOS para completar el proceso.

Nativo

  1. Haz clic en AGREGAR BLOQUE DE ANUNCIOS.
  2. Selecciona Nativo avanzado como formato.
  3. Ingresa android-inline-native en el campo Nombre del bloque de anuncios.
  4. Haz clic en CREAR BLOQUE DE ANUNCIOS para completar el proceso.

Los bloques de anuncios nuevos suelen demorar algunas horas para publicar anuncios.

Si deseas probar el comportamiento del anuncio de inmediato, utiliza el ID de la app y los ID de los bloques de anuncios de prueba que se indican en la tabla de ID de la app para Android/ID del bloque de anuncios y la tabla de ID de la app para Android/ID del bloque de anuncios.

Configuración para iOS

A fin de realizar la configuración para iOS, debes agregar una app para iOS y crear bloques de anuncios.

Cómo agregar una app para iOS

  1. En la consola de AdMob, haz clic en AGREGAR APP, en el menú de Apps.
  2. Cuando se te pregunte ¿Publicaste tu app en Google Play o App Store?, haz clic en NO.
  3. Ingresa AdMob inline ads en el campo del nombre de la app y selecciona iOS como plataforma.

e00fc8ac930a251b.png

  1. No es necesario habilitar las métricas del usuario para completar este codelab. Sin embargo, te recomendamos que los hagas porque te permite comprender el comportamiento del usuario con más detalle. Haz clic en AGREGAR para completar el proceso.

5204925f5c652b41.png

Cómo crear bloques de anuncios

Para agregar bloques de anuncios, haz lo siguiente:

  1. Selecciona la app Anuncios intercalados de AdMob en el menú de Apps, en la consola de AdMob.
  2. Haz clic en el menú Bloques de anuncios.

Banner

  1. Haz clic en AGREGAR BLOQUE DE ANUNCIOS.
  2. Selecciona Banner como formato.
  3. Ingresa ios-inline-banner en el campo Nombre del bloque de anuncios.
  4. Haz clic en CREAR BLOQUE DE ANUNCIOS para completar el proceso.

Nativo

  1. Haz clic en AGREGAR BLOQUE DE ANUNCIOS.
  2. Selecciona Nativo avanzado como formato.
  3. Ingresa ios-inline-native en el campo Nombre del bloque de anuncios.
  4. Haz clic en CREAR BLOQUE DE ANUNCIOS para completar el proceso.

Los bloques de anuncios nuevos suelen demorar algunas horas para publicar anuncios.

Si deseas probar el comportamiento del anuncio de inmediato, utiliza el ID de la app y los ID de los bloques de anuncios de prueba que se indican en la tabla más adelante.

Cómo usar la app y los bloques de anuncios de AdMob de prueba (opcional)

Si deseas seguir el codelab en lugar de crear una aplicación y bloques de anuncios nuevos por tu cuenta, puedes usar el ID de la app de AdMob y los ID de los bloques de anuncios de prueba en las siguientes tablas.

ID de la app para Android/ID del bloque de anuncios

Elemento

ID de la app/ID del bloque de anuncios

ID de la app de AdMob

ca-app-pub-3940256099942544~3347511713

Banner

ca-app-pub-3940256099942544/6300978111

Nativo

ca-app-pub-3940256099942544/2247696110

ID de la app para iOS/ID del bloque de anuncios

Elemento

ID de la app/ID del bloque de anuncios

ID de la app de AdMob

ca-app-pub-3940256099942544~1458002511

Banner

ca-app-pub-3940256099942544/2934735716

Nativo

ca-app-pub-3940256099942544/3986624511

Puedes obtener más información sobre los anuncios de prueba en la documentación para desarrolladores sobre los anuncios de prueba para Android y los anuncios de prueba para iOS.

Flutter utiliza complementos para brindar acceso a una amplia variedad de servicios específicos de la plataforma. Los complementos te permiten acceder a los servicios y las API de cada plataforma.

El complemento google_mobile_ads permite cargar y mostrar anuncios de banner, anuncios intersticiales, anuncios recompensados y anuncios nativos mediante la API de AdMob.

Como Flutter es un SDK multiplataforma, el complemento google_mobile_ads se aplica tanto a iOS como a Android. Por lo tanto, si agregas el complemento a tu app de Flutter, las versiones de iOS y Android de la app de anuncios intercalados de AdMob usarán este complemento.

Cómo agregar el complemento de anuncios de Google para dispositivos móviles como dependencia

Para acceder a las API de AdMob desde el proyecto AdMob inline ads, agrega google_mobile_ads como dependencia al archivo pubspec.yaml que se ubica en la raíz del proyecto.

pubspec.yaml

...
environment:
  # TODO: Update the minimum sdk version to 2.12.0 to support null safety.
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  google_fonts: ^0.3.9

  # TODO: Add google_mobile_ads as a dependency
  google_mobile_ads: ^0.12.0

...

Haz clic en Pub get para instalar el complemento en el proyecto AdMob inline ads.

39e66c2a3b7f078b.png

Cómo actualizar AndroidManifest.xml (Android)

  1. Abre el archivo android/app/src/main/AndroidManifest.xml en Android Studio.
  2. Para agregar el ID de la app de AdMob, inserta una etiqueta <meta-data> con el nombre com.google.android.gms.ads.APPLICATION_ID. Por ejemplo, si el ID de la app de AdMob es ca-app-pub-3940256099942544~3347511713, debes agregar las siguientes líneas al archivo AndroidManifest.xml.

AndroidManifest.xml

<manifest>
    ...
    <application>
       ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>
    </application>

</manifest>

Cómo actualizar Info.plist (iOS)

  1. Abre el archivo ios/Runner/Info.plist en Android Studio.
  2. Agrega una clave GADApplicationIdentifier con el valor de string del ID de la app de AdMob. Por ejemplo, si el ID de la app de AdMob es ca-app-pub-3940256099942544~1458002511, debes agregar las siguientes líneas al archivo Info.plist.

ios/Runner/Info.plist

...
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
...

Crea un archivo nuevo que se llame ad_helper.dart en el directorio lib. Luego, implementa la clase AdHelper, que brinda el ID de la app de AdMob y los ID de los bloques de anuncios para iOS y Android.

Asegúrate de reemplazar el ID de la app de AdMob (ca-app-pub-xxxxxx~yyyyy) y el ID del bloque de anuncios (ca-app-pub-xxxxxxx/yyyyyyyy) por los ID que creaste en el paso anterior.

ad_helper.dart

import 'dart:io';

class AdHelper {

  static String get bannerAdUnitId {
    if (Platform.isAndroid) {
      return "<YOUR_ANDROID_BANNER_AD_UNIT_ID";
    } else if (Platform.isIOS) {
      return "<YOUR_IOS_BANNER_AD_UNIT_ID>";
    } else {
      throw new UnsupportedError("Unsupported platform");
    }
  }

  static String get nativeAdUnitId {
    if (Platform.isAndroid) {
      return "<YOUR_ANDROID_NATIVE_AD_UNIT_ID>";
    } else if (Platform.isIOS) {
      return "<YOUR_IOS_NATIVE_AD_UNIT_ID>";
    } else {
      throw new UnsupportedError("Unsupported platform");
    }
  }
}

Use el siguiente fragmento de código si deseas usar el ID de la app de AdMob de prueba y los ID de los bloques de anuncios de prueba.

ad_helper.dart

import 'dart:io';

class AdHelper {

  static String get bannerAdUnitId {
    if (Platform.isAndroid) {
      return 'ca-app-pub-3940256099942544/6300978111';
    } else if (Platform.isIOS) {
      return 'ca-app-pub-3940256099942544/2934735716';
    }
    throw new UnsupportedError("Unsupported platform");
  }

  static String get nativeAdUnitId {
    if (Platform.isAndroid) {
      return 'ca-app-pub-3940256099942544/2247696110';
    } else if (Platform.isIOS) {
      return 'ca-app-pub-3940256099942544/3986624511';
    }
    throw new UnsupportedError("Unsupported platform");
  }
}

Antes de cargar anuncios, debes inicializar el SDK de anuncios de Google para dispositivos móviles. Abre el archivo lib/home_page.dart y modifica _initGoogleMobileAds() para inicializar el SDK antes de que se cargue la página principal.

Ten en cuenta que debes cambiar el tipo de datos que se muestra del método _initGoogleMobileAds() de Future<dynamic> a Future<InitializationStatus> para obtener el resultado de la inicialización del SDK después de que se complete.

home_page.dart

// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'package:flutter/material.dart';

...

class HomePage extends StatelessWidget {

  ...

  Future<InitializationStatus> _initGoogleMobileAds() {
    // TODO: Initialize Google Mobile Ads SDK
    return MobileAds.instance.initialize();
  }
}

En esta sección, mostrarás un anuncio de banner en el centro de la lista, como se observa en la siguiente captura de pantalla.

a3cd508128793e41.png

  1. Abre el archivo lib/banner_inline_page.dart.
  2. Agrega las siguientes líneas para importar ad_helper.dart y google_mobile_ads.dart:
...

// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';

// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';

class BannerInlinePage extends StatefulWidget {
  ...
}
  1. En la clase _BannerInlinePageState, agrega los siguientes miembros y métodos para un anuncio de banner.

Ten en cuenta que _kAdIndex indica el índice en el que se mostrará un anuncio de banner y se usa para calcular el índice del elemento desde el método _getDestinationItemIndex().

banner_inline_page.dart

class _BannerInlinePageState extends State<BannerInlinePage> {

  // TODO: Add _kAdIndex
  static final _kAdIndex = 4;

  // TODO: Add a BannerAd instance
  late BannerAd _ad;

  // TODO: Add _isAdLoaded
  bool _isAdLoaded = false;

  ...

  // TODO: Add _getDestinationItemIndex()
  int _getDestinationItemIndex(int rawIndex) {
    if (rawIndex >= _kAdIndex && _isAdLoaded) {
      return rawIndex - 1;
    }
    return rawIndex;
  }

  ...
}
  1. En el método initState(), crea y carga un elemento BannerAd para el banner de 320 x 50 (AdSize.banner). Ten en cuenta que se configura un objeto de escucha de eventos de anuncio a fin de actualizar la IU (setState()) cuando se carga un anuncio (MobileAdEvent.loaded).

banner_inline_page.dart

@override
void initState() {
  super.initState();

  // TODO: Create a BannerAd instance
  _ad = BannerAd(
    adUnitId: AdHelper.bannerAdUnitId,
    size: AdSize.banner,
    request: AdRequest(),
    listener: AdListener(
      onAdLoaded: (_) {
        setState(() {
          _isAdLoaded = true;
        });
      },
      onAdFailedToLoad: (ad, error) {
        // Releases an ad resource when it fails to load
        ad.dispose();

        print('Ad load failed (code=${error.code} message=${error.message})');
      },
    ),
  );

  // TODO: Load an ad
  _ad.load();
}
  1. Modifica el método build() para mostrar un anuncio de banner cuando esté disponible.
  2. Actualiza itemCount, para contar una entrada de anuncio de banner y actualiza el elemento itemBuilder, para renderizar un anuncio de banner en el índice del anuncio (_kAdIndex) cuando se cargue el anuncio.
  3. Actualiza el código para usar el método _getDestinationItemIndex() a fin de recuperar un índice para el elemento de contenido.

banner_inline_page.dart

@override
Widget build(BuildContext context) {
  return Scaffold(
    ...
    body: ListView.builder(
      // TODO: Adjust itemCount based on the ad load state
      itemCount: widget.entries.length + (_isAdLoaded ? 1 : 0),
      itemBuilder: (context, index) {
        // TODO: Render a banner ad
        if (_isAdLoaded && index == _kAdIndex) {
          return Container(
            child: AdWidget(ad: _ad),
            width: _ad.size.width.toDouble(),
            height: 72.0,
            alignment: Alignment.center,
          );
        } else {
          // TODO: Get adjusted item index from _getDestinationItemIndex()
          final item = widget.entries[_getDestinationItemIndex(index)];

          return ListTile(
            ...
          );
        }
      },
    ),
  );
}
  1. Libera el recurso asociado con el objeto BannerAd mediante una llamada al método BannerAd.dispose() en el método de devolución de llamada dispose().

banner_inline_page.dart

@override
void dispose() {
  // TODO: Dispose a BannerAd object
  _ad.dispose();

  super.dispose();
}

Eso es todo. Ejecuta el proyecto y haz clic en el botón Banner inline ad de la página principal. Después de que se cargue un anuncio, verás un anuncio de banner en el centro de la lista.

f1372268878a80a2.png c32af50872514224.png

En esta sección, mostrarás un anuncio nativo en el centro de la lista, como se observa en la siguiente captura de pantalla.

fbe594d5d9ce08ea.png

Los anuncios nativos se muestran a los usuarios que usan componentes de IU nativos de la plataforma (por ejemplo, View en Android o UIView en iOS).

Sin embargo, no es posible crear componentes de IU nativos directamente con widgets de Flutter. Por lo tanto, debes implementar un elemento NativeAdFactory para cada plataforma, que se usa con el objeto de compilar una reproducción de un anuncio nativo específico de la plataforma (UnifiedNativeAdView en Android y GADUnifiedNativeAdView en iOS) desde un objeto de anuncio nativo (UnifiedNativeAd en Android y GADUnifiedNativeAd en iOS).

Cómo implementar NativeAdFactory para Android (Java)

  1. Abre el archivo android/build.gradle (o cualquier archivo de la carpeta android) y haz clic en Open for Editing in Android Studio a fin de abrir un proyecto de Android.

88d3e99426cd8d8c.png

  1. Si se te pide que selecciones una ventana para abrir un proyecto nuevo, haz clic en New Window, de modo que el proyecto de Flutter permanezca abierto mientras trabajas en el proyecto de Android.

5d554e50a83f2bd1.png

Cómo crear la posición de un anuncio nativo

  1. Con el proyecto de Android abierto, haz clic con el botón derecho en app en el panel del proyecto de Android Studio y selecciona New > Android Resource File en el menú contextual.

7b2b6d28d0fe80a9.png

  1. En el diálogo New Resource File, Ingresa list_tile_native_ad.xml como nombre del archivo.
  2. Selecciona Layout como tipo de recurso e Ingresa com.google.android.gms.ads.formats.UnifiedNativeAdView como elemento raíz.
  3. Haz clic en OK para crear un archivo nuevo de posición.

615bf550a2ce9c45.png

  1. Implementa la posición del anuncio de la siguiente manera. Ten en cuenta que la posición debe coincidir con el diseño visual de la experiencia del usuario para la plataforma a la que está destinada.

list_tile_native_ad.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.formats.UnifiedNativeAdView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tv_list_tile_native_ad_attribution_small"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#F19938"
            android:text="Ad"
            android:textColor="#FFFFFF"
            android:textSize="12sp" />

        <ImageView
            android:id="@+id/iv_list_tile_native_ad_icon"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:scaleType="fitXY"
            tools:background="#EDEDED" />

        <TextView
            android:id="@+id/tv_list_tile_native_ad_attribution_large"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:background="#F19938"
            android:gravity="center"
            android:text="Ad"
            android:textColor="#FFFFFF"
            android:visibility="invisible" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="80dp"
            android:layout_marginLeft="80dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_list_tile_native_ad_headline"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:maxLines="1"
                android:textColor="#000000"
                android:textSize="16sp"
                tools:text="Headline" />

            <TextView
                android:id="@+id/tv_list_tile_native_ad_body"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:maxLines="1"
                android:textColor="#828282"
                android:textSize="14sp"
                tools:text="body" />

        </LinearLayout>

    </FrameLayout>

</com.google.android.gms.ads.formats.UnifiedNativeAdView>

Cómo crear la clase ListTileNativeAdFactory

  1. En el panel Project, haz clic con el botón derecho en el paquete com.codelab.flutter.admobinlineads y selecciona New > Java Class.

609df24b6a0b647e.png

  1. Ingresa ListTileNativeAdFactory como nombre y selecciona Class en la lista.

642050a1a83d5033.png

  1. Después de que aparezca el diálogo New Class, deja todo vacío y haz clic en OK.

Observarás que la clase ListTileNativeAdFactory se creó en el paquete com.codelab.flutter.admobinlineads.

3e7c27d864686efa.png

  1. Implementa la clase ListTileNativeAdFactory de la siguiente manera. Ten en cuenta que la clase implementa el método createNativeAd() en la interfaz GoogleMobileAdsPlugin.NativeAdFactory.

La clase de fábrica se encarga de crear un objeto de vista para renderizar un anuncio nativo. Como puedes observar en el código, la clase de fábrica crea un elemento UnitifedNativeAdView y lo propaga con un objeto UnifiedNativeAd.

ListTileNativeAdFactory.java

// TODO: Implement ListTileNativeAdFactory class

package com.codelab.flutter.admobinlineads;

import com.google.android.gms.ads.formats.NativeAd;
import com.google.android.gms.ads.formats.UnifiedNativeAd;
import com.google.android.gms.ads.formats.UnifiedNativeAdView;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Map;

import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin;

class ListTileNativeAdFactory implements GoogleMobileAdsPlugin.NativeAdFactory {

    private final Context context;

    ListTileNativeAdFactory(Context context) {
        this.context = context;
    }

    @Override
    public UnifiedNativeAdView createNativeAd(
            UnifiedNativeAd nativeAd, Map<String, Object> customOptions) {
        UnifiedNativeAdView nativeAdView = (UnifiedNativeAdView) LayoutInflater.from(context)
                .inflate(R.layout.list_tile_native_ad, null);

        TextView attributionViewSmall = nativeAdView
                .findViewById(R.id.tv_list_tile_native_ad_attribution_small);
        TextView attributionViewLarge = nativeAdView
                .findViewById(R.id.tv_list_tile_native_ad_attribution_large);

        ImageView iconView = nativeAdView.findViewById(R.id.iv_list_tile_native_ad_icon);
        NativeAd.Image icon = nativeAd.getIcon();
        if (icon != null) {
            attributionViewSmall.setVisibility(View.VISIBLE);
            attributionViewLarge.setVisibility(View.INVISIBLE);
            iconView.setImageDrawable(icon.getDrawable());
        } else {
            attributionViewSmall.setVisibility(View.INVISIBLE);
            attributionViewLarge.setVisibility(View.VISIBLE);
        }
        nativeAdView.setIconView(iconView);

        TextView headlineView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_headline);
        headlineView.setText(nativeAd.getHeadline());
        nativeAdView.setHeadlineView(headlineView);

        TextView bodyView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_body);
        bodyView.setText(nativeAd.getBody());
        bodyView.setVisibility(nativeAd.getBody() != null ? View.VISIBLE : View.INVISIBLE);
        nativeAdView.setBodyView(bodyView);

        nativeAdView.setNativeAd(nativeAd);

        return nativeAdView;
    }
}

Cómo registrar la clase ListTileNativeAdFactory

Se debe registrar una instancia de un elemento NativeAdFactory en el objeto GoogleMobileAdsPlugin para que se pueda usar en Flutter.

  1. Abre el archivo MainActivity.java, y anula el método configureFlutterEngine() y el método cleanUpFlutterEngine().
  2. Registra la clase ListTileNativeAdFactory con un ID de string único (listTile) en el método configureFlutterEngine().

MainActivity.java

public class MainActivity extends FlutterActivity {

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);

        // TODO: Register the ListTileNativeAdFactory
        GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "listTile",
                new ListTileNativeAdFactory(getContext()));
    }

    ...
}
  1. Se debe cancelar el registro de cada instancia NativeAdFactory durante el proceso de limpieza. Cancela el registro de la clase ListTileNativeAdFactory en el método cleanUpFlutterEngine().

MainActivity.java

public class MainActivity extends FlutterActivity {

    ...

    @Override
    public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine);

        // TODO: Unregister the ListTileNativeAdFactory
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile");
    }
}

Ahora está todo listo para usar la clase ListTileNativeAdFactory a fin de renderizar anuncios nativos en Android.

Cómo implementar NativeAdFactory para Android (Kotlin)

  1. Abre el archivo android/build.gradle (o cualquier archivo de la carpeta android) y haz clic en Open for Editing in Android Studio a fin de abrir un proyecto de Android.

88d3e99426cd8d8c.png

  1. Si se te pide que selecciones una ventana para abrir un proyecto nuevo, haz clic en New Window, de modo que el proyecto de Flutter permanezca abierto mientras trabajas en el proyecto de Android.

5d554e50a83f2bd1.png

Cómo crear la posición de un anuncio nativo

  1. Con el proyecto de Android abierto, haz clic con el botón derecho en app en el panel del proyecto de Android Studio y selecciona New > Android Resource File en el menú contextual.

7b2b6d28d0fe80a9.png

  1. En el diálogo New Resource File, Ingresa list_tile_native_ad.xml como nombre del archivo.
  2. Selecciona Layout como tipo de recurso e Ingresa com.google.android.gms.ads.formats.UnifiedNativeAdView como elemento raíz.
  3. Haz clic en OK para crear un archivo nuevo de posición.

615bf550a2ce9c45.png

  1. Implementa la posición del anuncio de la siguiente manera. Ten en cuenta que la posición debe coincidir con el diseño visual de la experiencia del usuario para la plataforma a la que está destinada.

list_tile_native_ad.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.formats.UnifiedNativeAdView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tv_list_tile_native_ad_attribution_small"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#F19938"
            android:text="Ad"
            android:textColor="#FFFFFF"
            android:textSize="12sp" />

        <ImageView
            android:id="@+id/iv_list_tile_native_ad_icon"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:scaleType="fitXY"
            tools:background="#EDEDED" />

        <TextView
            android:id="@+id/tv_list_tile_native_ad_attribution_large"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:background="#F19938"
            android:gravity="center"
            android:text="Ad"
            android:textColor="#FFFFFF"
            android:visibility="invisible" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="80dp"
            android:layout_marginLeft="80dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_list_tile_native_ad_headline"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:maxLines="1"
                android:textColor="#000000"
                android:textSize="16sp"
                tools:text="Headline" />

            <TextView
                android:id="@+id/tv_list_tile_native_ad_body"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:maxLines="1"
                android:textColor="#828282"
                android:textSize="14sp"
                tools:text="body" />

        </LinearLayout>

    </FrameLayout>

</com.google.android.gms.ads.formats.UnifiedNativeAdView>

Cómo crear la clase ListTileNativeAdFactory

  1. En el panel Project, haz clic con el botón derecho en el paquete com.codelab.flutter.admobinlineads y selecciona New > Kotlin File/Class.

7311744cb97cad75.png

  1. Ingresa ListTileNativeAdFactory como nombre y selecciona Class en la lista.

43a6ac7728826d8.png

  1. Observarás que la clase ListTileNativeAdFactory se creó en el paquete com.codelab.flutter.admobinlineads.
  2. Implementa la clase ListTileNativeAdFactory de la siguiente manera. Ten en cuenta que la clase implementa el método createNativeAd() en la interfaz GoogleMobileAdsPlugin.NativeAdFactory.

La clase de fábrica se encarga de crear un objeto de vista para renderizar un anuncio nativo. Como puedes observar en el código, la clase de fábrica crea un elemento UnitifedNativeAdView y lo propaga con un objeto UnifiedNativeAd.

ListTileNativeAdFactory.kt

// TODO: Implement ListTileNativeAdFactory class

package com.codelab.flutter.admobinlineads

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.google.android.gms.ads.formats.UnifiedNativeAd
import com.google.android.gms.ads.formats.UnifiedNativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin

class ListTileNativeAdFactory(val context: Context) : GoogleMobileAdsPlugin.NativeAdFactory {

    override fun createNativeAd(
            nativeAd: UnifiedNativeAd,
            customOptions: MutableMap<String, Any>?
    ): UnifiedNativeAdView {
        val nativeAdView = LayoutInflater.from(context)
                .inflate(R.layout.list_tile_native_ad, null) as UnifiedNativeAdView

        with(nativeAdView) {
            val attributionViewSmall =
                    findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_small)
            val attributionViewLarge =
                    findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_large)

            val iconView = findViewById<ImageView>(R.id.iv_list_tile_native_ad_icon)
            val icon = nativeAd.icon
            if (icon != null) {
                attributionViewSmall.visibility = View.VISIBLE
                attributionViewLarge.visibility = View.INVISIBLE
                iconView.setImageDrawable(icon.drawable)
            } else {
                attributionViewSmall.visibility = View.INVISIBLE
                attributionViewLarge.visibility = View.VISIBLE
            }
            this.iconView = iconView

            val headlineView = findViewById<TextView>(R.id.tv_list_tile_native_ad_headline)
            headlineView.text = nativeAd.headline
            this.headlineView = headlineView

            val bodyView = findViewById<TextView>(R.id.tv_list_tile_native_ad_body)
            with(bodyView) {
                text = nativeAd.body
                visibility = if (nativeAd.body.isNotEmpty()) View.VISIBLE else View.INVISIBLE
            }
            this.bodyView = bodyView

            setNativeAd(nativeAd)
        }

        return nativeAdView
    }
}

Cómo registrar la clase ListTileNativeAdFactory

Se debe registrar una instancia de un elemento NativeAdFactory en el objeto GoogleMobileAdsPlugin para que se pueda usar en Flutter.

  1. Abre el archivo MainActivity.kt, y anula el método configureFlutterEngine() y el método cleanUpFlutterEngine().
  2. Registra la clase ListTileNativeAdFactory con un ID de string único (listTile) en el método configureFlutterEngine().

MainActivity.kt

class MainActivity: FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        // TODO: Register the ListTileNativeAdFactory
        GoogleMobileAdsPlugin.registerNativeAdFactory(
                flutterEngine, "listTile", ListTileNativeAdFactory(context))
    }

    ...
}
  1. Se debe cancelar el registro de cada instancia NativeAdFactory durante el proceso de limpieza. Cancela el registro de la clase ListTileNativeAdFactory en el método cleanUpFlutterEngine().

MainActivity.kt

class MainActivity: FlutterActivity() {
    ...

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)

        // TODO: Unregister the ListTileNativeAdFactory
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile")
    }
}

Ahora está todo listo para usar la clase ListTileNativeAdFactory a fin de renderizar anuncios nativos en Android.

Cómo implementar NativeAdFactory para iOS (Objective-C)

Abre el archivo ios/Podfile (o cualquier archivo de la carpeta ios) y haz clic en Open iOS module in Xcode a fin de abrir un proyecto de iOS.

8f8b417705df6741.png

Cómo preparar la posición de un anuncio nativo

Deberás tener una vista personalizada (*.xib) para posicionar los elementos del anuncio nativo. En este codelab, la vista preconfigurada se usa para reducir el esfuerzo que realices.

Con el proyecto de iOS abierto en Xcode, confirma que exista ListTileNativeAdView.xib en el proyecto Runner.

8551d919ccc41818.png

Cómo crear la clase ListTileNativeAdFactory

  1. Desde el navegador del proyecto, haz clic con el botón derecho en el grupo Runner y selecciona New File a fin de crear un archivo de encabezado para la clase nueva.

249c43a7a1eac87.png

  1. En el diálogo de la plantilla, selecciona Header File y asígnale el nombre ListTileNativeAdFactory.
  2. Después de crear el archivo ListTileNativeAdFactory.h, define la clase ListNativeAdFactory de la siguiente manera:

ListTileNativeAdFactory.h

#ifndef ListTileNativeAdFactory_h
#define ListTileNativeAdFactory_h

// TODO: Import FLTGoogleMobileAdsPlugin.h
#import "FLTGoogleMobileAdsPlugin.h"

// TODO: Declare ListTileNativeAdFactory
@interface ListTileNativeAdFactory : NSObject<FLTNativeAdFactory>

@end

#endif /* ListTileNativeAdFactory_h */
  1. Para crear un archivo Objective-C, selecciona New File en el grupo Runner.
  2. En el siguiente diálogo, ingresa ListTileNativeAdFactory en el campo File y selecciona Empty File como tipo de archivo.

26f03ec58f26d1d2.png

  1. Después de hacer clic en Next, se te pedirá que selecciones una carpeta en la que se debe crear el archivo nuevo. Deja todo sin cambios y haz clic en Create.

c40f7080bdf513ff.png

  1. Implementa la clase ListTileNativeFactory de la siguiente manera. Ten en cuenta que la clase implementa el método createNativeAd() en el protocolo FLTNativeAdFactory.

La clase de fábrica se encarga de crear un objeto de vista para renderizar un anuncio nativo. Como puedes observar en el código, la clase de fábrica crea un elemento GADUnitifedNativeAdView y lo propaga con un objeto GADUnifiedNativeAd.

ListTileNativeAdFactory.m

// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"

// TODO: Implement ListTileNativeAdFactory
@implementation ListTileNativeAdFactory

- (GADUnifiedNativeAdView *)createNativeAd:(GADUnifiedNativeAd *)nativeAd
                             customOptions:(NSDictionary *)customOptions {
  GADUnifiedNativeAdView *nativeAdView =
    [[NSBundle mainBundle] loadNibNamed:@"ListTileNativeAdView" owner:nil options:nil].firstObject;

  ((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;

  ((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
  nativeAdView.bodyView.hidden = nativeAd.body ? NO : YES;

  ((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
  nativeAdView.iconView.hidden = nativeAd.icon ? NO : YES;

  nativeAdView.callToActionView.userInteractionEnabled = NO;

  nativeAdView.nativeAd = nativeAd;

  return nativeAdView;
}

@end

Cómo registrar la clase ListTileNativeAdFactory

Se debe registrar una implementación de un elemento FLTNativeAdFactory en el objeto FLTGoogleMobileAdsPlugin para que se pueda usar en Flutter.

Abre el archivo AppDelegate.m y registra el elemento ListTileNativeAdFactory con un ID de string único (listTile) mediante un llamado al método [FLTGoogleMobileAdsPlugin registerNativeAdFactory].

AppDelegate.m

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"

// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  // TODO: Register ListTileNativeAdFactory
  ListTileNativeAdFactory *listTileFactory = [[ListTileNativeAdFactory alloc] init];
  [FLTGoogleMobileAdsPlugin registerNativeAdFactory:self
                                        factoryId:@"listTile"
                                  nativeAdFactory:listTileFactory];

  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Ahora está todo listo para usar el elemento ListTileNativeAdFactory a fin de renderizar anuncios nativos en iOS.

Cómo implementar NativeAdFactory para iOS (Swift)

Abre el archivo ios/Podfile (o cualquier archivo de la carpeta ios) y haz clic en Open iOS module in Xcode a fin de abrir un proyecto de iOS.

8f8b417705df6741.png

Cómo preparar la posición de un anuncio nativo

Deberás tener una vista personalizada (*.xib) para posicionar los elementos del anuncio nativo. En este codelab, la vista preconfigurada se usa para reducir el esfuerzo que realices.

Con el proyecto de iOS abierto en Xcode, confirma que exista ListTileNativeAdView.xib en el proyecto Runner.

8551d919ccc41818.png

Cómo crear la clase ListTileNativeAdFactory

  1. Desde el navegador del proyecto, haz clic con el botón derecho en el grupo Runner y selecciona New File a fin de crear un archivo de encabezado para la clase nueva.

90bdca063c491134.png

  1. En el diálogo de la plantilla, selecciona Swift File y asígnale el nombre ListTileNativeAdFactory.
  2. Después de crear el archivo ListTileNativeAdFactory.swift, implementa la clase ListNativeAdFactory.

Ten en cuenta que la clase implementa el método createNativeAd() en el protocolo FLTNativeAdFactory.

La clase de fábrica se encarga de crear un objeto de vista para renderizar un anuncio nativo. Como puedes observar en el código, la clase de fábrica crea un elemento GADUnitifedNativeAdView y lo propaga con un objeto GADUnifiedNativeAd.

ListTileNativeAdFactory.swift

// TODO: Import google_mobile_ads
import google_mobile_ads

// TODO: Implement ListTileNativeAdFactory
class ListTileNativeAdFactory : FLTNativeAdFactory {

    func createNativeAd(_ nativeAd: GADUnifiedNativeAd,
                        customOptions: [AnyHashable : Any]? = nil) -> GADUnifiedNativeAdView? {
        let nibView = Bundle.main.loadNibNamed("ListTileNativeAdView", owner: nil, options: nil)!.first
        let nativeAdView = nibView as! GADUnifiedNativeAdView

        (nativeAdView.headlineView as! UILabel).text = nativeAd.headline

        (nativeAdView.bodyView as! UILabel).text = nativeAd.body
        nativeAdView.bodyView!.isHidden = nativeAd.body == nil

        (nativeAdView.iconView as! UIImageView).image = nativeAd.icon?.image
        nativeAdView.iconView!.isHidden = nativeAd.icon == nil

        nativeAdView.callToActionView?.isUserInteractionEnabled = false

        nativeAdView.nativeAd = nativeAd

        return nativeAdView
    }
}

Cómo registrar la clase ListTileNativeAdFactory

Se debe registrar una implementación de un elemento FLTNativeAdFactory en el objeto FLTGoogleMobileAdsPlugin para que se pueda usar en Flutter.

Abre el archivo AppDelegate.m y registra el elemento ListTileNativeAdFactory con un ID de string único (listTile) mediante un llamado al método FLTGoogleMobileAdsPlugin.registerNativeAdFactory().

AppDelegate.swift

import UIKit
import Flutter

// TODO: Import google_mobile_ads
import google_mobile_ads

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // TODO: Register ListTileNativeAdFactory
    let listTileFactory = ListTileNativeAdFactory()
    FLTGoogleMobileAdsPlugin.registerNativeAdFactory(
        self, factoryId: "listTile", nativeAdFactory: listTileFactory)

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Ahora está todo listo para usar el elemento ListTileNativeAdFactory a fin de renderizar anuncios nativos en iOS.

Cómo integrar el anuncio nativo con los widgets de Flutter

  1. Abre el archivo lib/native_inline_page.dart. Luego, para importar ad_helper.dart y google_mobile_ads.dart, agrega las siguientes líneas:

native_inline_page.dart

...

// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';

// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';

class NativeInlinePage extends StatefulWidget {
  ...
}
  1. En la clase _NativeInlinePageState, agrega los siguientes miembros y métodos para un anuncio nativo.

Ten en cuenta que _kAdIndex indica el índice en el que se mostrará un anuncio de banner y se usa para calcular el índice del elemento desde el método _getDestinationItemIndex().

native_inline_page.dart

class _NativeInlinePageState extends State<NativeInlinePage> {

  // TODO: Add _kAdIndex
  static final _kAdIndex = 4;

  // TODO: Add a NativeAd instance
  late NativeAd _ad;

  // TODO: Add _isAdLoaded
  bool _isAdLoaded = false;

  ...

  // TODO: Add _getDestinationItemIndex()
  int _getDestinationItemIndex(int rawIndex) {
    if (rawIndex >= _kAdIndex && _isAdLoaded) {
      return rawIndex - 1;
    }
    return rawIndex;
  }

  ...
}
  1. En el método initState(), crea y carga un objeto NativeAd que usa ListTileNativeAdFactory para generar una reproducción de un anuncio nativo.

Ten en cuenta que se usa el mismo ID de fábrica (listTile) que se utilizó para registrar la fábrica del complemento.

native_inline_page.dart

@override
void initState() {
  super.initState();

  // TODO: Create a NativeAd instance
  _ad = NativeAd(
    adUnitId: AdHelper.nativeAdUnitId,
    factoryId: 'listTile',
    request: AdRequest(),
    listener: AdListener(
      onAdLoaded: (_) {
        setState(() {
          _isAdLoaded = true;
        });
      },
      onAdFailedToLoad: (ad, error) {
        // Releases an ad resource when it fails to load
        ad.dispose();

        print('Ad load failed (code=${error.code} message=${error.message})');       },
    ),
  );

  _ad.load();
}
  1. Modifica el método build() para mostrar un anuncio de banner cuando esté disponible.
  2. Actualiza itemCount, para contar una entrada de anuncio de banner y actualiza el elemento itemBuilder, para renderizar un anuncio de banner en el índice del anuncio (_kAdIndex) cuando se cargue el anuncio.
  3. Actualiza el código para usar el método _getDestinationItemIndex() a fin de recuperar un índice para el elemento de contenido.

native_inline_page.dart

@override
Widget build(BuildContext context) {
  return Scaffold(
    ...
    body: ListView.builder(
      // TODO: Adjust itemCount based on the ad load state
      itemCount: widget.entries.length + (_isAdLoaded ? 1 : 0),
      itemBuilder: (context, index) {
        // TODO: Render a banner ad
        if (_isAdLoaded && index == _kAdIndex) {
          return Container(
            child: AdWidget(ad: _ad),
            height: 72.0,
            alignment: Alignment.center,
          );
        } else {
          // TODO: Get adjusted item index from _getDestinationItemIndex()
          final item = widget.entries[_getDestinationItemIndex(index)];

          return ListTile(
            ...
          );
        }
      },
    ),
  );
}
  1. Libera el recurso asociado con el objeto NativeAd mediante un llamado al método NativeAd.dispose() en el método de devolución de llamada dispose().

native_inline_page.dart

@override
void dispose() {
  // TODO: Dispose a NativeAd object
  _ad.dispose();

  super.dispose();
}

Eso es todo. Ejecuta el proyecto y haz clic en el botón Native inline ad de la página principal. Después de que se cargue un anuncio, verás un anuncio nativo en el centro de la lista.

fbe594d5d9ce08ea.png 5ead873222c800eb.png

Completaste el codelab. Puedes encontrar el código completo para este codelab en la carpeta android_studio_folder.pngcomplete o android_studio_folder.png complete_kotlin_swift.