الإعدادات الأصلية في نظامي التشغيل Android وiOS

يتم عرض الإعلانات المدمجة مع المحتوى للمستخدمين باستخدام مكوّنات واجهة المستخدم المضمّنة في المنصة، على سبيل المثال، View على نظام التشغيل Android أو UIView على iOS.

يوضِّح لك هذا الدليل كيفية تحميل الإعلانات المدمجة مع المحتوى وعرضها وتخصيصها باستخدام رمز خاص بوسيط عرض الإعلان.

المتطلبات الأساسية

الاختبار دائمًا من خلال الإعلانات الاختبارية

عند إنشاء تطبيقاتك واختبارها، تأكد من استخدام إعلانات اختبارية بدلاً من إعلانات مباشرة وإنتاجية. تتمثل أسهل طريقة لتحميل الإعلانات الاختبارية في استخدام رقم تعريف الوحدة الإعلانية الاختبارية المخصص للإعلانات المدمجة مع المحتوى:

  • /6499/example/native

تم إعداد الوحدات الإعلانية الاختبارية لعرض إعلانات اختبارية لكل طلب، لكي تتمكّن من استخدامها في تطبيقاتك أثناء الترميز والاختبار وتصحيح الأخطاء. ما عليك سوى التأكّد من استبدالها بأرقام تعريف وحدتك الإعلانية قبل نشر تطبيقك.

عمليات الإعداد الخاصة بالنظام الأساسي

لإنشاء إعلاناتك المدمجة مع المحتوى، ستحتاج إلى كتابة رمز خاص بنظام التشغيل iOS وAndroid، يليه تعديل تنفيذDart للاستفادة من التغييرات التي أجريتها على الرموز البرمجية المدمجة مع المحتوى.

Android

استيراد المكون الإضافي

يتطلب تنفيذ المكوّن الإضافي لإعلانات Google على الأجهزة الجوّالة لنظام التشغيل Android فئة تنفّذ واجهة برمجة التطبيقات NativeAdFactory. للإشارة إلى واجهة برمجة التطبيقات هذه من مشروع Android، أضف السطور التالية إلى settings.grale:

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
}

تنفيذ NativeAd أسعار

بعد ذلك، يجب إنشاء فئة تنفّذ NativeAdFactory وتلغي طريقة 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;
  }
}

للاطّلاع على مثال حول ضبط تنسيق NativeAdView، يمكنك الاطّلاع على my_native_ad.xml.

تسجيل NativeAd أسعار

يجب تسجيل كل عملية تنفيذ NativeAdFactory عند الاتصال على MainActivity.configureFlutterEngine(FlutterEngine) باستخدام factoryId، وهو معرِّف String فريد. سيتم استخدام factoryId في وقت لاحق عند إجراء إعلان مُدمج مع المحتوى من رمز Dart.

يمكن تنفيذ NativeAdFactory وتسجيله لكل تنسيق إعلان مدمج مع المحتوى فريد يستخدمه تطبيقك، أو يمكن لتخطيط واحد معالجة جميع التنسيقات.

تجدر الإشارة إلى أنّه عند الإنشاء باستخدام إضافة إلى التطبيق، يجب أيضًا أن يكون NativeAdFactory غير مسجَّل في cleanUpFlutterEngine(engine).

بعد إنشاء NativeAdFactoryExample، يمكنك إعداد MainActivity على النحو التالي:

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

تنفيذ NativeAd أسعار

يتطلب تنفيذ المكوّن الإضافي لإعلانات Google على الأجهزة الجوّالة لنظام التشغيل iOS صفًا تنفّذ واجهة برمجة التطبيقات FLTNativeAdFactory. أنشِئ صفًا ينفِّذ NativeAdFactory ونفِّذ طريقة 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

للاطّلاع على مثال حول ضبط تنسيق GADNativeAdView، يُرجى الاطّلاع على NativeAdView.xib.

تسجيل NativeAd أسعار

يجب تسجيل كل FLTNativeAdFactory باستخدام factoryId، وهو معرِّف String فريد، في registerNativeAdFactory:factoryId:nativeAdFactory:. سيتم استخدام factoryId لاحقًا عند إجراء إعلان مدمج مع المحتوى من رمز Dart.

يمكن تنفيذ FLTNativeAdFactory وتسجيله لكل تنسيق فريد من تنسيقات الإعلانات المدمجة مع المحتوى يستخدمه تطبيقك، أو يمكن لتخطيط واحد معالجة جميع التنسيقات.

بعد إنشاء FLTNativeAdFactory، يمكنك إعداد AppDelegate على النحو التالي:

#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

تحميل الإعلان

بعد إضافة الرمز الخاص بالنظام الأساسي، انتقِل إلى Dart لتحميل الإعلانات. تأكَّد من أنّ factoryID يطابق مستند التعريف الذي سجّلته سابقًا.

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

 // TODO: replace this test ad unit with your own ad unit.
 final _adUnitId = '/6499/example/native';

  /// 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 AdManagerAdRequest(),
        // Optional: Pass custom options to your native ad factory implementation.
        customOptions: {'custom-option-1', 'custom-value-1'}
    );
    _nativeAd.load();
  }
}

أحداث الإعلانات المدمجة مع المحتوى

لتلقّي إشعارات بالأحداث ذات الصلة بالتفاعلات مع الإعلانات المدمجة مع المحتوى، استخدِم السمة listener للإعلان. بعد ذلك، نفِّذ NativeAdListener لتلقّي استدعاءات الأحداث الإعلانية.

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

 // TODO: replace this test ad unit with your own ad unit.
 final _adUnitId = '/6499/example/native';

  /// 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 AdManagerAdRequest(),
        // Optional: Pass custom options to your native ad factory implementation.
        customOptions: {'custom-option-1', 'custom-value-1'}
    );
    _nativeAd.load();
        
  }
}

إعلان صوري

لعرض NativeAd كأداة، يجب إنشاء مثيل AdWidget الذي يحتوي على إعلان متوافق بعد طلب الرقم load(). يمكنك إنشاء التطبيق المصغّر قبل طلب البحث load()، إلا أنّه يجب استدعاء load() قبل إضافته إلى شجرة الأدوات.

يكتسِب AdWidget من فئة Widget في Flutter ويمكن استخدامها مثل أي تطبيق مصغّر آخر. على نظام التشغيل iOS، تأكد من وضع الأداة في حاوية ذات عرض وارتفاع محددين. وإلا فقد لا يتم عرض إعلانك.

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

التخلص من الإعلان

يجب التخلص من NativeAd عندما لا تكون هناك حاجة إليه. أفضل ممارسة لوقت طلب dispose() هي بعد إزالة AdWidget المرتبط بالإعلان المدمج مع المحتوى من شجرة الأدوات ومن معاودة الاتصال في AdListener.onAdFailedToLoad().