Como adicionar anúncios de banner e nativos in-line da AdMob a um app Flutter

Neste codelab, você implementará um banner e um anúncio nativo in-line da AdMob em um app Flutter.

O que você criará

Este codelab orientará você na implementação de um banner e de anúncios nativos in-line da AdMob em um app Flutter. Para isso, você usará o plug-in de anúncios para dispositivos móveis do Google para o Flutter.

Se você encontrar algum problema neste codelab (como bugs no código, erros gramaticais e instruções pouco claras), relate-o no link Informar um erro, no canto inferior esquerdo do codelab.

O que você aprenderá

  • Como configurar o plug-in de anúncios para dispositivos móveis do Google para o Flutter.
  • Como implementar um banner in-line e anúncios premiados em um app Flutter.

Pré-requisitos

  • Android Studio 4.1 ou versão mais recente
  • Xcode 12 ou versão mais recente (para desenvolvimento no iOS)

Como você classificaria seu nível de experiência com a AdMob?

Iniciante Intermediário Proficiente

Como você classificaria seu nível de experiência com o Flutter?

Iniciante Intermediário Proficiente

Configurar o ambiente de desenvolvimento do Flutter

  1. Instale o SDK do Flutter (link em inglês) na sua máquina.
  2. Abra o Android Studio e instale a extensão do Flutter para o Android Studio (link em inglês).

Fazer o download do código

Fazer o download do código-fonte Visualizar o repositório no GitHub

Depois de fazer o download do arquivo ZIP, extraia o conteúdo dele. Haverá uma pasta chamada admob-inline-ads-in-flutter-main.

Como alternativa, é possível clonar o repositório do GitHub usando a linha de comando:

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

O repositório contém três pastas:

  • android_studio_folder.png starter: código inicial que você criará neste codelab.
  • android_studio_folder.png complete: código completo deste codelab (Java e Objective-C para código nativo).
  • android_studio_folder.png complete_kotlin_swift: código completo deste codelab (Kotlin e Swift para código nativo).

Como o Flutter é um SDK multiplataforma, é necessário adicionar um app e blocos de anúncios na AdMob para Android e iOS.

Configurar para Android

Para a configuração para Android, adicione um app Android e crie blocos de anúncios.

Adicionar um app Android

  1. No console da AdMob, clique em ADICIONAR APP no menu Apps.
  2. Ao ver a pergunta O app está disponível na Google Play ou na App Store?, clique em NÃO.
  3. No campo de nome do app, insira AdMob inline ads e selecione Android como a plataforma.

e4d968797610c8c0.png

  1. Não é necessário ativar as métricas do usuário para este codelab. No entanto, recomendamos que elas sejam ativadas porque isso permite entender o comportamento do usuário de forma mais detalhada. Clique em ADICIONAR para concluir o processo.

5204925f5c652b41.png

Criar blocos de anúncios

Para adicionar blocos de anúncios:

  1. Selecione o app Anúncios inline da AdMob no menu Apps do console da AdMob.
  2. Clique no menu Blocos de anúncios.

Banner

  1. Clique em ADICIONAR BLOCO DE ANÚNCIOS.
  2. Selecione Banner como o formato.
  3. Insira android-inline-banner no campo Nome do bloco de anúncios.
  4. Clique em CRIAR BLOCO DE ANÚNCIOS para concluir o processo.

Nativo

  1. Clique em ADICIONAR BLOCO DE ANÚNCIOS.
  2. Selecione Nativo avançado como o formato.
  3. Insira android-inline-native no campo Nome do bloco de anúncios.
  4. Clique em CRIAR BLOCO DE ANÚNCIOS para concluir o processo.

Geralmente leva algumas horas para que um novo bloco veicule anúncios.

Caso queira testar o comportamento do anúncio imediatamente, use os IDs do app de teste e do bloco de anúncios listados nas tabelas de IDs do app Android e do bloco de anúncios.

Configurar para iOS

Para fazer a configuração para iOS, adicione um app iOS e crie blocos de anúncios.

Adicionar um app iOS

  1. No console da AdMob, clique em ADICIONAR APP no menu Apps.
  2. Ao ver a pergunta O app está disponível na Google Play ou na App Store?, clique em NÃO.
  3. No campo de nome do app, insira AdMob inline ads e selecione iOS como a plataforma.

e00fc8ac930a251b.png

  1. Não é necessário ativar as métricas do usuário para este codelab. No entanto, recomendamos que elas sejam ativadas porque isso permite entender o comportamento do usuário de forma mais detalhada. Clique em ADICIONAR para concluir o processo.

5204925f5c652b41.png

Criar blocos de anúncios

Para adicionar blocos de anúncios:

  1. Selecione o app Anúncios inline da AdMob no menu Apps do console da AdMob.
  2. Clique no menu Blocos de anúncios.

Banner

  1. Clique em ADICIONAR BLOCO DE ANÚNCIOS.
  2. Selecione Banner como o formato.
  3. Insira ios-inline-banner no campo Nome do bloco de anúncios.
  4. Clique em CRIAR BLOCO DE ANÚNCIOS para concluir o processo.

Nativo

  1. Clique em ADICIONAR BLOCO DE ANÚNCIOS.
  2. Selecione Nativo avançado como o formato.
  3. Insira ios-inline-native no campo Nome do bloco de anúncios.
  4. Clique em CRIAR BLOCO DE ANÚNCIOS para concluir o processo.

Geralmente leva algumas horas para que um novo bloco veicule anúncios.

Caso queira testar o comportamento do anúncio imediatamente, use os IDs do app de teste e do bloco de anúncios listados na tabela a seguir.

Opcional: usar o app e os blocos de anúncios de teste da AdMob

Caso prefira seguir o codelab, em vez de criar um novo aplicativo e blocos de anúncios por conta própria, você pode usar os IDs do app e do bloco de anúncios de teste da AdMob listados nas tabelas a seguir.

ID do app Android/ID do bloco de anúncios

Item

ID do app/ID do bloco de anúncios

ID do app AdMob

ca-app-pub-3940256099942544~3347511713

Banner

ca-app-pub-3940256099942544/6300978111

Nativo

ca-app-pub-3940256099942544/2247696110

ID do app iOS/ID do bloco de anúncios

Item

ID do app/ID do bloco de anúncios

ID do app AdMob

ca-app-pub-3940256099942544~1458002511

Banner

ca-app-pub-3940256099942544/2934735716

Nativo

ca-app-pub-3940256099942544/3986624511

Para ver mais informações sobre os anúncios de teste, consulte a documentação do desenvolvedor sobre anúncios de teste para Android e anúncios de teste para iOS.

O Flutter usa plug-ins para oferecer acesso a uma ampla variedade de serviços específicos da plataforma. Os plug-ins permitem que você acesse serviços e APIs em cada plataforma.

O plug-in google_mobile_ads (link em inglês) é compatível com o carregamento e a exibição de banners, anúncios intersticiais, premiados e nativos usando a API AdMob.

Como o Flutter é um SDK multiplataforma, o plug-in google_mobile_ads funciona tanto para iOS quanto para Android. Assim, ao adicionar o plug-in ao app Flutter, ele será usado pelas versões do Android e do iOS do app de anúncios in-line da AdMob.

Adicionar o plug-in de anúncios para dispositivos móveis do Google como uma dependência

Para acessar as APIs AdMob no projeto Anúncios in-line da AdMob, adicione google_mobile_ads como uma dependência no arquivo pubspec.yaml, localizado na raiz do projeto.

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

...

Clique em Pub get para instalar o plug-in no projeto Anúncios in-line da AdMob.

39e66c2a3b7f078b.png

Atualizar o AndroidManifest.xml (Android)

  1. Abra o arquivo android/app/src/main/AndroidManifest.xml no Android Studio.
  2. Adicione o ID do app AdMob inserindo uma tag <meta-data> com o nome com.google.android.gms.ads.APPLICATION_ID. Por exemplo, se o ID do app da AdMob for ca-app-pub-3940256099942544~3347511713, será necessário inserir as linhas a seguir no arquivo 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>

Atualizar o Info.plist (iOS)

  1. Abra o arquivo ios/Runner/Info.plist no Android Studio.
  2. Adicione uma chave GADApplicationIdentifier com o valor de string do ID do app da AdMob. Por exemplo, se o ID do app da AdMob for ca-app-pub-3940256099942544~1458002511, será necessário inserir as linhas a seguir ao arquivo Info.plist.

ios/Runner/Info.plist

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

Crie um novo arquivo chamado ad_helper.dart no diretório lib. Em seguida, implemente a classe AdHelper, que fornece um ID do app AdMob e do bloco de anúncios para Android e iOS.

Substitua o ID do app da AdMob (ca-app-pub-xxxxxx~yyyyy) e o ID do bloco de anúncios (ca-app-pub-xxxxxxx/yyyyyyyy) pelos IDs criados na etapa 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");
    }
  }
}

Implemente o snippet de código a seguir caso queira usar os IDs do app e do bloco de anúncios de teste da AdMob.

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 carregar anúncios, é necessário inicializar o SDK dos anúncios para dispositivos móveis do Google. Abra o arquivo lib/home_page.dart e modifique _initGoogleMobileAds() para inicializar o SDK antes que a página inicial seja carregada.

É necessário mudar o tipo de retorno do método _initGoogleMobileAds() de Future<dynamic> para Future<InitializationStatus>, para conseguir o resultado de inicialização do SDK após a conclusão.

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();
  }
}

Nesta seção, você exibirá um anúncio de banner no meio de uma lista, como mostrado na captura de tela a seguir.

a3cd508128793e41.png

  1. Abra o arquivo lib/banner_inline_page.dart.
  2. Importe ad_helper.dart e google_mobile_ads.dart adicionando as seguintes linhas:
...

// 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. Na classe _BannerInlinePageState, adicione os membros e métodos a seguir para um anúncio de banner.

_kAdIndex mostra o índice em que um anúncio de banner será exibido e é usado para calcular o índice de itens de acordo com o 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. No método initState(), crie e carregue um BannerAd para o banner de 320 x 50 (AdSize.banner). Um listener de eventos de anúncio é configurado para atualizar a IU (setState()) quando o anúncio for carregado (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. Modifique o método build() para exibir um anúncio de banner quando disponível.
  2. Atualize o itemCount, para contar uma entrada de anúncio de banner e atualize o itemBuilder, para renderizar um anúncio de banner no índice (_kAdIndex) quando ele for carregado.
  3. Atualize o código para usar o método _getDestinationItemIndex() para recuperar um índice para o item de conteúdo.

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. Libere o recurso associado ao objeto BannerAd chamando o método BannerAd.dispose() no método de callback dispose().

banner_inline_page.dart

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

  super.dispose();
}

Pronto! Execute o projeto e clique no botão Banner inline ad na página inicial. Após o carregamento, você verá um anúncio de banner no meio da lista.

f1372268878a80a2.png c32af50872514224.png

Nesta seção, você exibirá um anúncio nativo no meio de uma lista, como mostrado na captura de tela a seguir.

fbe594d5d9ce08ea.png

Os anúncios nativos são apresentados aos usuários que usam componentes de IU nativos da plataforma (por exemplo, View no Android ou UIView no iOS).

No entanto, não é possível criar componentes de IU nativos diretamente usando os widgets do Flutter. Dessa forma, é necessário implementar uma NativeAdFactory para cada plataforma, que é usada para criar uma visualização do anúncio nativo específico da plataforma (UnifiedNativeAdView no Android e GADUnifiedNativeAdView no iOS) em um objeto de anúncio nativo (UnifiedNativeAd no Android e GADUnifiedNativeAd no iOS).

Implementar a NativeAdFactory para Android (Java)

  1. Abra o arquivo android/build.gradle (ou qualquer arquivo na pasta android) e clique em Open for Editing in Android Studio para abrir um projeto Android.

88d3e99426cd8d8c.png

  1. Caso seja solicitado que você selecione uma janela para abrir um novo projeto, clique em New Window para deixar o projeto do Flutter aberto enquanto você trabalha no projeto Android.

5d554e50a83f2bd1.png

Criar um layout de anúncio nativo

  1. Com o projeto Android aberto, clique com o botão direito do mouse em app no painel do projeto no Android Studio e selecione New > Android Resource File no menu de contexto.

7b2b6d28d0fe80a9.png

  1. Na caixa de diálogo New Resource File, insira list_tile_native_ad.xml como o nome do arquivo.
  2. Selecione Layout como o tipo de recurso e insira com.google.android.gms.ads.formats.UnifiedNativeAdView como um elemento raiz.
  3. Clique em OK para criar um novo arquivo de layout.

615bf550a2ce9c45.png

  1. Implemente o layout do anúncio da seguinte maneira: O layout precisa corresponder ao design visual da experiência do usuário da plataforma a que o anúncio se destina.

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>

Criar a classe ListTileNativeAdFactory

  1. No painel "Project", clique com o botão direito do mouse no pacote com.codelab.flutter.admobinlineads e selecione New > Java Class.

609df24b6a0b647e.png

  1. Insira ListTileNativeAdFactory como o nome e selecione Class na lista.

642050a1a83d5033.png

  1. Quando a caixa de diálogo New Class for exibida, deixe tudo em branco e clique em OK.

Você verá que a classe ListTileNativeAdFactory foi criada no pacote com.codelab.flutter.admobinlineads.

3e7c27d864686efa.png

  1. Implemente a classe ListTileNativeAdFactory da seguinte maneira: A classe implementa o método createNativeAd() na interface GoogleMobileAdsPlugin.NativeAdFactory.

A classe factory é responsável por criar um objeto de visualização para renderizar um anúncio nativo. Como é possível ver no código, a classe factory cria uma UnitifedNativeAdView que é preenchida com um 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;
    }
}

Registrar a classe ListTileNativeAdFactory

Uma instância da NativeAdFactory precisa ser registrada no GoogleMobileAdsPlugin para que ela possa ser usada no Flutter.

  1. Abra o arquivo MainActivity.java e modifique os métodos configureFlutterEngine() e cleanUpFlutterEngine().
  2. Registre a classe ListTileNativeAdFactory com um ID de string exclusivo (listTile) no 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. É necessário cancelar o registro de todas as instâncias da NativeAdFactory durante o processo de limpeza. Cancele o registro da classe ListTileNativeAdFactory no 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");
    }
}

Agora está tudo pronto para usar a classe ListTileNativeAdFactory para renderizar anúncios nativos no Android.

Implementar a NativeAdFactory para Android (Kotlin)

  1. Abra o arquivo android/build.gradle (ou qualquer arquivo na pasta android) e clique em Open for Editing in Android Studio para abrir um projeto Android.

88d3e99426cd8d8c.png

  1. Caso seja solicitado que você selecione uma janela para abrir um novo projeto, clique em New Window para deixar o projeto do Flutter aberto enquanto você trabalha no projeto Android.

5d554e50a83f2bd1.png

Criar um layout de anúncio nativo

  1. Com o projeto Android aberto, clique com o botão direito do mouse em app no painel do projeto no Android Studio e selecione New > Android Resource File no menu de contexto.

7b2b6d28d0fe80a9.png

  1. Na caixa de diálogo New Resource File, insira list_tile_native_ad.xml como o nome do arquivo.
  2. Selecione Layout como o tipo de recurso e insira com.google.android.gms.ads.formats.UnifiedNativeAdView como um elemento raiz.
  3. Clique em OK para criar um novo arquivo de layout.

615bf550a2ce9c45.png

  1. Implemente o layout do anúncio da seguinte maneira: O layout precisa corresponder ao design visual da experiência do usuário da plataforma a que o anúncio se destina.

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>

Criar a classe ListTileNativeAdFactory

  1. No painel "Project", clique com o botão direito do mouse no pacote com.codelab.flutter.admobinlineads e selecione New > Kotlin File/Class.

7311744cb97cad75.png

  1. Insira ListTileNativeAdFactory como o nome e selecione Class na lista.

43a6ac7728826d8.png

  1. Você verá que a classe ListTileNativeAdFactory foi criada no pacote com.codelab.flutter.admobinlineads.
  2. Implemente a classe ListTileNativeAdFactory da seguinte maneira: A classe implementa o método createNativeAd() na interface GoogleMobileAdsPlugin.NativeAdFactory.

A classe factory é responsável por criar um objeto de visualização para renderizar um anúncio nativo. Como é possível ver no código, a classe factory cria uma UnitifedNativeAdView que é preenchida com um 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
    }
}

Registrar a classe ListTileNativeAdFactory

Uma instância da NativeAdFactory precisa ser registrada no GoogleMobileAdsPlugin para que ela possa ser usada no Flutter.

  1. Abra o arquivo MainActivity.kt e modifique os métodos configureFlutterEngine() e cleanUpFlutterEngine().
  2. Registre a classe ListTileNativeAdFactory com um ID de string exclusivo (listTile) no 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. É necessário cancelar o registro de todas as instâncias da NativeAdFactory durante o processo de limpeza. Cancele o registro da classe ListTileNativeAdFactory no método cleanUpFlutterEngine().

MainActivity.kt

class MainActivity: FlutterActivity() {
    ...

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

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

Agora está tudo pronto para usar a classe ListTileNativeAdFactory para renderizar anúncios nativos no Android.

Implementar a NativeAdFactory para iOS (Objective-C)

Abra o arquivo ios/Podfile (ou qualquer arquivo na pasta iOS) e clique em Open iOS module in Xcode para abrir um projeto iOS.

8f8b417705df6741.png

Preparar o layout de um anúncio nativo

É necessário ter uma visualização personalizada (*.xib) para definir o layout dos recursos de anúncios nativos. Neste codelab, a visualização pré-configurada é usada para facilitar o processo.

Com o projeto iOS aberto no Xcode, confirme se ListTileNativeAdView.xib existe no projeto Runner.

8551d919ccc41818.png

Criar a classe ListTileNativeAdFactory

  1. No navegador de projetos, clique com o botão direito do mouse no grupo Runner e selecione New File para criar um arquivo principal para a nova classe.

249c43a7a1eac87.png

  1. Na caixa de diálogo do modelo, selecione o Header File e nomeie-o como ListTileNativeAdFactory.
  2. Depois que o arquivo ListTileNativeAdFactory.h for criado, defina a classe ListNativeAdFactory da seguinte maneira:

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. Crie um arquivo Objective-C selecionando New File no grupo Runner.
  2. Na próxima caixa de diálogo, insira ListTileNativeAdFactory no campo File e selecione Empty File como o tipo de arquivo.

26f03ec58f26d1d2.png

  1. Depois de clicar em Next, será solicitado que você selecione a pasta em que o novo arquivo será criado. Deixe tudo como está e clique em Create.

c40f7080bdf513ff.png

  1. Implemente a classe ListTileNativeFactory da seguinte maneira: A classe implementa o método createNativeAd() no protocolo FLTNativeAdFactory.

A classe factory é responsável por criar um objeto de visualização para renderizar um anúncio nativo. Como é possível ver no código, a classe factory cria uma GADUnitifedNativeAdView que é preenchida com um 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

Registrar a classe ListTileNativeAdFacotry

Uma implementação da FLTNativeAdFactory precisa ser registrada no FLTGoogleMobileAdsPlugin para que ela possa ser usada no Flutter.

Abra o arquivo AppDelegate.m e registre a ListTileNativeAdFactory com um ID de string exclusivo (listTile) chamando o 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

Agora está tudo pronto para usar a ListTileNativeAdFactory para renderizar anúncios nativos no iOS.

Implementar a NativeAdFactory para iOS (Swift)

Abra o arquivo ios/Podfile (ou qualquer arquivo na pasta iOS) e clique em Open iOS module in Xcode para abrir um projeto iOS.

8f8b417705df6741.png

Preparar o layout de um anúncio nativo

É necessário ter uma visualização personalizada (*.xib) para definir o layout dos recursos de anúncios nativos. Neste codelab, a visualização pré-configurada é usada para facilitar o processo.

Com o projeto iOS aberto no Xcode, confirme se ListTileNativeAdView.xib existe no projeto Runner.

8551d919ccc41818.png

Criar a classe ListTileNativeAdFactory

  1. No navegador de projetos, clique com o botão direito do mouse no grupo Runner e selecione New File para criar um arquivo principal para a nova classe.

90bdca063c491134.png

  1. Na caixa de diálogo do modelo, selecione Swift File e nomeie-o como ListTileNativeAdFactory.
  2. Depois que o arquivo ListTileNativeAdFactory.swift for criado, implemente a classe ListNativeAdFactory.

A classe implementa o método createNativeAd() no protocolo FLTNativeAdFactory.

A classe factory é responsável por criar um objeto de visualização para renderizar um anúncio nativo. Como é possível ver no código, a classe factory cria uma GADUnitifedNativeAdView que é preenchida com um 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
    }
}

Registrar a classe ListTileNativeAdFacotry

Uma implementação da FLTNativeAdFactory precisa ser registrada no FLTGoogleMobileAdsPlugin para que ela possa ser usada no Flutter.

Abra o arquivo AppDelegate.m e registre a ListTileNativeAdFactory com um ID de string exclusivo (listTile) chamando o 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)
  }
}

Agora está tudo pronto para usar a ListTileNativeAdFactory para renderizar anúncios nativos no iOS.

Integrar o anúncio nativo com widgets do Flutter

  1. Abra o arquivo lib/native_inline_page.dart. Em seguida, importe ad_helper.dart e google_mobile_ads.dart adicionando as seguintes linhas:

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. Na classe _NativeInlinePageState, adicione os seguintes membros e métodos para anúncios nativos.

_kAdIndex mostra o índice em que um anúncio de banner será exibido e é usado para calcular o índice de itens de acordo com o 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. No método initState(), crie e carregue um NativeAd que usa a ListTileNativeAdFactory para gerar uma visualização de anúncio nativo.

O mesmo ID de factory (listTile) é usado para registrar factory no plug-in que é usado.

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. Modifique o método build() para exibir um anúncio de banner quando disponível.
  2. Atualize itemCount, para contar uma entrada de anúncio de banner e atualize itemBuilder, para renderizar um banner no índice de anúncios (_kAdIndex) quando ele for carregado.
  3. Atualize o código para usar o método _getDestinationItemIndex() para recuperar um índice para o item de conteúdo.

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. Libere o recurso associado ao objeto NativeAd chamando o método NativeAd.dispose() no método de callback dispose().

native_inline_page.dart

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

  super.dispose();
}

Pronto! Execute o projeto e clique no botão Native inline ad na página inicial. Após o carregamento, você verá um anúncio nativo no meio da lista.

fbe594d5d9ce08ea.png 5ead873222c800eb.png

Você concluiu o codelab. O código completo deste codelab está disponível na pasta android_studio_folder.pngcomplete ou android_studio_folder.png complete_kotlin_swift.