using System;
using System.Linq.Expressions;
using System.Reflection;
namespace JustTrack
{
///
/// Utility class for reflection-based integrations with third-party SDKs.
///
public class Reflection
{
///
/// Retrieves the AppsFlyer ID using reflection.
///
/// The AppsFlyer ID, or an empty string if retrieval fails.
internal static string GetAppsflyerId()
{
try
{
var assembly = GetAppsflyerAssembly();
if (assembly == null)
{
return string.Empty;
}
return assembly.GetAppsflyerId();
}
catch (System.Exception)
{
return string.Empty;
}
}
///
/// Checks if Facebook Audience Network Unity integration is available.
///
/// true if Facebook Audience Network Unity is available; otherwise, false.
public static bool HasFacebookAudienceNetworkUnity()
{
try
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var type = assembly.GetType("AudienceNetwork.AdSettings", false);
if (type != null)
{
var method = type.GetMethod("SetAdvertiserTrackingEnabled", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new Type[] { typeof(bool) }, null);
return method != null;
}
}
return false;
}
catch (System.Exception)
{
return false;
}
}
///
/// Sets advertiser tracking enabled status for Facebook Audience Network on iOS.
///
/// Whether advertiser tracking is authorized.
internal static void SetAdvertiserTrackingEnabled(bool authorized)
{
#if UNITY_IOS
// we only need to call this on iOS (the method also just exists on iOS), so we don't have to search for it on Android
try {
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies) {
var type = assembly.GetType("JustTrackInjected.FacebookAudienceNetworkAdapter", false);
if (type != null) {
var method = type.GetMethod("SetAdvertiserTrackingEnabled", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new Type[] { typeof(bool) }, null);
if (method != null) {
method.Invoke(null, new object[] { authorized });
}
return;
}
}
} catch (System.Exception) {
return;
}
#endif
}
///
/// Represents impression data from IronSource ad network.
///
internal class IronSourceImpressionData
{
///
/// Gets the ad unit identifier.
///
internal string AdUnit { get; }
///
/// Gets the placement identifier.
///
internal string Placement { get; }
///
/// Gets the ad network identifier.
///
internal string AdNetwork { get; }
///
/// Gets the A/B testing identifier.
///
internal string AbTesting { get; }
///
/// Gets the segment name.
///
internal string SegmentName { get; }
///
/// Gets the instance name.
///
internal string InstanceName { get; }
///
/// Gets the revenue amount.
///
internal double Revenue { get; }
///
/// Initializes a new instance of the class.
///
/// The ad unit identifier.
/// The placement identifier.
/// The ad network identifier.
/// The A/B testing identifier.
/// The segment name.
/// The instance name.
/// The revenue amount.
internal IronSourceImpressionData(string adUnit, string placement, string adNetwork, string abTesting, string segmentName, string instanceName, double revenue)
{
AdUnit = adUnit;
Placement = placement;
AdNetwork = adNetwork;
AbTesting = abTesting;
SegmentName = segmentName;
InstanceName = instanceName;
Revenue = revenue;
}
}
///
/// Wrapper class for interacting with IronSource SDK via reflection.
///
public class IronSourceAssembly
{
///
/// Gets the banner ad type identifier.
///
internal string BannerType { get; }
///
/// Gets the interstitial ad type identifier.
///
internal string InterstitialType { get; }
///
/// Gets the rewarded video ad type identifier.
///
internal string RewardedVideoType { get; }
///
/// Gets the offerwall ad type identifier.
///
internal string OfferwallType { get; }
private readonly PropertyInfo agentField;
private readonly MethodInfo init;
private readonly MethodInfo setUserId;
private readonly Type impressionDataType;
private readonly FieldInfo impressionDataAdUnit;
private readonly FieldInfo impressionDataPlacement;
private readonly FieldInfo impressionDataAdNetwork;
private readonly FieldInfo impressionDataAbTesting;
private readonly FieldInfo impressionDataSegmentName;
private readonly FieldInfo impressionDataInstanceName;
private readonly FieldInfo impressionDataRevenue;
private readonly EventInfo? onImpressionEvent;
private readonly IronSourceAdapter? ironSourceAdapter;
///
/// Initializes a new instance of the class.
///
/// The IronSource assembly to wrap.
internal IronSourceAssembly(Assembly assembly)
{
var adUnitsType = assembly.GetType("IronSourceAdUnits", true);
BannerType = (string)GetStaticField("BANNER", adUnitsType).GetValue(null);
InterstitialType = (string)GetStaticField("INTERSTITIAL", adUnitsType).GetValue(null);
RewardedVideoType = (string)GetStaticField("REWARDED_VIDEO", adUnitsType).GetValue(null);
OfferwallType = (string)GetStaticField("OFFERWALL", adUnitsType).GetValue(null);
var ironSourceType = assembly.GetType("IronSource", true);
this.agentField = GetStaticField("Agent", ironSourceType);
this.init = ironSourceType.GetMethod("init", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[] { typeof(string), typeof(string[]) }, null);
this.setUserId = ironSourceType.GetMethod("setUserId", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[] { typeof(string) }, null);
this.impressionDataType = assembly.GetType("IronSourceImpressionData", true);
this.impressionDataAdUnit = this.impressionDataType.GetField("adUnit");
this.impressionDataPlacement = this.impressionDataType.GetField("placement");
this.impressionDataAdNetwork = this.impressionDataType.GetField("adNetwork");
this.impressionDataAbTesting = this.impressionDataType.GetField("ab");
this.impressionDataSegmentName = this.impressionDataType.GetField("segmentName");
this.impressionDataInstanceName = this.impressionDataType.GetField("instanceName");
this.impressionDataRevenue = this.impressionDataType.GetField("revenue");
var eventsType = assembly.GetType("IronSourceEvents", true);
var onImpressionSuccessInfo = eventsType.GetMember("onImpressionSuccessEvent", BindingFlags.Public | BindingFlags.Static);
var onImpressionEvent = IronSourceAssembly.GetOnImpressionEvent(onImpressionSuccessInfo);
if (onImpressionEvent == null)
{
var onImpressionDataReadyInfo = eventsType.GetMember("onImpressionDataReadyEvent", BindingFlags.Public | BindingFlags.Static);
onImpressionEvent = IronSourceAssembly.GetOnImpressionEvent(onImpressionDataReadyInfo);
}
this.onImpressionEvent = onImpressionEvent;
this.ironSourceAdapter = GetIronSourceAdapter();
}
///
/// Gets the impression event from the provided member info array.
///
/// The member info array to search.
/// The impression event info, or null if not found.
private static EventInfo? GetOnImpressionEvent(System.Reflection.MemberInfo[] onImpressionEventInfo)
{
foreach (var onImpressionEvent in onImpressionEventInfo)
{
if (onImpressionEvent.MemberType != MemberTypes.Event)
{
continue;
}
return (EventInfo)onImpressionEvent;
}
return null;
}
///
/// Initializes the IronSource SDK with the specified app key and ad units.
///
/// The IronSource app key.
/// The ad units to initialize.
internal void Init(string appKey, string[] adUnits)
{
var agent = agentField.GetValue(null);
init.Invoke(agent, new object[] { appKey, adUnits });
}
///
/// Sets the user ID for the IronSource SDK.
///
/// The user ID to set.
internal void SetUserId(string userId)
{
var agent = agentField.GetValue(null);
setUserId.Invoke(agent, new object[] { userId });
}
///
/// Converts an IronSource impression object to our impression data format.
///
/// The IronSource impression object.
/// The converted impression data.
internal IronSourceImpressionData ToImpressionData(object impression)
{
var adUnit = (string)impressionDataAdUnit.GetValue(impression);
var placement = (string)impressionDataPlacement.GetValue(impression);
var adNetwork = (string)impressionDataAdNetwork.GetValue(impression);
var abTesting = (string)impressionDataAbTesting.GetValue(impression);
var segmentName = (string)impressionDataSegmentName.GetValue(impression);
var instanceName = (string)impressionDataInstanceName.GetValue(impression);
var revenue = (double?)impressionDataRevenue.GetValue(impression);
return new IronSourceImpressionData(adUnit, placement, adNetwork, abTesting, segmentName, instanceName, revenue ?? 0);
}
///
/// Adds an impression listener to the IronSource SDK.
///
/// The proxy action to handle impressions.
internal void AddImpressionListener(Action