xamarin.forms - 如何在 Xamarin.Forms ios 中实现 UnifiedNative 广告
问题描述
我正在尝试在我的 xamarin.forms 应用程序中添加 UnifiedNative 广告。我在 Android 中成功实现了它们,但在 iOS 中遇到了困难。
对于 Android - 我创建了一个自定义渲染器和一个用于保存广告内容的 xml 布局。
对于 ios,我尝试遵循这个 - github.com/xamarin/GoogleApisForiOSComponents/blob/master/docs/Firebase/AdMob/ 但它不是很清楚并且仅在 Swift/Objective C 中提供帮助,我正在寻找 C#。
编辑 -
Xamarin.Forms
在 .xaml 中
<adview:AdmobNativeAd HeightRequest="360"></adview:AdmobNativeAd>
AdView 类 -
public class AdmobNativeAd : ContentView
{
public AdmobNativeAd()
{
this.HeightRequest = 360;
this.Margin = new Thickness(8, 8, 8, 0);
SetPlaceholderContent();
}
private void SetPlaceholderContent()
{
var placeholderGrid = new Grid();
var placeHolderText = new Label
{
Text = "AD",
FontSize = 48,
FontAttributes = FontAttributes.Bold,
TextColor = Color.White,
Opacity = 0.3,
VerticalOptions = new LayoutOptions(LayoutAlignment.Center, true),
HorizontalOptions = new LayoutOptions(LayoutAlignment.Center, true)
};
placeholderGrid.Children.Add(placeHolderText);
this.Content = placeholderGrid;
}
}
安卓实现——
[assembly: ExportRenderer(typeof(AdmobNativeAd), typeof(xxx.Droid.Services.NativeAd))]
namespace xxx.Droid.Services
{
public class NativeAd : ViewRenderer
{
public NativeAd(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var adLoader = new AdLoader.Builder(Context, "ca-app-pub-xxxxxxxxxxx/xxxxxxxx");
var listener = new UnifiedNativeAdLoadedListener();
listener.OnNativeAdLoaded += (s, ad) =>
{
try
{
var root = new UnifiedNativeAdView(Context);
var inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
var adView = (UnifiedNativeAdView)inflater.Inflate(Resource.Layout.ad_unified, root);
populateUnifiedNativeAdView(ad, adView);
SetNativeControl(adView);
}
catch
{
}
};
adLoader.ForUnifiedNativeAd(listener);
var requestBuilder = new AdRequest.Builder();
adLoader.Build().LoadAd(requestBuilder.Build());
}
}
private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView)
{
adView.MediaView = adView.FindViewById<MediaView>(Resource.Id.ad_media);
// Set other ad assets.
adView.HeadlineView = adView.FindViewById<TextView>(Resource.Id.ad_headline);
adView.BodyView = adView.FindViewById<TextView>(Resource.Id.ad_body);
adView.CallToActionView = adView.FindViewById<TextView>(Resource.Id.ad_call_to_action);
adView.IconView = adView.FindViewById<ImageView>(Resource.Id.ad_app_icon);
adView.PriceView = adView.FindViewById<TextView>(Resource.Id.ad_price);
adView.StarRatingView = adView.FindViewById<RatingBar>(Resource.Id.ad_stars);
adView.StoreView = adView.FindViewById<TextView>(Resource.Id.ad_store);
adView.AdvertiserView = adView.FindViewById<TextView>(Resource.Id.ad_advertiser);
// The headline and mediaContent are guaranteed to be in every UnifiedNativeAd.
((TextView)adView.HeadlineView).Text = nativeAd.Headline;
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
if (nativeAd.Body == null)
{
adView.BodyView.Visibility = ViewStates.Invisible;
}
else
{
adView.BodyView.Visibility = ViewStates.Visible;
((TextView)adView.BodyView).Text = nativeAd.Body;
}
if (nativeAd.CallToAction == null)
{
adView.CallToActionView.Visibility = ViewStates.Invisible;
}
else
{
adView.CallToActionView.Visibility = ViewStates.Visible;
((Android.Widget.Button)adView.CallToActionView).Text = nativeAd.CallToAction;
}
if (nativeAd.Icon == null)
{
adView.IconView.Visibility = ViewStates.Gone;
}
else
{
((ImageView)adView.IconView).SetImageDrawable(nativeAd.Icon.Drawable);
adView.IconView.Visibility = ViewStates.Visible;
}
if (string.IsNullOrEmpty(nativeAd.Price))
{
adView.PriceView.Visibility = ViewStates.Gone;
}
else
{
adView.PriceView.Visibility = ViewStates.Visible;
((TextView)adView.PriceView).Text = nativeAd.Price;
}
if (nativeAd.Store == null)
{
adView.StoreView.Visibility = ViewStates.Invisible;
}
else
{
adView.StoreView.Visibility = ViewStates.Visible;
((TextView)adView.StoreView).Text = nativeAd.Store;
}
if (nativeAd.StarRating == null)
{
adView.StarRatingView.Visibility = ViewStates.Invisible;
}
else
{
((RatingBar)adView.StarRatingView).Rating = nativeAd.StarRating.FloatValue();
adView.StarRatingView.Visibility = ViewStates.Visible;
}
if (nativeAd.Advertiser == null)
{
adView.AdvertiserView.Visibility = ViewStates.Invisible;
}
else
{
((TextView)adView.AdvertiserView).Text = nativeAd.Advertiser;
adView.AdvertiserView.Visibility = ViewStates.Visible;
}
// This method tells the Google Mobile Ads SDK that you have finished populating your
// native ad view with this native ad.
adView.SetNativeAd(nativeAd);
}
}
public class UnifiedNativeAdLoadedListener : AdListener, UnifiedNativeAd.IOnUnifiedNativeAdLoadedListener
{
public void OnUnifiedNativeAdLoaded(UnifiedNativeAd ad)
{
OnNativeAdLoaded?.Invoke(this, ad);
}
public EventHandler<UnifiedNativeAd> OnNativeAdLoaded { get; set; }
}
}
用于处理接收到的广告内容的 XML -
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.formats.UnifiedNativeAdView android:hardwareAccelerated="false"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardPreventCornerOverlap="false"
app:cardCornerRadius="12dp">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FFFFFF">
<AbsoluteLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<com.google.android.gms.ads.formats.MediaView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ad_media"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="Ad"
android:textColor="#FFFFFF"
android:background="#FFCC66"
android:textSize="14sp"
android:padding="4dp" />
</AbsoluteLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="fill_horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:paddingBottom="5dp"
android:paddingEnd="5dp"
android:paddingRight="5dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#0000FF"
android:text="Join the dark side!"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:textSize="14sp"
android:text="Google"
android:textColor="#222222"
android:textStyle="bold"/>
<RatingBar
android:id="@+id/ad_stars"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5"
android:rating="4" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:textColor="#555555"
android:id="@+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nis."
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:paddingLeft="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:id="@+id/ad_store"
android:text="Google Play"
android:textColor="#222222"
android:textSize="12sp" />
<Button
android:id="@+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="0dp"
android:text="INSTALL"
android:textSize="12sp" />
<TextView
android:id="@+id/ad_price"
android:text="$ 3.49"
android:textColor="#222222"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</com.google.android.gms.ads.formats.UnifiedNativeAdView>
我已经将这篇文章推荐给 Android 实现 -
https://startdebugging.net/2019/09/admob-native-ads-in-xamarin-forms-android/
我在IOS中试过这个,到目前为止我的代码是这样的——
[assembly: ExportRenderer(typeof(AdmobNativeAd), typeof(AdMobNativeAdRenderer))]
namespace xxxx.iOS.Renderers
{
public class AdMobNativeAdRenderer : ViewRenderer<AdmobNativeAd, NativeExpressAdView>
{
NativeExpressAdView mAdView;
bool viewOnScreen;
// public AdMobNativeAdRenderer(Context context) : base() { }
protected override void OnElementChanged(ElementChangedEventArgs<AdmobNativeAd> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (e.OldElement == null)
{
CreateAdView(this);
}
}
private void CreateAdView(AdMobNativeAdRenderer renderer)
{
if (Element == null) return;
var loader = new AdLoader(
"ca-app-pub-xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxx",
GetVisibleViewController(),
new AdLoaderAdType[] { AdLoaderAdType.UnifiedNative },
new AdLoaderOptions[] {
new NativeAdViewAdOptions {PreferredAdChoicesPosition = AdChoicesPosition.TopRightCorner}
});
var request = Request.GetDefaultRequest();
request.TestDevices = new string[] { Request.SimulatorId };
if (adView == null) return;
try
{
loader.Delegate = new MyAdLoaderDelegate(renderer);
loader.LoadRequest(request);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
Debug.WriteLine("Loading: " + loader.IsLoading);
}
private UIViewController GetVisibleViewController()
{
var windows = UIApplication.SharedApplication.Windows;
foreach (var window in windows)
{
if (window.RootViewController != null)
{
return window.RootViewController;
}
}
return null;
}
我不知道如何为 IOS 创建类似于上述 xml doc 的 UI 并将其与委托链接。
另外,我想提一下我正在为这个项目使用 Visual Studio 2019 Windows。
解决方案
推荐阅读
- python - django.db.utils.IntegrityError:NOT NULL 约束失败:new__users_personal_detail.husband_adhaarcopy
- c# - 如何检查对象类型变量是否为空?
- android - 将 Gradle 升级到 3.6.0 后找不到本机库
- css - 通过Angular中的插值将css应用于打字稿变量的某些部分
- php - 根据数据库中的单选按钮值显示 div
- python - groupby 表 Python Pandas 有问题吗?
- java - 通知安卓 (FCM)
- c# - 是否可以使用 ML.NET 为神经网络构建自定义深度学习层?
- java - 如何从 Java 上的字符串中修剪特定字符
- python - Numpy 索引解释