Thiết lập mã gốc trong Android và iOS

Quảng cáo gốc hiển thị cho người dùng thông qua các thành phần giao diện người dùng vốn có của nền tảng, ví dụ: View trên Android hoặc UIView trên iOS.

Hướng dẫn này cho bạn biết cách tải, hiển thị và tuỳ chỉnh quảng cáo gốc bằng cách sử dụng mã dành riêng cho nền tảng.

Điều kiện tiên quyết

Luôn thử nghiệm bằng quảng cáo thử nghiệm

Khi tạo và thử nghiệm ứng dụng, hãy nhớ sử dụng quảng cáo thử nghiệm thay vì quảng cáo đang chạy trong thực tế. Cách dễ nhất để tải quảng cáo thử nghiệm là sử dụng mã đơn vị quảng cáo thử nghiệm dành riêng cho quảng cáo gốc:

Android

ca-app-pub-3940256099942544/2247696110

iOS

ca-app-pub-3940256099942544/3986624511

Các đơn vị quảng cáo thử nghiệm được định cấu hình để trả về quảng cáo thử nghiệm cho mọi yêu cầu. Vì vậy, bạn có thể sử dụng các đơn vị quảng cáo đó trong ứng dụng của riêng mình khi lập trình, thử nghiệm và gỡ lỗi. Bạn chỉ cần nhớ thay thế các đơn vị quảng cáo đó bằng mã đơn vị quảng cáo của riêng mình trước khi xuất bản ứng dụng.

Thiết lập theo nền tảng cụ thể

Để tạo quảng cáo gốc, bạn cần viết mã dành riêng cho nền tảng cho iOS và Android, sau đó sửa đổi cách triển khai Dart để tận dụng các thay đổi về mã gốc mà bạn đã thực hiện.

Android

Nhập trình bổ trợ

Việc triển khai trình bổ trợ Quảng cáo của Google trên thiết bị di động cho Android yêu cầu phải có một lớp triển khai API NativeAdFactory. Để tham chiếu API này từ dự án Android, hãy thêm các dòng sau vào settings.gradle:

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withInputStream { stream -> plugins.load(stream) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}

Triển khai NativeAdFactory

Tiếp theo, hãy tạo một lớp triển khai NativeAdFactory và ghi đè phương thức createNativeAd().

package io.flutter.plugins.googlemobileadsexample;

import android.graphics.Color;
import android.view.LayoutInflater;
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.NativeAdFactory;
import java.util.Map;

/**
 * my_native_ad.xml can be found at
 * github.com/googleads/googleads-mobile-flutter/blob/main/packages/google_mobile_ads/
 *     example/android/app/src/main/res/layout/my_native_ad.xml
 */
class NativeAdFactoryExample implements NativeAdFactory {
  private final LayoutInflater layoutInflater;

  NativeAdFactoryExample(LayoutInflater layoutInflater) {
    this.layoutInflater = layoutInflater;
  }

  @Override
  public NativeAdView createNativeAd(
      NativeAd nativeAd, Map<String, Object> customOptions) {
    final NativeAdView adView =
        (NativeAdView) layoutInflater.inflate(R.layout.my_native_ad, null);

    // Set the media view.
    adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));

    // Set other ad assets.
    adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
    adView.setBodyView(adView.findViewById(R.id.ad_body));
    adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
    adView.setIconView(adView.findViewById(R.id.ad_app_icon));
    adView.setPriceView(adView.findViewById(R.id.ad_price));
    adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
    adView.setStoreView(adView.findViewById(R.id.ad_store));
    adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));

    // The headline and mediaContent are guaranteed to be in every NativeAd.
    ((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
    adView.getMediaView().setMediaContent(nativeAd.getMediaContent());

    // These assets aren't guaranteed to be in every NativeAd, so it's important to
    // check before trying to display them.
    if (nativeAd.getBody() == null) {
      adView.getBodyView().setVisibility(View.INVISIBLE);
    } else {
      adView.getBodyView().setVisibility(View.VISIBLE);
      ((TextView) adView.getBodyView()).setText(nativeAd.getBody());
    }

    if (nativeAd.getCallToAction() == null) {
      adView.getCallToActionView().setVisibility(View.INVISIBLE);
    } else {
      adView.getCallToActionView().setVisibility(View.VISIBLE);
      ((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
    }

    if (nativeAd.getIcon() == null) {
      adView.getIconView().setVisibility(View.GONE);
    } else {
      ((ImageView) adView.getIconView()).setImageDrawable(nativeAd.getIcon().getDrawable());
      adView.getIconView().setVisibility(View.VISIBLE);
    }

    if (nativeAd.getPrice() == null) {
      adView.getPriceView().setVisibility(View.INVISIBLE);
    } else {
      adView.getPriceView().setVisibility(View.VISIBLE);
      ((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
    }

    if (nativeAd.getStore() == null) {
      adView.getStoreView().setVisibility(View.INVISIBLE);
    } else {
      adView.getStoreView().setVisibility(View.VISIBLE);
      ((TextView) adView.getStoreView()).setText(nativeAd.getStore());
    }

    if (nativeAd.getStarRating() == null) {
      adView.getStarRatingView().setVisibility(View.INVISIBLE);
    } else {
      ((RatingBar) adView.getStarRatingView()).setRating(nativeAd.getStarRating()
          .floatValue());
      adView.getStarRatingView().setVisibility(View.VISIBLE);
    }

    if (nativeAd.getAdvertiser() == null) {
      adView.getAdvertiserView().setVisibility(View.INVISIBLE);
    } else {
      adView.getAdvertiserView().setVisibility(View.VISIBLE);
      ((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
    }

    // This method tells the Google Mobile Ads SDK that you have finished populating your
    // native ad view with this native ad.
    adView.setNativeAd(nativeAd);

    return adView;
  }
}

Để biết ví dụ về cách định cấu hình bố cục NativeAdView, hãy xem my_native_ad.xml.

Đăng ký NativeAdFactory

Mỗi cách triển khai NativeAdFactory phải được đăng ký bằng một factoryId (một giá trị nhận dạng String duy nhất) khi gọi MainActivity.configureFlutterEngine(FlutterEngine). factoryId sẽ được sử dụng sau khi tạo bản sao quảng cáo gốc từ mã Dart.

Bạn có thể triển khai và đăng ký một NativeAdFactory cho mỗi bố cục quảng cáo gốc riêng mà ứng dụng của bạn sử dụng, hoặc một phương thức duy nhất có thể xử lý tất cả các bố cục.

Xin lưu ý rằng khi tạo bằng tính năng thêm vào ứng dụng, bạn cũng nên huỷ đăng ký NativeAdFactory trong cleanUpFlutterEngine(engine).

Sau khi tạo NativeAdFactoryExample, hãy thiết lập MainActivity như sau:

package my.app.path;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin;

public class MainActivity extends FlutterActivity {
  @Override
  public void configureFlutterEngine(FlutterEngine flutterEngine) {
    flutterEngine.getPlugins().add(new GoogleMobileAdsPlugin());
    super.configureFlutterEngine(flutterEngine);

    GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine,
        "adFactoryExample", NativeAdFactoryExample());
  }

  @Override
  public void cleanUpFlutterEngine(FlutterEngine flutterEngine) {
    GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample");
  }
}

iOS

Triển khai NativeAdFactory

Việc triển khai trình bổ trợ Quảng cáo trên thiết bị di động của Google dành cho iOS yêu cầu phải có một lớp triển khai API FLTNativeAdFactory. Tạo một lớp triển khai NativeAdFactory và triển khai phương thức createNativeAd().

#import "FLTGoogleMobileAdsPlugin.h"

/**
 * The example NativeAdView.xib can be found at
 * github.com/googleads/googleads-mobile-flutter/blob/main/packages/google_mobile_ads/
 *     example/ios/Runner/NativeAdView.xib
 */
@interface NativeAdFactoryExample : NSObject <FLTNativeAdFactory>
@end

@implementation NativeAdFactoryExample
- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
                      customOptions:(NSDictionary *)customOptions {
  // Create and place the ad in the view hierarchy.
  GADNativeAdView *adView =
      [[NSBundle mainBundle] loadNibNamed:@"NativeAdView" owner:nil options:nil].firstObject;

  // Populate the native ad view with the native ad assets.
  // The headline is guaranteed to be present in every native ad.
  ((UILabel *)adView.headlineView).text = nativeAd.headline;

  // These assets are not guaranteed to be present. Check that they are before
  // showing or hiding them.
  ((UILabel *)adView.bodyView).text = nativeAd.body;
  adView.bodyView.hidden = nativeAd.body ? NO : YES;

  [((UIButton *)adView.callToActionView) setTitle:nativeAd.callToAction
                                         forState:UIControlStateNormal];
  adView.callToActionView.hidden = nativeAd.callToAction ? NO : YES;

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

  ((UILabel *)adView.storeView).text = nativeAd.store;
  adView.storeView.hidden = nativeAd.store ? NO : YES;

  ((UILabel *)adView.priceView).text = nativeAd.price;
  adView.priceView.hidden = nativeAd.price ? NO : YES;

  ((UILabel *)adView.advertiserView).text = nativeAd.advertiser;
  adView.advertiserView.hidden = nativeAd.advertiser ? NO : YES;

  // In order for the SDK to process touch events properly, user interaction
  // should be disabled.
  adView.callToActionView.userInteractionEnabled = NO;

  // Associate the native ad view with the native ad object. This is
  // required to make the ad clickable.
  // Note: this should always be done after populating the ad views.
  adView.nativeAd = nativeAd;

  return adView;
}
@end

Để biết ví dụ về cách định cấu hình bố cục GADNativeAdView, hãy xem NativeAdView.xib.

Đăng ký NativeAdFactory

Mỗi FLTNativeAdFactory cần được đăng ký với một factoryId, một giá trị nhận dạng String riêng, trong registerNativeAdFactory:factoryId:nativeAdFactory:. Sau này, factoryId sẽ được sử dụng khi tạo thực thể một quảng cáo gốc từ mã Dart.

Bạn có thể triển khai và đăng ký một FLTNativeAdFactory cho mỗi bố cục quảng cáo gốc riêng mà ứng dụng của bạn sử dụng, hoặc một phương thức duy nhất có thể xử lý tất cả các bố cục.

Sau khi tạo FLTNativeAdFactory, hãy thiết lập AppDelegate như sau:

#import "FLTGoogleMobileAdsPlugin.h"
#import "NativeAdFactoryExample.h"

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

  // Must be added after GeneratedPluginRegistrant registerWithRegistry:self];
  // is called.
  NativeAdFactoryExample *nativeAdFactory = [[NativeAdFactoryExample alloc] init];
  [FLTGoogleMobileAdsPlugin registerNativeAdFactory:self
                                          factoryId:@"adFactoryExample"
                                    nativeAdFactory:nativeAdFactory];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

Tải quảng cáo

Sau khi thêm mã dành riêng cho nền tảng, hãy chuyển sang Dart để tải quảng cáo. Đảm bảo rằng factoryID khớp với mã nhận dạng mà bạn đã đăng ký trước đó.

class NativeExampleState extends State<NativeExample> {
  NativeAd? _nativeAd;
  bool _nativeAdIsLoaded = false;

 // TODO: replace this test ad unit with your own ad unit.
 final String _adUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/2247696110'
      : 'ca-app-pub-3940256099942544/3986624511';

  /// Loads a native ad.
  void loadAd() {
    _nativeAd = NativeAd(
        adUnitId: _adUnitId,
        // Factory ID registered by your native ad factory implementation.
        factoryId: 'adFactoryExample',
        listener: NativeAdListener(
          onAdLoaded: (ad) {
            print('$NativeAd loaded.');
            setState(() {
              _nativeAdIsLoaded = true;
            });
          },
          onAdFailedToLoad: (ad, error) {
            // Dispose the ad here to free resources.
            print('$NativeAd failedToLoad: $error');
            ad.dispose();
          },
        ),
        request: const AdRequest(),
        // Optional: Pass custom options to your native ad factory implementation.
        customOptions: {'custom-option-1', 'custom-value-1'}
    );
    _nativeAd.load();
  }
}

Sự kiện quảng cáo gốc

Để nhận thông báo về những sự kiện có liên quan đến các lượt tương tác với quảng cáo gốc, hãy sử dụng thuộc tính listener của quảng cáo. Sau đó, hãy triển khai NativeAdListener để nhận lệnh gọi lại sự kiện quảng cáo.

class NativeExampleState extends State<NativeExample> {
  NativeAd? _nativeAd;
  bool _nativeAdIsLoaded = false;

 // TODO: replace this test ad unit with your own ad unit.
 final String _adUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/2247696110'
      : 'ca-app-pub-3940256099942544/3986624511';

  /// Loads a native ad.
  void loadAd() {
    _nativeAd = NativeAd(
        adUnitId: _adUnitId,
        // Factory ID registered by your native ad factory implementation.
        factoryId: 'adFactoryExample',
        listener: NativeAdListener(
          onAdLoaded: (ad) {
            print('$NativeAd loaded.');
            setState(() {
              _nativeAdIsLoaded = true;
            });
          },
          onAdFailedToLoad: (ad, error) {
            // Dispose the ad here to free resources.
            print('$NativeAd failedToLoad: $error');
            ad.dispose();
          },
          // Called when a click is recorded for a NativeAd.
          onAdClicked: (ad) {},
          // Called when an impression occurs on the ad.
          onAdImpression: (ad) {},
          // Called when an ad removes an overlay that covers the screen.
          onAdClosed: (ad) {},
          // Called when an ad opens an overlay that covers the screen.
          onAdOpened: (ad) {},
          // For iOS only. Called before dismissing a full screen view
          onAdWillDismissScreen: (ad) {},
          // Called when an ad receives revenue value.
          onPaidEvent: (ad, valueMicros, precision, currencyCode) {},
        ),
        request: const AdRequest(),
        // Optional: Pass custom options to your native ad factory implementation.
        customOptions: {'custom-option-1', 'custom-value-1'}
    );
    _nativeAd.load();
        
  }
}

Quảng cáo hiển thị hình ảnh

Để hiển thị NativeAd dưới dạng một tiện ích, bạn phải tạo AdWidget với một quảng cáo được hỗ trợ sau khi gọi load(). Bạn có thể tạo tiện ích trước khi gọi load(), nhưng phải gọi load() trước khi thêm tiện ích đó vào cây tiện ích.

AdWidget kế thừa từ lớp Widget của Flutter và có thể được sử dụng như bất kỳ tiện ích nào khác. Trên iOS, hãy nhớ đặt tiện ích này trong một vùng chứa đã được chỉ định chiều rộng và chiều cao. Nếu không, quảng cáo của bạn có thể sẽ không hiển thị.

final Container adContainer = Container(
  alignment: Alignment.center,
  child: AdWidget adWidget = AdWidget(ad: _nativeAd!),
  width: WIDTH,
  height: HEIGHT,
);

Xoá quảng cáo

Bạn phải loại bỏ NativeAd khi không cần truy cập vào đối tượng đó nữa. Bạn nên gọi dispose() sau khi AdWidget liên kết với quảng cáo gốc bị xoá khỏi cây tiện ích và trong lệnh gọi lại AdListener.onAdFailedToLoad().

Các bước tiếp theo

Ví dụ hoàn chỉnh trên GitHub

Nền tảng gốc