Dodawanie banera AdMob i natywnych reklam wbudowanych do aplikacji Flutter

1. Wprowadzenie

Z tego ćwiczenia dowiesz się, jak zaimplementować w aplikacji Flutter baner AdMob i natywną reklamę wbudowaną AdMob.

Co utworzysz

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak zaimplementować wbudowany baner AdMob i natywne reklamy wbudowane AdMob w aplikacji Flutter, korzystając z wtyczki Google do reklam mobilnych.

Jeśli podczas pracy z programem masz jakieś problemy (błędy w kodzie, błędy gramatyczne, niejasne sformułowania itp.), zgłoś je, korzystając z linku Zgłoś błąd w lewym dolnym rogu ćwiczenia.

Czego się nauczysz

  • Jak skonfigurować wtyczkę Google Mobile Ads Flutter
  • Jak wdrożyć baner wbudowany i reklamy z nagrodą w aplikacji Flutter

Czego potrzebujesz

  • Android Studio 4.1 lub nowszy
  • Xcode 12 lub nowsza wersja (na potrzeby programowania na iOS)

Jak oceniasz swój poziom znajomości AdMob?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz swój poziom znajomości Flutter?

Początkujący Poziom średnio zaawansowany Biegły
.

2. Konfigurowanie środowiska programistycznego Flutter

Aby ukończyć ten moduł, potrzebujesz 2 oprogramowania: pakietu SDK Flutter i edytora.

Ćwiczenie z programowania możesz uruchomić na dowolnym z tych urządzeń:

  • Fizyczne urządzenie z Androidem lub iOS podłączone do komputera i ustawione w trybie programisty.
  • Symulator iOS (wymaga zainstalowania narzędzi Xcode).
  • Emulator Androida (wymaga skonfigurowania Android Studio).
  • Przeglądarka (do debugowania wymagany jest Chrome).
  • Aplikacja komputerowa w systemie Windows, Linux lub macOS Programowanie należy tworzyć na platformie, na której zamierzasz wdrożyć usługę. Jeśli więc chcesz opracować aplikację komputerową dla systemu Windows, musisz to zrobić w tym systemie, aby uzyskać dostęp do odpowiedniego łańcucha kompilacji. Istnieją wymagania związane z konkretnymi systemami operacyjnymi, które zostały szczegółowo omówione na stronie docs.flutter.dev/desktop.

Pobieranie kodu

Po pobraniu pliku ZIP rozpakuj jego zawartość. Zostanie utworzony folder o nazwie admob-inline-ads-in-flutter-main.

Możesz też skopiować repozytorium GitHub za pomocą wiersza poleceń:

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

Repozytorium zawiera 3 foldery:

  • android_studio_folder.png starter: rozpoczęcie kodu, który utworzysz w ramach tego ćwiczenia z programowania.
  • android_studio_folder.png complete (ukończony): kod ukończony w ramach tego ćwiczenia z programowania. (Java i Objective-C dla kodu natywnego)
  • android_studio_folder.png complete_kotlin_swift: ukończony kod w ramach tego ćwiczenia w Codelabs. (Kotlin i Swift w przypadku kodu natywnego)

3. Skonfiguruj aplikację i jednostki reklamowe AdMob

Flutter to wieloplatformowy pakiet SDK, dlatego w AdMob musisz dodać aplikację i jednostki reklamowe na Androida i iOS.

Skonfiguruj na urządzeniu z Androidem

Aby skonfigurować aplikację na Androida, musisz dodać aplikację na Androida i utworzyć jednostki reklamowe.

Dodawanie aplikacji na Androida

  1. W konsoli AdMob w menu Aplikacje kliknij DODAJ APLIKACJĘ.
  2. Gdy pojawi się pytanie Czy Twoja aplikacja została opublikowana w Google Play lub App Store?, kliknij NIE.
  3. Wpisz AdMob inline ads w polu nazwy aplikacji i jako platformę wybierz Android.

d51828db0e2e4f6c.png

  1. Włączenie danych o użytkownikach nie jest konieczne do wykonania tego ćwiczenia z programowania. Zalecamy jednak, aby to zrobić, ponieważ pozwala to lepiej poznać zachowania użytkowników. Aby zakończyć proces, kliknij DODAJ.

b918bf44362813a9.png

Tworzenie jednostek reklamowych

Aby dodać jednostki reklamowe:

  1. W menu Aplikacje w konsoli AdMob wybierz aplikację Reklamy wbudowane AdMob.
  2. Kliknij menu Jednostki reklamowe.

Banner

  1. Kliknij DODAJ JEDNOSTKĘ REKLAMOWĄ.
  2. Jako format wybierz Baner.
  3. W polu Nazwa jednostki reklamowej wpisz android-inline-banner.
  4. Aby zakończyć proces, kliknij UTWÓRZ JEDNOSTKĘ REKLAMOWĄ.

Natywne

  1. Kliknij DODAJ JEDNOSTKĘ REKLAMOWĄ.
  2. Jako format wybierz Zaawansowana reklama natywna.
  3. W polu Nazwa jednostki reklamowej wpisz android-inline-native.
  4. Aby zakończyć proces, kliknij UTWÓRZ JEDNOSTKĘ REKLAMOWĄ.

Zazwyczaj zajmuje to kilka godzin, zanim nowa jednostka reklamowa zacznie wyświetlać reklamy.

Jeśli chcesz od razu przetestować działanie reklamy, użyj identyfikatora aplikacji testowej i identyfikatora jednostki reklamowej wymienionych w tabelach identyfikatorów aplikacji na Androida lub jednostki reklamowej, a także identyfikatorów aplikacji na iOS / jednostek reklamowych na iOS.

Skonfiguruj na urządzeniu z iOS

Aby skonfigurować kampanię pod kątem iOS, musisz dodać aplikację na iOS i utworzyć jednostki reklamowe.

Dodawanie aplikacji na iOS

  1. W konsoli AdMob w menu Aplikacje kliknij DODAJ APLIKACJĘ.
  2. Gdy pojawi się pytanie Czy Twoja aplikacja została opublikowana w Google Play lub App Store?, kliknij NIE.
  3. Wpisz AdMob inline ads w polu nazwy aplikacji i jako platformę wybierz iOS.

a4c963c9aa09519.png

  1. Włączenie danych o użytkownikach nie jest konieczne do wykonania tego ćwiczenia z programowania. Zalecamy jednak, aby to zrobić, ponieważ pozwala to lepiej poznać zachowania użytkowników. Aby zakończyć proces, kliknij DODAJ.

b918bf44362813a9.png

Tworzenie jednostek reklamowych

Aby dodać jednostki reklamowe:

  1. W menu Aplikacje w konsoli AdMob wybierz aplikację Reklamy wbudowane AdMob.
  2. Kliknij menu Jednostki reklamowe.

Banner

  1. Kliknij DODAJ JEDNOSTKĘ REKLAMOWĄ.
  2. Jako format wybierz Baner.
  3. W polu Nazwa jednostki reklamowej wpisz ios-inline-banner.
  4. Aby zakończyć proces, kliknij UTWÓRZ JEDNOSTKĘ REKLAMOWĄ.

Natywne

  1. Kliknij DODAJ JEDNOSTKĘ REKLAMOWĄ.
  2. Jako format wybierz Zaawansowana reklama natywna.
  3. W polu Nazwa jednostki reklamowej wpisz ios-inline-native.
  4. Aby zakończyć proces, kliknij UTWÓRZ JEDNOSTKĘ REKLAMOWĄ.

Zazwyczaj zajmuje to kilka godzin, zanim nowa jednostka reklamowa zacznie wyświetlać reklamy.

Jeśli chcesz od razu przetestować działanie reklamy, użyj identyfikatora aplikacji testowej i identyfikatorów jednostki reklamowej wymienionych w tabeli poniżej.

Opcjonalnie: używanie testowej aplikacji i jednostek reklamowych AdMob

Jeśli chcesz wykonać ćwiczenia w Codelabs, zamiast samodzielnie tworzyć nową aplikację i jednostki reklamowe, możesz użyć testowego identyfikatora aplikacji AdMob i identyfikatorów jednostek reklamowych wymienionych w tabelach poniżej.

Identyfikator aplikacji na Androida/identyfikator jednostki reklamowej

Element

identyfikator aplikacji/identyfikator jednostki reklamowej

Identyfikator aplikacji AdMob

ca-app-pub-3940256099942544~3347511713

Baner

ca-app-pub-3940256099942544/6300978111

Natywna

ca-app-pub-3940256099942544/2247696110

Identyfikator aplikacji na iOS lub identyfikator jednostki reklamowej

Element

identyfikator aplikacji/identyfikator jednostki reklamowej

Identyfikator aplikacji AdMob

ca-app-pub-3940256099942544~1458002511

Baner

ca-app-pub-3940256099942544/2934735716

Natywna

ca-app-pub-3940256099942544/3986624511

Więcej informacji o reklamach testowych znajdziesz w artykułach na temat reklam testowych na Androida i reklam testowych na iOS dla deweloperów.

4. Dodaj wtyczkę Google Mobile Ads Flutter

Flutter wykorzystuje wtyczki, aby zapewnić dostęp do szerokiej gamy usług dostępnych na poszczególnych platformach. Wtyczki umożliwiają dostęp do usług i interfejsów API na każdej platformie.

Wtyczka google_mobile_ads obsługuje wczytywanie i wyświetlanie banerów, reklam pełnoekranowych, reklam z nagrodą oraz reklam natywnych za pomocą interfejsu AdMob API.

Flutter to wieloplatformowy pakiet SDK, więc wtyczka google_mobile_ads działa zarówno w wersji na iOS, jak i na Androida. Jeśli dodasz tę wtyczkę do aplikacji Flutter, będzie ona używana przez wersję aplikacji do wyświetlania reklam wbudowanych w AdMob na Androida i iOS.

Dodaj wtyczkę do reklam mobilnych Google jako zależność

Aby uzyskać dostęp do interfejsów API AdMob z poziomu projektu reklamy wbudowane AdMob, dodaj google_mobile_ads jako zależność do pliku pubspec.yaml znajdującego się w katalogu głównym projektu.

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

...

Kliknij Pub get, aby zainstalować wtyczkę w projekcie Reklamy wbudowane AdMob.

93ef6061e58ebc86.png

Zaktualizuj plik AndroidManifest.xml (Android)

  1. Otwórz plik android/app/src/main/AndroidManifest.xml w Android Studio.
  2. Dodaj identyfikator aplikacji AdMob, dodając tag <meta-data> o nazwie com.google.android.gms.ads.APPLICATION_ID. Jeśli na przykład identyfikator aplikacji AdMob to ca-app-pub-3940256099942544~3347511713, do pliku AndroidManifest.xml musisz dodać te wiersze.

AndroidManifest.xml

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

</manifest>

Zaktualizuj plik Info.plist (iOS)

  1. Otwórz plik ios/Runner/Info.plist w Android Studio.
  2. Dodaj klucz GADApplicationIdentifier z wartością ciągu znaków identyfikatora aplikacji AdMob. Jeśli na przykład identyfikator aplikacji AdMob to ca-app-pub-3940256099942544~1458002511, do pliku Info.plist musisz dodać te wiersze.

ios/Runner/Info.plist

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

5. Dodaj klasę pomocniczą do reklam

Utwórz nowy plik o nazwie ad_helper.dart w katalogu lib. Następnie zaimplementuj klasę AdHelper, która zawiera identyfikator aplikacji AdMob i identyfikatory jednostek reklamowych dla Androida i iOS.

Pamiętaj, aby zastąpić identyfikatory aplikacji AdMob (ca-app-pub-xxxxxx~yyyyy) i identyfikatory jednostki reklamowej (ca-app-pub-xxxxxxx/yyyyyyyy) identyfikatorami utworzonymi w poprzednim kroku.

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

Jeśli chcesz użyć testowego identyfikatora aplikacji AdMob, a także identyfikatorów jednostek reklamowych, użyj tego fragmentu kodu.

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. Zainicjowanie pakietu SDK do reklam mobilnych Google

Zanim wczytasz reklamy, musisz zainicjować pakiet SDK do reklam mobilnych Google. Otwórz plik lib/home_page.dart i zmodyfikuj _initGoogleMobileAds(), aby zainicjować pakiet SDK przed wczytaniem strony głównej.

Pamiętaj, że aby uzyskać wynik inicjowania pakietu SDK po zakończeniu procesu, musisz zmienić typ zwracany metody _initGoogleMobileAds() z Future<dynamic> na 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. Dodawanie banera reklamowego

W tej sekcji na środku listy wyświetla się baner reklamowy, tak jak na zrzucie ekranu poniżej.

62c405c962909fd3.png

  1. Otwórz plik lib/banner_inline_page.dart.
  2. Importuj ad_helper.dart i google_mobile_ads.dart, dodając te wiersze:
...

// 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. W klasie _BannerInlinePageState dodaj wymienione niżej elementy i metody związane z banerem reklamowym.

Pamiętaj, że _kAdIndex wskazuje indeks, w którym będzie wyświetlany baner reklamowy. Służy do obliczania indeksu elementu za pomocą metody _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. W metodzie initState() utwórz i wczytaj element BannerAd dla banera 320 x 50 (AdSize.banner). Pamiętaj, że detektor zdarzeń reklamowych jest skonfigurowany tak, aby aktualizować interfejs (setState()) po wczytaniu reklamy.

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. Zmień metodę build(), aby wyświetlać baner reklamowy, gdy jest dostępny.
  2. Zaktualizuj pole itemCount,, by zliczać wpis banera reklamowego, oraz zaktualizuj itemBuilder,, by renderował baner reklamowy o indeksie reklamy (_kAdIndex) po wczytaniu reklamy.
  3. Zaktualizuj kod, by używać metody _getDestinationItemIndex() do pobierania indeksu dla elementu treści.

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. Zwolnij zasób powiązany z obiektem BannerAd, wywołując metodę BannerAd.dispose() w metodzie wywołania zwrotnego dispose().

banner_inline_page.dart

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

  super.dispose();
}

Znakomicie. Uruchom projekt i kliknij przycisk Baner reklamowy w tekście na stronie głównej. Po wczytaniu reklamy na środku listy pojawi się baner reklamowy.

a5f857a850539fe9.png c32af50872514224.png

8. Dodawanie reklamy natywnej

W tej sekcji wyświetlisz reklamę natywną na środku listy, tak jak na zrzucie ekranu poniżej.

f1671b0fa349ccf8.png

Reklamy natywne są wyświetlane użytkownikom za pomocą komponentów interfejsu, które są natywne dla danej platformy (np. View na Androidzie lub UIView na iOS).

Nie można jednak bezpośrednio tworzyć natywnych komponentów interfejsu za pomocą widżetów Flutter. Musisz więc zaimplementować dla każdej platformy obiekt NativeAdFactory, który posłuży do utworzenia wyświetlenia reklamy natywnej na poziomie platformy (NativeAdView na Androida i GADNativeAdView na iOS) z obiektu reklamy natywnej (NativeAd na Androida i GADNativeAd na iOS).

Wdróż NativeAdFactory na Androida (Java)

  1. Otwórz plik android/build.gradle (lub dowolny plik w folderze android) i kliknij Otwórz do edycji w Android Studio, aby otworzyć projekt na Androida.

623ad3d2282ccbf8.png

  1. Jeśli wyświetli się prośba o wybranie okna do otwarcia nowego projektu, kliknij Nowe okno, aby projekt Flutter pozostał otwarty podczas pracy nad projektem na Androida.

d188bb51cf7c2d08.png

Tworzenie układu reklamy natywnej

  1. Po otwarciu projektu na Androida kliknij prawym przyciskiem aplikację w panelu projektu w Android Studio i wybierz Nowy > Plik zasobów Androida w menu kontekstowym.

2b629ee277a68fd7.png

  1. W oknie Nowy plik zasobów wpisz list_tile_native_ad.xml jako nazwę pliku.
  2. Wybierz Układ jako typ zasobu i wpisz com.google.android.gms.ads.nativead.NativeAdView jako element główny.
  3. Kliknij OK, by utworzyć nowy plik układu.

575f126dd018bc0.png

  1. Wdróż układ reklamy w ten sposób. Pamiętaj, że układ powinien odpowiadać projektowi wizualnemu platformy, z której jest przeznaczony.

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>

Tworzenie klasy ListTileNativeAdFactory

  1. W panelu Projekt kliknij prawym przyciskiem myszy pakiet com.codelab.flutter.admobinlineads i wybierz Nowy > Klasa Java.

9f3f111dd207a9b4.png

  1. Wpisz ListTileNativeAdFactory jako nazwę i wybierz z listy Klasa.

47ff82d92676e26.png

  1. Po wyświetleniu okna Nowa klasa pozostaw wszystkie pola puste i kliknij OK.

Zobaczysz, że klasa ListTileNativeAdFactory została utworzona w pakiecie com.codelab.flutter.admobinlineads.

e4ed232c358ffb19.png

  1. Zaimplementuj klasę ListTileNativeAdFactory w ten sposób. Zwróć uwagę, że klasa implementuje metodę createNativeAd() w interfejsie GoogleMobileAdsPlugin.NativeAdFactory.

Klasa fabryki odpowiada za utworzenie obiektu widoku danych do renderowania reklamy natywnej. Jak widać z kodu, klasa fabryczna tworzy UnifiedNativeAdView i wypełnia ją obiektem 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;
    }
}

Rejestrowanie klasy ListTileNativeAdFactory

Aby można było używać instancji NativeAdFactory od strony Flutter, jej wystąpienie powinno zostać zarejestrowane w GoogleMobileAdsPlugin.

  1. Otwórz plik MainActivity.java i zastąp metody configureFlutterEngine() oraz cleanUpFlutterEngine().
  2. Zarejestruj klasę ListTileNativeAdFactory za pomocą unikalnego identyfikatora ciągu znaków (listTile) w metodzie 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. Podczas procesu czyszczenia należy wyrejestrować każde wystąpienie NativeAdFactory. Wyrejestruj klasę ListTileNativeAdFactory w metodzie 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");
    }
}

Teraz możesz użyć klasy ListTileNativeAdFactory do renderowania reklam natywnych na Androidzie.

Implementacja NativeAdFactory na Androida (Kotlin)

  1. Otwórz plik android/build.gradle (lub dowolny plik w folderze android) i kliknij Otwórz do edycji w Android Studio, aby otworzyć projekt na Androida.

623ad3d2282ccbf8.png

  1. Jeśli wyświetli się prośba o wybranie okna do otwarcia nowego projektu, kliknij Nowe okno, aby projekt Flutter pozostał otwarty podczas pracy nad projektem na Androida.

d188bb51cf7c2d08.png

Tworzenie układu reklamy natywnej

  1. Po otwarciu projektu na Androida kliknij prawym przyciskiem aplikację w panelu projektu w Android Studio i wybierz Nowy > Plik zasobów Androida w menu kontekstowym.

2b629ee277a68fd7.png

  1. W oknie Nowy plik zasobów wpisz list_tile_native_ad.xml jako nazwę pliku.
  2. Wybierz Układ jako typ zasobu i wpisz com.google.android.gms.ads.nativead.NativeAdView jako element główny.
  3. Kliknij OK, by utworzyć nowy plik układu.

575f126dd018bc0.png

  1. Wdróż układ reklamy w ten sposób. Pamiętaj, że układ powinien odpowiadać projektowi wizualnemu platformy, z której jest przeznaczony.

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>

Tworzenie klasy ListTileNativeAdFactory

  1. W panelu Projekt kliknij prawym przyciskiem myszy pakiet com.codelab.flutter.admobinlineads i wybierz Nowy > Plik/klasa Kotlin.

7311744cb97cad75.png

  1. Wpisz ListTileNativeAdFactory jako nazwę i wybierz z listy Klasa.

25691151b5814867.png

  1. Zobaczysz, że klasa ListTileNativeAdFactory została utworzona w pakiecie com.codelab.flutter.admobinlineads.
  2. Zaimplementuj klasę ListTileNativeAdFactory w ten sposób. Zwróć uwagę, że klasa implementuje metodę createNativeAd() w interfejsie GoogleMobileAdsPlugin.NativeAdFactory.

Klasa fabryki odpowiada za utworzenie obiektu widoku danych do renderowania reklamy natywnej. Jak widać z kodu, klasa fabryczna tworzy NativeAdView i wypełnia ją obiektem 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
    }
}

Rejestrowanie klasy ListTileNativeAdFactory

Aby można było używać instancji NativeAdFactory od strony Flutter, jej wystąpienie powinno zostać zarejestrowane w GoogleMobileAdsPlugin.

  1. Otwórz plik MainActivity.kt i zastąp metody configureFlutterEngine() oraz cleanUpFlutterEngine().
  2. Zarejestruj klasę ListTileNativeAdFactory za pomocą unikalnego identyfikatora ciągu znaków (listTile) w metodzie 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. Podczas procesu czyszczenia należy wyrejestrować każde wystąpienie NativeAdFactory. Wyrejestruj klasę ListTileNativeAdFactory w metodzie cleanUpFlutterEngine().

MainActivity.kt

class MainActivity: FlutterActivity() {
    ...

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

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

Teraz możesz użyć klasy ListTileNativeAdFactory do renderowania reklam natywnych na Androidzie.

Implementacja NativeAdFactory na iOS (Objective-C)

Otwórz plik ios/Podfile (lub dowolny plik w folderze ios) i kliknij Otwórz moduł iOS w Xcode, aby otworzyć projekt iOS.

62aa12c10e6d671f.png

Przygotowywanie układu reklamy natywnej

Do rozmieszczenia zasobów reklamy natywnej musisz mieć widok niestandardowy (*.xib). W tym ćwiczeniu w programowaniu do zminimalizowania nakładu pracy służy wstępnie skonfigurowany widok.

Po otwarciu projektu na iOS w Xcode sprawdź, czy w projekcie Runner istnieje plik ListTileNativeAdView.xib.

a5f04a32f1868d4f.png

Tworzenie klasy ListTileNativeAdFactory

  1. W nawigatorze projektów kliknij prawym przyciskiem myszy grupę Runner i wybierz New File (Nowy plik), aby utworzyć plik nagłówka dla nowych zajęć.

6455aab9e9881ca.png

  1. W oknie szablonu wybierz Plik nagłówka i nadaj mu nazwę ListTileNativeAdFactory.
  2. Po utworzeniu pliku ListTileNativeAdFactory.h zdefiniuj klasę ListNativeAdFactory w ten sposób:

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. Utwórz plik Objective-C, wybierając New File (Nowy plik) z grupy Runner (Runner).
  2. W następnym oknie wpisz ListTileNativeAdFactory w polu Plik i wybierz Pusty plik jako typ pliku.

2c9c998c48db3a0.png

  1. Po kliknięciu Dalej pojawi się prośba o wybranie folderu, w którym chcesz utworzyć nowy plik. Pozostaw wszystko bez zmian i kliknij Utwórz.

8635ffe502d1f4ab.png

  1. Zaimplementuj klasę ListTileNativeFactory w ten sposób. Pamiętaj, że klasa implementuje metodę createNativeAd() w protokole FLTNativeAdFactory.

Klasa fabryki odpowiada za utworzenie obiektu widoku danych do renderowania reklamy natywnej. Jak widać z kodu, klasa fabryczna tworzy GADNativeAdView i wypełnia ją obiektem 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

Rejestrowanie klasy ListTileNativeAdFacotry

Implementacja FLTNativeAdFactory powinna zostać zarejestrowana w FLTGoogleMobileAdsPlugin, zanim będzie można jej używać od strony Flutter.

Otwórz plik AppDelegate.m i zarejestruj ListTileNativeAdFactory za pomocą unikalnego identyfikatora ciągu znaków (listTile), wywołując metodę [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

Teraz możesz wykorzystać ListTileNativeAdFactory do renderowania reklam natywnych na iOS.

Implementacja NativeAdFactory na iOS (Swift)

Otwórz plik ios/Podfile (lub dowolny plik w folderze ios) i kliknij Otwórz moduł iOS w Xcode, aby otworzyć projekt iOS.

62aa12c10e6d671f.png

Przygotowywanie układu reklamy natywnej

Do rozmieszczenia zasobów reklamy natywnej musisz mieć widok niestandardowy (*.xib). W tym ćwiczeniu w programowaniu do zminimalizowania nakładu pracy służy wstępnie skonfigurowany widok.

Po otwarciu projektu na iOS w Xcode sprawdź, czy w projekcie Runner istnieje plik ListTileNativeAdView.xib.

a5f04a32f1868d4f.png

Tworzenie klasy ListTileNativeAdFactory

  1. W nawigatorze projektów kliknij prawym przyciskiem myszy grupę Runner i wybierz New File (Nowy plik), aby utworzyć plik nagłówka dla nowych zajęć.

9115c92543345ef1.png

  1. W oknie szablonu wybierz Swift File (Plik Swift) i nazwij go ListTileNativeAdFactory.
  2. Po utworzeniu pliku ListTileNativeAdFactory.swift wdróż klasę ListNativeAdFactory.

Pamiętaj, że klasa implementuje metodę createNativeAd() w protokole FLTNativeAdFactory.

Klasa fabryki odpowiada za utworzenie obiektu widoku danych do renderowania reklamy natywnej. Jak widać z kodu, klasa fabryczna tworzy GADNativeAdView i wypełnia ją obiektem 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
    }
}

Rejestrowanie klasy ListTileNativeAdFacotry

Implementacja FLTNativeAdFactory powinna zostać zarejestrowana w FLTGoogleMobileAdsPlugin, zanim będzie można jej używać od strony Flutter.

Otwórz plik AppDelegate.m i zarejestruj ListTileNativeAdFactory za pomocą unikalnego identyfikatora ciągu znaków (listTile), wywołując metodę 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)
  }
}

Teraz możesz wykorzystać ListTileNativeAdFactory do renderowania reklam natywnych na iOS.

Integracja reklamy natywnej z widżetami Flutter

  1. Otwórz plik lib/native_inline_page.dart. Następnie zaimportuj ad_helper.dart i google_mobile_ads.dart, dodając te wiersze:

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. W klasie _NativeInlinePageState dodaj elementy składowe i metody dotyczące reklamy natywnej.

Pamiętaj, że _kAdIndex wskazuje indeks, w którym będzie wyświetlany baner reklamowy. Służy do obliczania indeksu elementu za pomocą metody _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. W metodzie initState() utwórz i załaduj element NativeAd, który do wygenerowania wyświetlenia reklamy natywnej używa parametru ListTileNativeAdFactory.

Pamiętaj, że użyty zostanie ten sam identyfikator fabryczny (listTile), który został użyty do zarejestrowania urządzenia w wtyczce.

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. Zmień metodę build(), aby wyświetlać baner reklamowy, gdy jest dostępny.
  2. Zaktualizuj pole itemCount,, by zliczać wpis banera reklamowego, a itemBuilder,, by renderował baner reklamowy w indeksie reklamy (_kAdIndex), po wczytaniu reklamy.
  3. Zaktualizuj kod, by używać metody _getDestinationItemIndex() do pobierania indeksu dla elementu treści.

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. Zwolnij zasób powiązany z obiektem NativeAd, wywołując metodę NativeAd.dispose() w metodzie wywołania zwrotnego dispose().

native_inline_page.dart

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

  super.dispose();
}

Znakomicie. Uruchom projekt i kliknij przycisk Natywna reklama wbudowana na stronie głównej. Po wczytaniu reklamy na środku listy wyświetli się reklama natywna.

f1671b0fa349ccf8.png 5ead873222c800eb.png

9. Wszystko gotowe

Ćwiczenie z programowania zostało ukończone. Ukończony kod tego ćwiczenia znajdziesz w folderze android_studio_folder.pngcomplete lub android_studio_folder.png complete_kotlin_swift.