Добавление баннера AdMob и встроенной рекламы в приложение Flutter

1. Введение

В этом практическом задании вы реализуете баннер AdMob и встроенную рекламу AdMob в приложении Flutter.

Что вы построите

В этом практическом занятии вы узнаете, как реализовать встроенный баннер AdMob и нативные встроенные объявления AdMob в приложении Flutter, используя плагин Google Mobile Ads для Flutter.

Если у вас возникнут какие-либо проблемы (ошибки в коде, грамматические неточности, неясные формулировки и т. д.) во время выполнения этого практического задания, сообщите о них, используя ссылку «Сообщить об ошибке» в левом нижнем углу задания.

Что вы узнаете

  • Как настроить плагин Google Mobile Ads Flutter
  • Как реализовать встроенный баннер и рекламу с вознаграждением в приложении Flutter

Что вам понадобится

  • Android Studio 4.1 или более поздняя версия
  • Xcode 12 или более поздней версии (для разработки под iOS)

Как бы вы оценили свой уровень опыта работы с AdMob?

Новичок Средний Профессионал

Как бы вы оценили свой уровень опыта работы с Flutter?

Новичок Средний Профессионал

2. Настройте среду разработки Flutter.

Для выполнения этой лабораторной работы вам понадобятся два программных компонента: Flutter SDK и редактор .

Вы можете выполнить это практическое задание, используя любое из следующих устройств:

  • Физическое устройство Android или iOS , подключенное к компьютеру и настроенное на режим разработчика.
  • Симулятор iOS (требуется установка инструментов Xcode).
  • Эмулятор Android (требуется настройка в Android Studio).
  • Для работы требуется браузер (для отладки необходим Chrome).
  • Если вы разрабатываете настольное приложение для Windows , Linux или macOS , вам необходимо работать на той платформе, на которой вы планируете его развернуть. Таким образом, если вы хотите разработать настольное приложение для Windows, вам необходимо использовать Windows для доступа к соответствующей цепочке сборки. Существуют специфические требования к операционной системе, которые подробно описаны в документации docs.flutter.dev/desktop .

Скачать код

После загрузки ZIP-файла распакуйте его содержимое. У вас появится папка с именем admob-inline-ads-in-flutter-main .

В качестве альтернативы вы можете клонировать репозиторий GitHub из командной строки:

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

Репозиторий содержит три папки:

  • android_studio_folder.png Задание: Начальный код, который вы будете создавать в этом практическом занятии.
  • android_studio_folder.png Завершено: Код для данной практической работы готов. (Java и Objective-C для нативного кода)
  • android_studio_folder.png complete_kotlin_swift: Завершенный код для этого практического занятия. (Kotlin и Swift для нативного кода)

3. Настройте приложение AdMob и рекламные блоки.

Поскольку Flutter — это многоплатформенный SDK, вам необходимо добавить приложение и рекламные блоки как для Android, так и для iOS в AdMob.

Настройка для Android

Для настройки под Android необходимо добавить приложение Android и создать рекламные блоки.

Добавить приложение для Android

  1. В консоли AdMob нажмите кнопку «ДОБАВИТЬ ПРИЛОЖЕНИЕ» в меню «Приложения» .
  2. Когда вас спросят: «Вы опубликовали свое приложение в Google Play или App Store?» , нажмите «НЕТ» .
  3. В поле «Название приложения» введите AdMob inline ads и выберите Android в качестве платформы.

d51828db0e2e4f6c.png

  1. Включение пользовательских метрик не является обязательным для выполнения этого практического задания. Однако мы рекомендуем это сделать, поскольку это позволит вам более детально понять поведение пользователей. Нажмите ДОБАВИТЬ , чтобы завершить процесс.

b918bf44362813a9.png

Создавайте рекламные блоки

Чтобы добавить рекламные блоки:

  1. В консоли AdMob выберите приложение «Встроенная реклама AdMob» в меню « Приложения ».
  2. Нажмите на меню «Рекламные блоки» .

Баннер

  1. Нажмите «ДОБАВИТЬ РЕКЛАМНЫЙ БЛОК» .
  2. Выберите формат «Баннер» .
  3. В поле «Название рекламного блока» введите android-inline-banner .
  4. Нажмите «СОЗДАТЬ РЕКЛАМНЫЙ БЛОК» , чтобы завершить процесс.

Родной

  1. Нажмите «ДОБАВИТЬ РЕКЛАМНЫЙ БЛОК» .
  2. Выберите формат «Native advanced» .
  3. В поле « Название рекламного блока» введите android-inline-native .
  4. Нажмите «СОЗДАТЬ РЕКЛАМНЫЙ БЛОК» , чтобы завершить процесс.

Обычно для показа нового рекламного блока требуется несколько часов.

Если вы хотите немедленно проверить работу рекламы, используйте идентификаторы тестового приложения и рекламного блока, указанные в таблицах идентификаторов приложений/рекламных блоков для Android и iOS.

Настройка для iOS

Для настройки под iOS необходимо добавить iOS-приложение и создать рекламные блоки.

Добавить приложение для iOS

  1. В консоли AdMob нажмите кнопку «ДОБАВИТЬ ПРИЛОЖЕНИЕ» в меню «Приложения» .
  2. Когда вас спросят: «Вы опубликовали свое приложение в Google Play или App Store?» , нажмите «НЕТ» .
  3. В поле «Название приложения» введите AdMob inline ads и выберите iOS в качестве платформы.

a4c963c9aa09519.png

  1. Включение пользовательских метрик не является обязательным для выполнения этого практического задания. Однако мы рекомендуем это сделать, поскольку это позволит вам более детально понять поведение пользователей. Нажмите ДОБАВИТЬ , чтобы завершить процесс.

b918bf44362813a9.png

Создавайте рекламные блоки

Чтобы добавить рекламные блоки:

  1. В консоли AdMob выберите приложение «Встроенная реклама AdMob» в меню « Приложения ».
  2. Нажмите на меню «Рекламные блоки» .

Баннер

  1. Нажмите «ДОБАВИТЬ РЕКЛАМНЫЙ БЛОК» .
  2. Выберите формат «Баннер» .
  3. В поле «Название рекламного блока» введите ios-inline-banner .
  4. Нажмите «СОЗДАТЬ РЕКЛАМНЫЙ БЛОК» , чтобы завершить процесс.

Родной

  1. Нажмите «ДОБАВИТЬ РЕКЛАМНЫЙ БЛОК» .
  2. Выберите формат «Native advanced» .
  3. В поле «Название рекламного блока» введите ios-inline-native .
  4. Нажмите «СОЗДАТЬ РЕКЛАМНЫЙ БЛОК» , чтобы завершить процесс.

Обычно для показа нового рекламного блока требуется несколько часов.

Если вы хотите немедленно проверить работу рекламы, используйте идентификаторы тестового приложения и рекламного блока, указанные в следующей таблице.

Дополнительно: воспользуйтесь тестовым приложением AdMob и рекламными блоками.

Если вы хотите следовать инструкциям из практического руководства, вместо того чтобы создавать новое приложение и рекламные блоки самостоятельно, вы можете использовать идентификаторы тестового приложения AdMob и идентификаторы рекламных блоков, указанные в следующих таблицах.

Идентификатор приложения Android/идентификатор рекламного блока

Элемент

Идентификатор приложения/идентификатор рекламного блока

Идентификатор приложения AdMob

ca-app-pub-3940256099942544~3347511713

Баннер

ca-app-pub-3940256099942544/6300978111

Родной

ca-app-pub-3940256099942544/2247696110

Идентификатор приложения iOS/идентификатор рекламного блока

Элемент

Идентификатор приложения/идентификатор рекламного блока

Идентификатор приложения AdMob

ca-app-pub-3940256099942544~1458002511

Баннер

ca-app-pub-3940256099942544/2934735716

Родной

ca-app-pub-3940256099942544/3986624511

Для получения дополнительной информации о тестовой рекламе см. документацию для разработчиков по тестовой рекламе для Android и тестовой рекламе для iOS .

4. Добавьте плагин Google Mobile Ads Flutter.

Flutter использует плагины для обеспечения доступа к широкому спектру сервисов, специфичных для каждой платформы. Плагины позволяют получать доступ к сервисам и API на каждой платформе.

Плагин google_mobile_ads поддерживает загрузку и отображение баннерной, межстраничной, рекламной и нативной рекламы с использованием API AdMob.

Поскольку Flutter — это многоплатформенный SDK, плагин google_mobile_ads применим как для iOS, так и для Android. Таким образом, если вы добавите плагин в свое приложение Flutter, он будет использоваться как версиями приложения AdMob для встроенной рекламы на Android, так и на iOS.

Добавьте плагин Google Mobile Ads в качестве зависимости.

Для доступа к API AdMob из проекта встроенной рекламы AdMob добавьте зависимость google_mobile_ads в файл pubspec.yaml , расположенный в корне проекта.

pubspec.yaml

...
dependencies:
  flutter:
    sdk: flutter
  google_fonts: ^0.3.9

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

...

Нажмите «Pub get» , чтобы установить плагин в проект встроенной рекламы AdMob .

93ef6061e58ebc86.png

Обновите файл AndroidManifest.xml (Android)

  1. Откройте файл android/app/src/main/AndroidManifest.xml в Android Studio.
  2. Добавьте идентификатор вашего приложения AdMob, добавив тег <meta-data> с именем com.google.android.gms.ads.APPLICATION_ID . Например, если идентификатор вашего приложения AdMob — ca-app-pub-3940256099942544~3347511713 , то вам необходимо добавить следующие строки в файл 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>

Обновить файл Info.plist (iOS)

  1. Откройте файл ios/Runner/Info.plist в Android Studio.
  2. Добавьте ключ GADApplicationIdentifier со строковым значением идентификатора вашего приложения AdMob. Например, если идентификатор вашего приложения AdMob — ca-app-pub-3940256099942544~1458002511 , то вам необходимо добавить следующие строки в файл Info.plist .

ios/Runner/Info.plist

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

5. Добавьте вспомогательный класс для рекламы.

Создайте новый файл с именем ad_helper.dart в каталоге lib . Затем реализуйте класс AdHelper , который предоставляет идентификатор приложения AdMob и идентификаторы рекламных блоков для Android и iOS.

Убедитесь, что вы заменили идентификатор приложения AdMob ( ca-app-pub-xxxxxx~yyyyy ) и идентификатор рекламного блока ( ca-app-pub-xxxxxxx/yyyyyyyy ) на идентификаторы, созданные вами на предыдущем шаге.

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 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 UnsupportedError("Unsupported platform");
    }
  }
}

Используйте следующий фрагмент кода, если хотите использовать идентификатор тестового приложения 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 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 UnsupportedError("Unsupported platform");
  }
}

6. Инициализируйте SDK Google Mobile Ads

Перед загрузкой рекламы необходимо инициализировать SDK Google Mobile Ads. Откройте файл lib/home_page.dart и измените функцию _initGoogleMobileAds() , чтобы инициализировать SDK до загрузки главной страницы.

Обратите внимание, что для получения результата инициализации SDK после её завершения необходимо изменить тип возвращаемого значения метода _initGoogleMobileAds() с Future<dynamic> на Future<InitializationStatus> .

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

7. Добавьте баннерную рекламу.

В этом разделе вы размещаете баннерную рекламу в середине списка, как показано на следующем скриншоте.

62c405c962909fd3.png

  1. Откройте файл lib/banner_inline_page.dart .
  2. Для импорта ad_helper.dart и 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. В класс _BannerInlinePageState добавьте следующие члены и методы для баннерной рекламы.

Обратите внимание, что _kAdIndex указывает индекс, по которому будет отображаться баннерная реклама, и используется для вычисления индекса элемента в методе _getDestinationItemIndex() .

banner_inline_page.dart

class _BannerInlinePageState extends State<BannerInlinePage> {

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

  // TODO: Add a banner ad instance
  BannerAd? _ad;

  ...

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

  ...
}
  1. В методе initState() создайте и загрузите BannerAd размером 320x50 пикселей ( AdSize.banner ). Обратите внимание, что обработчик событий рекламы настроен на обновление пользовательского интерфейса ( setState() ) при загрузке рекламы.

banner_inline_page.dart

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

  // TODO: Load a banner ad
  BannerAd(
    adUnitId: AdHelper.bannerAdUnitId,
    size: AdSize.banner,
    request: AdRequest(),
    listener: BannerAdListener(
      onAdLoaded: (ad) {
        setState(() {
          _ad = ad as BannerAd;
        });
      },
      onAdFailedToLoad: (ad, error) {
        // Releases an ad resource when it fails to load
        ad.dispose();
        print('Ad load failed (code=${error.code} message=${error.message})');
      },
    ),
  ).load();
}
  1. Измените метод build() таким образом, чтобы при наличии баннерной рекламы отображалась соответствующая реклама.
  2. Обновите itemCount, чтобы он подсчитывал количество показов баннерной рекламы, и обновите itemBuilder, чтобы он отображал баннерную рекламу по индексу объявления ( _kAdIndex ) при загрузке объявления.
  3. Обновите код, чтобы использовать метод _getDestinationItemIndex() для получения индекса элемента контента.

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 + (_ad != null ? 1 : 0),
      itemBuilder: (context, index) {
        // TODO: Render a banner ad
        if (_ad != null && index == _kAdIndex) {
          return Container(
            width: _ad!.size.width.toDouble(),
            height: 72.0,
            alignment: Alignment.center,
            child: AdWidget(ad: _ad!),
          );
        } else {
          // TODO: Get adjusted item index from _getDestinationItemIndex()
          final item = widget.entries[_getDestinationItemIndex(index)];

          return ListTile(
            ...
          );
        }
      },
    ),
  );
}
  1. Освободите ресурс, связанный с объектом BannerAd , вызвав метод BannerAd.dispose() в методе обратного вызова dispose() .

banner_inline_page.dart

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

  super.dispose();
}

Вот и всё! Запустите проект и нажмите кнопку «Встроенная баннерная реклама» на главной странице. После загрузки рекламы вы увидите баннерную рекламу в середине списка.

a5f857a850539fe9.pngc32af50872514224.png

8. Добавьте нативную рекламу

В этом разделе вы отображаете нативную рекламу в середине списка, как показано на следующем скриншоте.

f1671b0fa349ccf8.png

Нативная реклама отображается пользователям с использованием компонентов пользовательского интерфейса, которые являются собственными для платформы (например, View на Android или UIView на iOS).

Однако создавать нативные компоненты пользовательского интерфейса напрямую с помощью виджетов Flutter невозможно. Поэтому для каждой платформы необходимо реализовать NativeAdFactory , который используется для создания специфичного для платформы представления нативной рекламы ( NativeAdView на Android и GADNativeAdView на iOS) из объекта нативной рекламы ( NativeAd на Android и GADNativeAd на iOS).

Реализация NativeAdFactory для Android (Java)

  1. Откройте файл android/build.gradle (или любой другой файл в папке android ) и нажмите «Открыть для редактирования» в Android Studio , чтобы открыть проект Android.

623ad3d2282ccbf8.png

  1. Если вас попросят выбрать окно для открытия нового проекта, нажмите «Новое окно» , чтобы проект Flutter оставался открытым, пока вы работаете над проектом Android.

d188bb51cf7c2d08.png

Создайте макет нативной рекламы.

  1. Открыв проект Android, щелкните правой кнопкой мыши по приложению в панели проекта в Android Studio и выберите в контекстном меню «Новый» > «Файл ресурсов Android» .

2b629ee277a68fd7.png

  1. В диалоговом окне «Создать файл ресурсов» введите list_tile_native_ad.xml в качестве имени файла.
  2. Выберите тип ресурса «Макет» и введите com.google.android.gms.ads.nativead.NativeAdView в качестве корневого элемента.
  3. Нажмите кнопку ОК , чтобы создать новый файл макета.

575f126dd018bc0.png

  1. Разместите рекламное объявление следующим образом. Обратите внимание, что макет должен соответствовать визуальному оформлению пользовательского интерфейса платформы, для которой оно предназначено.

list_tile_native_ad.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
    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.nativead.NativeAdView>

Создайте класс ListTileNativeAdFactory.

  1. В панели «Проект» щелкните правой кнопкой мыши пакет com.codelab.flutter.admobinlineads и выберите «Создать» > «Класс Java» .

9f3f111dd207a9b4.png

  1. Введите ListTileNativeAdFactory в качестве имени и выберите Class из списка.

47ff82d92676e26.png

  1. После появления диалогового окна «Новый класс» оставьте все поля пустыми и нажмите «ОК» .

Вы увидите, что класс ListTileNativeAdFactory создан в пакете com.codelab.flutter.admobinlineads .

e4ed232c358ffb19.png

  1. Реализуйте класс ListTileNativeAdFactory следующим образом. Обратите внимание, что класс реализует метод createNativeAd() из интерфейса GoogleMobileAdsPlugin.NativeAdFactory .

Класс-фабрика отвечает за создание объекта представления для отображения нативной рекламы. Как видно из кода, класс-фабрика создает объект UnifiedNativeAdView и заполняет его объектом NativeAd .

ListTileNativeAdFactory.java

// TODO: Implement ListTileNativeAdFactory class

package com.codelab.flutter.admobinlineads;

import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;

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 NativeAdView createNativeAd(
            NativeAd nativeAd, Map<String, Object> customOptions) {
        NativeAdView nativeAdView = (NativeAdView) 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;
    }
}

Зарегистрируйте класс ListTileNativeAdFactory

Перед использованием компонента NativeAdFactory на стороне Flutter его необходимо зарегистрировать в плагине GoogleMobileAdsPlugin .

  1. Откройте файл MainActivity.java и переопределите методы configureFlutterEngine() и cleanUpFlutterEngine() .
  2. Зарегистрируйте класс ListTileNativeAdFactory с уникальным строковым идентификатором ( listTile ) в методе 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. В процессе очистки необходимо отменить регистрацию каждого экземпляра NativeAdFactory . Отмените регистрацию класса ListTileNativeAdFactory в методе 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");
    }
}

Теперь вы готовы использовать класс ListTileNativeAdFactory для отображения нативной рекламы на Android.

Реализация NativeAdFactory для Android (Kotlin)

  1. Откройте файл android/build.gradle (или любой другой файл в папке android ) и нажмите «Открыть для редактирования» в Android Studio , чтобы открыть проект Android.

623ad3d2282ccbf8.png

  1. Если вас попросят выбрать окно для открытия нового проекта, нажмите «Новое окно» , чтобы проект Flutter оставался открытым, пока вы работаете над проектом Android.

d188bb51cf7c2d08.png

Создайте макет нативной рекламы.

  1. Открыв проект Android, щелкните правой кнопкой мыши по приложению в панели проекта в Android Studio и выберите в контекстном меню «Новый» > «Файл ресурсов Android» .

2b629ee277a68fd7.png

  1. В диалоговом окне «Создать файл ресурсов» введите list_tile_native_ad.xml в качестве имени файла.
  2. Выберите тип ресурса «Макет» и введите com.google.android.gms.ads.nativead.NativeAdView в качестве корневого элемента.
  3. Нажмите кнопку ОК , чтобы создать новый файл макета.

575f126dd018bc0.png

  1. Разместите рекламное объявление следующим образом. Обратите внимание, что макет должен соответствовать визуальному оформлению пользовательского интерфейса платформы, для которой оно предназначено.

list_tile_native_ad.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
    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.nativead.NativeAdView>

Создайте класс ListTileNativeAdFactory.

  1. В панели «Проект» щелкните правой кнопкой мыши пакет com.codelab.flutter.admobinlineads и выберите «Создать» > «Файл/класс Kotlin» .

7311744cb97cad75.png

  1. Введите ListTileNativeAdFactory в качестве имени и выберите Class из списка.

25691151b5814867.png

  1. Вы увидите, что класс ListTileNativeAdFactory создан в пакете com.codelab.flutter.admobinlineads .
  2. Реализуйте класс ListTileNativeAdFactory следующим образом. Обратите внимание, что класс реализует метод createNativeAd() из интерфейса GoogleMobileAdsPlugin.NativeAdFactory .

Класс-фабрика отвечает за создание объекта представления для отображения нативной рекламы. Как видно из кода, класс-фабрика создает NativeAdView и заполняет его объектом NativeAd .

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.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin

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

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

        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
    }
}

Зарегистрируйте класс ListTileNativeAdFactory

Перед использованием компонента NativeAdFactory на стороне Flutter его необходимо зарегистрировать в плагине GoogleMobileAdsPlugin .

  1. Откройте файл MainActivity.kt и переопределите методы configureFlutterEngine() и cleanUpFlutterEngine() .
  2. Зарегистрируйте класс ListTileNativeAdFactory с уникальным строковым идентификатором ( listTile ) в методе 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. В процессе очистки необходимо отменить регистрацию каждого экземпляра NativeAdFactory . Отмените регистрацию класса ListTileNativeAdFactory в методе cleanUpFlutterEngine() .

MainActivity.kt

class MainActivity: FlutterActivity() {
    ...

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

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

Теперь вы готовы использовать класс ListTileNativeAdFactory для отображения нативной рекламы на Android.

Реализация NativeAdFactory для iOS (Objective-C)

Откройте файл ios/Podfile (или любой другой файл в папке ios ) и нажмите «Открыть модуль iOS в Xcode» , чтобы открыть проект iOS.

62aa12c10e6d671f.png

Подготовьте макет нативной рекламы.

Для размещения рекламных материалов вам потребуется собственный шаблон представления ( *.xib ). В этом практическом задании используется предварительно настроенный шаблон представления, чтобы свести ваши усилия к минимуму.

Откройте проект iOS в Xcode и убедитесь, что файл ListTileNativeAdView.xib существует в проекте Runner .

a5f04a32f1868d4f.png

Создайте класс ListTileNativeAdFactory.

  1. В навигаторе проекта щелкните правой кнопкой мыши группу Runner и выберите New File , чтобы создать заголовочный файл для нового класса.

6455aab9e9881ca.png

  1. В диалоговом окне шаблона выберите файл заголовка и назовите его ListTileNativeAdFactory .
  2. После создания файла ListTileNativeAdFactory.h определите класс ListNativeAdFactory следующим образом:

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. Создайте файл Objective-C, выбрав «Новый файл» в группе «Выполняющие команды» .
  2. В следующем диалоговом окне введите ListTileNativeAdFactory в поле «Файл» и выберите «Пустой файл» в качестве типа файла.

2c9c998c48db3a0.png

  1. После нажатия кнопки «Далее» вам будет предложено выбрать папку, в которой должен быть создан новый файл. Оставьте все параметры без изменений и нажмите «Создать» .

8635ffe502d1f4ab.png

  1. Реализуйте класс ListTileNativeFactory следующим образом. Обратите внимание, что класс реализует метод createNativeAd() из протокола FLTNativeAdFactory .

Класс-фабрика отвечает за создание объекта представления для отображения нативной рекламы. Как видно из кода, класс-фабрика создает объект GADNativeAdView и заполняет его объектом GADNativeAd .

ListTileNativeAdFactory.m

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

// TODO: Implement ListTileNativeAdFactory
@implementation ListTileNativeAdFactory

- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
                             customOptions:(NSDictionary *)customOptions {
  GADNativeAdView *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

Зарегистрируйте класс ListTileNativeAdFacortry

Для использования реализации FLTNativeAdFactory на стороне Flutter её необходимо зарегистрировать в FLTGoogleMobileAdsPlugin .

Откройте файл AppDelegate.m и зарегистрируйте ListTileNativeAdFactory с уникальным строковым идентификатором ( listTile ), вызвав метод [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

Теперь вы готовы использовать ListTileNativeAdFactory для отображения нативной рекламы на iOS.

Реализация NativeAdFactory для iOS (Swift)

Откройте файл ios/Podfile (или любой другой файл в папке ios ) и нажмите «Открыть модуль iOS в Xcode» , чтобы открыть проект iOS.

62aa12c10e6d671f.png

Подготовьте макет нативной рекламы.

Для размещения рекламных материалов вам потребуется собственный шаблон представления ( *.xib ). В этом практическом задании используется предварительно настроенный шаблон представления, чтобы свести ваши усилия к минимуму.

Откройте проект iOS в Xcode и убедитесь, что файл ListTileNativeAdView.xib существует в проекте Runner .

a5f04a32f1868d4f.png

Создайте класс ListTileNativeAdFactory.

  1. В навигаторе проекта щелкните правой кнопкой мыши группу Runner и выберите New File , чтобы создать заголовочный файл для нового класса.

9115c92543345ef1.png

  1. В диалоговом окне шаблона выберите файл Swift и назовите его ListTileNativeAdFactory .
  2. После создания файла ListTileNativeAdFactory.swift реализуйте класс ListNativeAdFactory .

Обратите внимание, что данный класс реализует метод createNativeAd() из протокола FLTNativeAdFactory .

Класс-фабрика отвечает за создание объекта представления для отображения нативной рекламы. Как видно из кода, класс-фабрика создает объект GADNativeAdView и заполняет его объектом GADNativeAd .

ListTileNativeAdFactory.swift

// TODO: Import google_mobile_ads
import google_mobile_ads

// TODO: Implement ListTileNativeAdFactory
class ListTileNativeAdFactory : FLTNativeAdFactory {

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

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

Зарегистрируйте класс ListTileNativeAdFacortry

Для использования реализации FLTNativeAdFactory на стороне Flutter её необходимо зарегистрировать в FLTGoogleMobileAdsPlugin .

Откройте файл AppDelegate.m и зарегистрируйте ListTileNativeAdFactory с уникальным строковым идентификатором ( listTile ), вызвав метод 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)
  }
}

Теперь вы готовы использовать ListTileNativeAdFactory для отображения нативной рекламы на iOS.

Интегрируйте нативную рекламу с виджетами Flutter.

  1. Откройте файл lib/native_inline_page.dart . Затем импортируйте ad_helper.dart и google_mobile_ads.dart , добавив следующие строки:

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. В класс _NativeInlinePageState добавьте следующие члены и методы для нативной рекламы.

Обратите внимание, что _kAdIndex указывает индекс, по которому будет отображаться баннерная реклама, и используется для вычисления индекса элемента в методе _getDestinationItemIndex() .

native_inline_page.dart

class _NativeInlinePageState extends State<NativeInlinePage> {

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

  // TODO: Add a native ad instance
  NativeAd? _ad;

  ...

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

  ...
}
  1. В методе initState() создайте и загрузите NativeAd , который использует ListTileNativeAdFactory для генерации представления нативной рекламы.

Обратите внимание, что используется тот же идентификатор фабрики ( listTile ), который применялся для регистрации фабрики в плагине.

native_inline_page.dart

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

  // TODO: Create a NativeAd instance
  _ad = NativeAd(
    adUnitId: AdHelper.nativeAdUnitId,
    factoryId: 'listTile',
    request: AdRequest(),
    listener: NativeAdListener(
      onAdLoaded: (ad) {
        setState(() {
          _ad = ad as NativeAd;
        });
      },
      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. Измените метод build() таким образом, чтобы при наличии баннерной рекламы отображалась соответствующая реклама.
  2. Обновите itemCount, чтобы он подсчитывал количество показов баннерной рекламы, и обновите itemBuilder, чтобы он отображал баннерную рекламу по индексу объявления ( _kAdIndex ) при загрузке объявления.
  3. Обновите код, чтобы использовать метод _getDestinationItemIndex() для получения индекса элемента контента.

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 + (_ad != null ? 1 : 0),
      itemBuilder: (context, index) {
        // TODO: Render a banner ad
        if (_ad != null && index == _kAdIndex) {
          return Container(
            height: 72.0,
            alignment: Alignment.center,
            child: AdWidget(ad: _ad!),
          );
        } else {
          // TODO: Get adjusted item index from _getDestinationItemIndex()
          final item = widget.entries[_getDestinationItemIndex(index)];

          return ListTile(
            ...
          );
        }
      },
    ),
  );
}
  1. Освободите ресурс, связанный с объектом NativeAd , вызвав метод NativeAd.dispose() в методе обратного вызова dispose() .

native_inline_page.dart

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

  super.dispose();
}

Вот и всё! Запустите проект и нажмите кнопку «Встроенная нативная реклама» на главной странице. После загрузки рекламы вы увидите нативную рекламу в середине списка.

f1671b0fa349ccf8.png5ead873222c800eb.png

9. Всё готово!

Вы завершили выполнение задания в CodeLab. Полный код для этого задания можно найти в... android_studio_folder.png полный или android_studio_folder.png папка complete_kotlin_swift .