如何在 Xamarin.Android 中实现 RewardedAdLoadCallback?
Posted
技术标签:
【中文标题】如何在 Xamarin.Android 中实现 RewardedAdLoadCallback?【英文标题】:How can I implement RewardedAdLoadCallback in Xamarin.Android? 【发布时间】:2021-05-19 19:01:02 【问题描述】:我正在尝试用 C# 在 Xamarin.android 中实现奖励广告。
Android 文档中的代码 sn-ps 是用 Java 编写的,通常我在 C# 中采用该代码并没有太大问题,但现在看来确实是个问题。
要在 Java 中加载 RewardedAd,您必须执行以下操作 (according to the official documentation):
AdRequest adRequest = new AdRequest.Builder().build();
RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917",
adRequest, new RewardedAdLoadCallback()
@Override
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError)
// Handle the error.
Log.d(TAG, loadAdError.getMessage());
mRewardedAd = null
@Override
public void onAdLoaded(@NonNull RewardedAd rewardedAd)
mRewardedAd = rewardedAd;
Log.d(TAG, "onAdFailedToLoad");
);
现在这里的问题是,在这段代码中传递的对象RewardedAdLoadCallback
,还定义了方法实现(onAdFailedToLoad
和onAdLoaded
),而在 C# 中这是无法做到的。
所以我的解决方案是创建自己的类MyRewardedAdLoadCallback
,并覆盖方法。
public class MyRewardedAdLoadCallback : RewardedAdLoadCallback
public override void OnAdLoaded(Java.Lang.Object p0)
base.OnAdLoaded(p0);
public override void OnAdFailedToLoad(LoadAdError p0)
base.OnAdFailedToLoad(p0);
然后我只需使用以下代码加载奖励广告:
AdRequest adRequest = new AdRequest.Builder().Build();
RewardedAd.Load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, new MyRewardedAdLoadCallback());
现在由于一些奇怪的原因,我在构建项目时遇到了这个错误:
error: name ***: onAdLoaded(Object) in MyRewardedAdLoadCallback and onAdLoaded(AdT) in AdLoadCallback have the same erasure, yet neither overrides the other
public void onAdLoaded (java.lang.Object p0)
where AdT is a type-variable:
AdT extends Object declared in class AdLoadCallback
我尝试在互联网上搜索此错误并得出结论,这是一个 Java 错误并且与泛型类型有关(请参阅this SO 问题)。但是,我在我的代码和关于奖励广告的 Android 文档中都没有看到任何通用类型。关于我正在尝试实施的奖励广告的 Xamarin 文档也为零。
如果有人能帮我解决这个问题,我会非常高兴。提前致谢。
【问题讨论】:
您是否尝试覆盖OnRewardedAdLoaded
和 OnRewardedAdFailedToLoad
method ?
@LeoZhu-MSFT 覆盖这两种方法完全可以正常工作,但自 SDK 版本 19.7.0 起已弃用,因此我不想使用它们。
乍一看没有意义。 onAdLoaded( Object )
和 onAdLoaded( AdT )
不应该有相同的擦除。话虽如此,onAdLoaded( Object )
不应该能够覆盖onAdLoaded( Object )
,因为 擦除不一样。这可能是您的错误的根源。
@Koenigsberg 这确实是重点。另一个奇怪的事情是,在 Xamarin 中,我必须重写 OnAdLoaded(Java.Lang.Object)
,但在 Android 文档 (here) 中,只有一个名称为 onAdLoaded
的方法,它有一个类型为 @987654341 的参数@ (没有任何文档)。那么为什么我无法使用这个方法呢?
@Maximus 听起来很糟糕。在我在之前的评论中发送的 Github 链接中,有一条带有非官方解决方案的评论 (link)。不过自己没试过。
【参考方案1】:
这是让插页式广告和奖励广告在 Xamarin.GooglePlayServices.Ads 版本 120.0.0 中运行的技巧。
将以下文件添加到您的项目(需要使用 unsafe 标志构建)并使用 Android.Gms.Ads.Hack
命名空间来加载您的广告和子类化回调。
例如,InterstitialAd.Load
变为 global::Android.Gms.Ads.Hack.InterstitialAd.Load
,InterstitialAdLoadCallback
变为 global::Android.Gms.Ads.Hack.InterstitialAdLoadCallback
。
回调类分别将OnInterstitialAdLoaded()
和OnRewardedAdLoaded()
虚拟方法添加到插页式广告加载回调和奖励广告加载回调中。
using System;
using System.ComponentModel;
using System.Diagnostics;
using Android.Content;
using Android.Runtime;
using Java.Interop;
namespace Android.Gms.Ads.Hack
public abstract class InterstitialAd : Java.Lang.Object
private static readonly JniPeerMembers _members = new XAPeerMembers("com/google/android/gms/ads/interstitial/InterstitialAd", typeof(InterstitialAd));
public unsafe static void Load(Context context, string adUnit, AdRequest request, AdLoadCallback callback)
IntPtr intPtr = JNIEnv.NewString(adUnit);
try
JniArgumentValue* ptr = stackalloc JniArgumentValue[4];
*ptr = new JniArgumentValue(context?.Handle ?? IntPtr.Zero);
ptr[1] = new JniArgumentValue(intPtr);
ptr[2] = new JniArgumentValue(request?.Handle ?? IntPtr.Zero);
ptr[3] = new JniArgumentValue(callback?.Handle ?? IntPtr.Zero);
_members.StaticMethods.InvokeVoidMethod("load.(Landroid/content/Context;Ljava/lang/String;Lcom/google/android/gms/ads/AdRequest;Lcom/google/android/gms/ads/interstitial/InterstitialAdLoadCallback;)V", ptr);
finally
JNIEnv.DeleteLocalRef(intPtr);
GC.KeepAlive(context);
GC.KeepAlive(request);
GC.KeepAlive(callback);
[Register("com/google/android/gms/ads/interstitial/InterstitialAdLoadCallback", DoNotGenerateAcw = true)]
public abstract class InterstitialAdLoadCallback : AdLoadCallback
private static readonly JniPeerMembers _members = new XAPeerMembers("com/google/android/gms/ads/interstitial/InterstitialAdLoadCallback", typeof(InterstitialAdLoadCallback));
static IntPtr class_ref => _members.JniPeerType.PeerReference.Handle;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override JniPeerMembers JniPeerMembers => _members;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override Type ThresholdType => _members.ManagedPeerType;
protected InterstitialAdLoadCallback(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
[Register(".ctor", "()V", "")]
public unsafe InterstitialAdLoadCallback()
: base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
if (!(base.Handle != IntPtr.Zero))
SetHandle(_members.InstanceMethods.StartCreateInstance("()V", GetType(), null).Handle, JniHandleOwnership.TransferLocalRef);
_members.InstanceMethods.FinishCreateInstance("()V", this, null);
private static Delegate cb_onAdLoaded;
private static Delegate GetOnAdLoadedHandler()
if (cb_onAdLoaded is null)
cb_onAdLoaded = JNINativeWrapper.CreateDelegate((Action<IntPtr, IntPtr, IntPtr>)n_onAdLoaded);
return cb_onAdLoaded;
private static void n_onAdLoaded(IntPtr jnienv, IntPtr native__this, IntPtr native_p0)
InterstitialAdLoadCallback? @object = Java.Lang.Object.GetObject<InterstitialAdLoadCallback>(jnienv, native__this, JniHandleOwnership.DoNotTransfer);
global::Android.Gms.Ads.Interstitial.InterstitialAd object2 = Java.Lang.Object.GetObject<global::Android.Gms.Ads.Interstitial.InterstitialAd>(native_p0, JniHandleOwnership.DoNotTransfer);
@object!.OnInterstitialAdLoaded(object2);
[Register("onAdLoaded", "(Lcom/google/android/gms/ads/interstitial/InterstitialAd;)V", "GetOnAdLoadedHandler")]
public virtual void OnInterstitialAdLoaded(global::Android.Gms.Ads.Interstitial.InterstitialAd interstitialAd)
public abstract class RewardedAd : Java.Lang.Object
private static readonly JniPeerMembers _members = new XAPeerMembers("com/google/android/gms/ads/rewarded/RewardedAd", typeof(RewardedAd));
public unsafe static void Load(Context context, string adUnit, AdRequest request, RewardedAdLoadCallback callback)
IntPtr intPtr = JNIEnv.NewString(adUnit);
try
JniArgumentValue* ptr = stackalloc JniArgumentValue[4];
*ptr = new JniArgumentValue(context?.Handle ?? IntPtr.Zero);
ptr[1] = new JniArgumentValue(intPtr);
ptr[2] = new JniArgumentValue(request?.Handle ?? IntPtr.Zero);
ptr[3] = new JniArgumentValue(callback?.Handle ?? IntPtr.Zero);
_members.StaticMethods.InvokeVoidMethod("load.(Landroid/content/Context;Ljava/lang/String;Lcom/google/android/gms/ads/AdRequest;Lcom/google/android/gms/ads/rewarded/RewardedAdLoadCallback;)V", ptr);
finally
JNIEnv.DeleteLocalRef(intPtr);
GC.KeepAlive(context);
GC.KeepAlive(request);
GC.KeepAlive(callback);
[Register("com/google/android/gms/ads/rewarded/RewardedAdLoadCallback", DoNotGenerateAcw = true)]
public abstract class RewardedAdLoadCallback : AdLoadCallback
private static readonly JniPeerMembers _members = new XAPeerMembers("com/google/android/gms/ads/rewarded/RewardedAdLoadCallback", typeof(RewardedAdLoadCallback));
static IntPtr class_ref => _members.JniPeerType.PeerReference.Handle;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override JniPeerMembers JniPeerMembers => _members;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override IntPtr ThresholdClass => _members.JniPeerType.PeerReference.Handle;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override Type ThresholdType => _members.ManagedPeerType;
protected RewardedAdLoadCallback(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
[Register(".ctor", "()V", "")]
public unsafe RewardedAdLoadCallback()
: base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
if (!(base.Handle != IntPtr.Zero))
SetHandle(_members.InstanceMethods.StartCreateInstance("()V", GetType(), null).Handle, JniHandleOwnership.TransferLocalRef);
_members.InstanceMethods.FinishCreateInstance("()V", this, null);
private static Delegate cb_onAdLoaded;
private static Delegate GetOnAdLoadedHandler()
if (cb_onAdLoaded is null)
cb_onAdLoaded = JNINativeWrapper.CreateDelegate((Action<IntPtr, IntPtr, IntPtr>)n_onAdLoaded);
return cb_onAdLoaded;
private static void n_onAdLoaded(IntPtr jnienv, IntPtr native__this, IntPtr native_p0)
RewardedAdLoadCallback? @object = Java.Lang.Object.GetObject<RewardedAdLoadCallback>(jnienv, native__this, JniHandleOwnership.DoNotTransfer);
global::Android.Gms.Ads.Rewarded.RewardedAd object2 = Java.Lang.Object.GetObject<global::Android.Gms.Ads.Rewarded.RewardedAd>(native_p0, JniHandleOwnership.DoNotTransfer);
@object!.OnRewardedAdLoaded(object2);
[Register("onAdLoaded", "(Lcom/google/android/gms/ads/rewarded/RewardedAd;)V", "GetOnAdLoadedHandler")]
public virtual void OnRewardedAdLoaded(global::Android.Gms.Ads.Rewarded.RewardedAd rewardedAd)
【讨论】:
【参考方案2】:public abstract class InterstitialCallback : Android.Gms.Ads.Interstitial.InterstitialAdLoadCallback
[Register("onAdLoaded", "(Lcom/google/android/gms/ads/interstitial/InterstitialAd;)V", "GetOnAdLoadedHandler")]
public virtual void OnAdLoaded(Android.Gms.Ads.Interstitial.InterstitialAd interstitialAd)
private static Delegate cb_onAdLoaded;
private static Delegate GetOnAdLoadedHandler()
if (cb_onAdLoaded is null)
cb_onAdLoaded = JNINativeWrapper.CreateDelegate((Action<IntPtr, IntPtr, IntPtr>)n_onAdLoaded);
return cb_onAdLoaded;
private static void n_onAdLoaded(IntPtr jnienv, IntPtr native__this, IntPtr native_p0)
InterstitialCallback thisobject = GetObject<InterstitialCallback>(jnienv, native__this, JniHandleOwnership.DoNotTransfer);
Android.Gms.Ads.Interstitial.InterstitialAd resultobject = GetObject<Android.Gms.Ads.Interstitial.InterstitialAd>(native_p0, JniHandleOwnership.DoNotTransfer);
thisobject.OnAdLoaded(resultobject);
public abstract class RewardedAdLoadCallback : Android.Gms.Ads.Rewarded.RewardedAdLoadCallback
[Register("onAdLoaded", "(Lcom/google/android/gms/ads/rewarded/RewardedAd;)V", "GetOnAdLoadedHandler")]
public virtual void OnAdLoaded(Android.Gms.Ads.Rewarded.RewardedAd rewardedAd)
private static Delegate cb_onAdLoaded;
private static Delegate GetOnAdLoadedHandler()
if (cb_onAdLoaded is null)
cb_onAdLoaded = JNINativeWrapper.CreateDelegate((Action<IntPtr, IntPtr, IntPtr>)n_onAdLoaded);
return cb_onAdLoaded;
private static void n_onAdLoaded(IntPtr jnienv, IntPtr native__this, IntPtr native_p0)
RewardedAdLoadCallback thisobject = GetObject<RewardedAdLoadCallback>(jnienv, native__this, JniHandleOwnership.DoNotTransfer);
Android.Gms.Ads.Rewarded.RewardedAd resultobject = GetObject<Android.Gms.Ads.Rewarded.RewardedAd>(native_p0, JniHandleOwnership.DoNotTransfer);
thisobject.OnAdLoaded(resultobject);
【讨论】:
【参考方案3】:也许只是子类化回调
class RewardedVideoAds : RewardedAdLoadCallback
private RewardedAd rewardedAd;
public RewardedVideoAds()
AdRequest adRequest = new AdRequest.Builder().Build();
RewardedAd.Load(MainActivity.Current, "ca-app-pub-3940256099942544/5224354917", adRequest, this);
public override void OnAdFailedToLoad(LoadAdError p0)
base.OnAdFailedToLoad(p0);
public override void OnAdLoaded(Java.Lang.Object p0)
base.OnAdLoaded(p0);
【讨论】:
以上是关于如何在 Xamarin.Android 中实现 RewardedAdLoadCallback?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Xamarin Android 在 Edit Text 上实现 TextWatcher 接口?
OnTokenRefresh 从未在 Xamarin Android 中调用