تظهر "الإعلانات المدمجة مع المحتوى" للمستخدمين باستخدام مكوّنات واجهة مستخدم خاصة بالمنصة، مثل View على Android أو UIView على iOS.
يوضِّح لك هذا الدليل كيفية تحميل "الإعلانات المدمجة مع المحتوى" وعرضها وتخصيصها باستخدام رمز خاص بالمنصة.
المتطلبات الأساسية
قبل المتابعة، يُرجى اتّخاذ الإجراءات التالية:
الاختبار دائمًا باستخدام الإعلانات الاختبارية
عند إنشاء تطبيقاتك واختبارها، احرص على استخدام الإعلانات الاختبارية بدلاً من الإعلانات الفعلية المعروضة. أسهل طريقة لتحميل الإعلانات الاختبارية هي استخدام رقم تعريف الوحدة الإعلانية الاختبارية المخصّص للإعلانات المدمجة مع المحتوى:
/21775744923/example/native
تم ضبط الوحدات الإعلانية الاختبارية لعرض إعلانات اختبارية لكل طلب، لذا يمكنك استخدامها في تطبيقاتك أثناء كتابة الرموز البرمجية والاختبار وتحديد الأخطاء وحلّها. ما عليك سوى استبدالها بأرقام تعريف الوحدات الإعلانية الخاصة بك قبل نشر تطبيقك.
عمليات الإعداد الخاصة بالمنصة
لإنشاء "الإعلانات المدمجة مع المحتوى"، عليك كتابة رموز برمجية أصلية خاصة بمنصتَي iOS وAndroid، ثم تعديل عملية تنفيذ Dart للاستفادة من التغييرات التي أجريتها على الرموز البرمجية الأصلية.
Android
استيراد المكوّن الإضافي
يتطلّب تنفيذ مكوّن Google Mobile Ads الإضافي على Android فئة
تنفّذ
NativeAdFactory
واجهة برمجة التطبيقات. للإشارة إلى واجهة برمجة التطبيقات هذه من مشروع Android، أضِف الأسطر التالية إلى ملف 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
}
تنفيذ NativeAdFactory
بعد ذلك، أنشئ فئة تنفّذ 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 Google Mobile Ads Flutter Plugin that you have finished populating your
// native ad view with this native ad.
adView.setNativeAd(nativeAd);
return adView;
}
}
للاطّلاع على مثال عن ضبط تنسيق NativeAdView، يُرجى الاطّلاع على my_native_ad.xml.
تسجيل NativeAdFactory
يجب تسجيل كل عملية تنفيذ NativeAdFactory باستخدام factoryId، وهو معرّف String فريد، عند استدعاء MainActivity.configureFlutterEngine(FlutterEngine). سيتم استخدام 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
تنفيذ NativeAdFactory
يتطلّب تنفيذ مكوّن Google Mobile Ads الإضافي على 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.
تسجيل NativeAdFactory
يجب تسجيل كل 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 = '/21775744923/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 = '/21775744923/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().