using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using GoogleMobileAds.Api; using UnityEngine; using Newtonsoft.Json.Linq; namespace WZ { abstract class IStack { public abstract string GetStackName(); protected abstract string[] GetBannerStack(); protected abstract string[] GetSpStack(); protected abstract string[] GetIvStack(); protected abstract string[] GetRvStack(); protected abstract string[] GetNaStack(); public string[] GetStackFromName(string stackName) { return stackName switch { "BannerStack" => GetBannerStack(), "SpStack" => GetSpStack(), "IvStack" => GetIvStack(), "RvStack" => GetRvStack(), "NaStack" => GetNaStack(), _ => Array.Empty() }; } } internal class Stack1 : IStack { private static readonly string[] BannerStack = { "zza", "zzj", "zzi", "zze", "zza", "zzk", "zzae" }; private static readonly string[] SpStack = { "zzb", "zza", "zzc", "zza", "zzk", "zzae" }; private static readonly string[] IvStack = { "zzc", "zzj", "zzf", "zzd", "zzae" }; private static readonly string[] RvStack = { "zzb", "zzi", "zze", "zze", "zzae" }; private static readonly string[] NaStack = { "zza", "zzb", "zzf", "zzD", "zzb", "zzae" }; public override string GetStackName() { return "Stack1"; } protected override string[] GetBannerStack() { return BannerStack; } protected override string[] GetSpStack() { return SpStack; } protected override string[] GetIvStack() { return IvStack; } protected override string[] GetRvStack() { return RvStack; } protected override string[] GetNaStack() { return NaStack; } } internal class Stack2 : IStack { private static readonly string[] BannerStack = { "zza", "zzj", "zza", "a", "a", "e", "a", "e", "ae" }; private static readonly string[] SpStack = { "zzb", "zza", "a", "a", "a", "e", "ae" }; private static readonly string[] IvStack = { "zzc", "zza", "a", "a", "d", "d", "ae" }; private static readonly string[] RvStack = { "zzb", "zza", "b", "g", "e", "ae" }; private static readonly string[] NaStack = { "zza", "zza", "b", "c", "c", "ae" }; public override string GetStackName() { return "Stack2"; } protected override string[] GetBannerStack() { return BannerStack; } protected override string[] GetSpStack() { return SpStack; } protected override string[] GetIvStack() { return IvStack; } protected override string[] GetRvStack() { return RvStack; } protected override string[] GetNaStack() { return NaStack; } } internal class EmptyStack : IStack { public override string GetStackName() { return "EmptyStack"; } protected override string[] GetBannerStack() { return Array.Empty(); } protected override string[] GetSpStack() { return Array.Empty(); } protected override string[] GetIvStack() { return Array.Empty(); } protected override string[] GetRvStack() { return Array.Empty(); } protected override string[] GetNaStack() { return Array.Empty(); } } public class AdmobUtils { private static IStack _stack; private static readonly List AvailableStrategies = new() { new Stack1(), new Stack2() // 新增策略只需在此处添加 }; public static double GetBannerEcpm(BannerView bannerView) { return GetEcpm(bannerView, "bannerView", "adView", "BannerStack"); } public static double GetRewardedAdEcpm(RewardedAd rewardedAd) { return GetEcpm(rewardedAd, "androidRewardedAd", "rewardedAd", "RvStack"); } public static double GetInterstitialAdEcpm(InterstitialAd interstitialAd) { return GetEcpm(interstitialAd, "androidInterstitialAd", "interstitialAd", "IvStack"); } public static double GetAppOpenAdEcpm(AppOpenAd appOpenAd) { return GetEcpm(appOpenAd, "androidAppOpenAd", "appOpenAd", "SpStack"); } public static double GetNativeEcpm(NativeOverlayAd ad) { return GetEcpm(ad, "nativeOverlayAd", "nativeAd", "NaStack"); } private static double GetEcpm(object o, string cShapeFieldName, string javaFieldName, string stack) { if (_stack is EmptyStack) { return -0.1; } try { if (_stack != null) { return GetEcpm(GetAdValue(GetJavaAdViewOjb(o, cShapeFieldName, javaFieldName), _stack.GetStackFromName(stack))); } } catch (Exception e) { LoggerUtils.Error("[AdmobTools] e : " + e.Message + "\t cShapeFieldName : " + cShapeFieldName); return -0.2; } foreach (var availableStrategy in AvailableStrategies) { try { var ecpm = GetEcpm(GetAdValue(GetJavaAdViewOjb(o, cShapeFieldName, javaFieldName), availableStrategy.GetStackFromName(stack))); _stack = availableStrategy; LoggerUtils.Debug("[AdmobTools] stack name : " + _stack.GetStackName()); return ecpm; } catch (Exception e) { LoggerUtils.Error("[AdmobTools] stack name " + availableStrategy.GetStackName() + "e : " + e.Message + "\t cShapeFieldName : " + cShapeFieldName); } } _stack = new EmptyStack(); return -1.0; } /// /// 获取java ad view 对象 /// /// unity admob 实例化对象 /// unity 引用 java 桥阶层的属性名 /// java桥阶层,持有ad对象的方法名 /// private static AndroidJavaObject GetJavaAdViewOjb(object o, string cShapeFieldName, string javaFieldName) { if (o == null) { throw new NullReferenceException("adView is null ; " + cShapeFieldName + "\t " + javaFieldName); } var type = o.GetType(); // 获取 BannerView 类型 var fieldInfo = type.GetField("_client", BindingFlags.NonPublic | BindingFlags.Instance); // 获取 _client 字段信息 if (fieldInfo == null) { throw new NullReferenceException("fieldInfo is null ; " + cShapeFieldName + "\t " + javaFieldName); } var client = fieldInfo.GetValue(o); // 获取 _client 字段的值 var clientType = client.GetType(); var bannerViewFieldInfo = clientType.GetField(cShapeFieldName, BindingFlags.NonPublic | BindingFlags.Instance); if (bannerViewFieldInfo == null) { throw new NullReferenceException("cShapeFieldName fieldInfo is null ; " + cShapeFieldName + "\t " + javaFieldName); } var bannerViewAndroidJavaObject = (AndroidJavaObject)bannerViewFieldInfo.GetValue(client); var javaAdViewOjb = bannerViewAndroidJavaObject.Get(javaFieldName); if (javaAdViewOjb == null) { throw new NullReferenceException("java obj is null ; " + cShapeFieldName + "\t " + javaFieldName); } return javaAdViewOjb; } /// /// 获取 admob 的 AdValue 对象 /// /// admob 广告对象 /// 内存位置 /// AdValue 的对象 private static AndroidJavaObject GetAdValue(AndroidJavaObject obj, string[] stack) { return stack.Aggregate(obj, (current, field) => { var androidJavaObject = current.Get(field); if (androidJavaObject == null) { throw new NullReferenceException("androidJavaObject is null ; " + current + "\t " + field); } return androidJavaObject; }); } /// /// 获取 ecpm /// /// admob AdValue对象 /// 广告收益 private static double GetEcpm(AndroidJavaObject obj) { return obj.Get("zzd") * 1.0 / 1000000; } } }