Files
2026-05-26 16:15:54 +08:00

223 lines
7.2 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AppsFlyerSDK;
using System.Threading.Tasks;
using System;
[DefaultExecutionOrder(-100)]
public class AFHelper : MonoBehaviour, IAppsFlyerConversionData, IAppsFlyerUserInvite
{
public bool DidReceivedDeepLink { get; private set; } // marks if we got a DL and processed it
private Dictionary<string, object> _conversionDataDictionary;
private Dictionary<string, object> _deepLinkParamsDictionary;
public bool IsFirstLaunch { get; private set; }
public string AFState { get; private set; }
public IReadOnlyDictionary<string, object> DeepLinkParamsDictionary => _deepLinkParamsDictionary;
public IReadOnlyDictionary<string, object> ConversionDataDictionary => _conversionDataDictionary;
public string AttributionData { get; private set; }
private string _referrerUID;
private string _inviteLink;
private TaskCompletionSource<string> _tcs;
public string StoreLink { get; private set; }
public bool GetDLReferer(out string pid, out string uid)
{
pid = null;
uid = null;
if (!DidReceivedDeepLink)
return false;
if (_deepLinkParamsDictionary == null)
return false;
if (_deepLinkParamsDictionary.TryGetValue("deep_link_value", out var deep_link_value))
{
if ((string)deep_link_value != "friend_invite")
return false;
if (_deepLinkParamsDictionary.TryGetValue("deep_link_sub2", out var referrer_pid))
pid = (string)referrer_pid;
if (_deepLinkParamsDictionary.TryGetValue("deep_link_sub1", out var referrer_uid))
uid = (string)referrer_uid;
if (!string.IsNullOrEmpty(pid) && !string.IsNullOrEmpty(uid))
return true;
}
return false;
}
public static AFHelper Instance { get; private set; }
public void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
DontDestroyOnLoad(this);
}
}
public void Init(string afkey, string afAppID, string customerUserID, string oneLinkID, bool debugMode = false)
{
AppsFlyer.setIsDebug(debugMode);
AppsFlyer.setAppInviteOneLinkID(oneLinkID);
AppsFlyer.initSDK(afkey, afAppID, this);
AppsFlyer.setCustomerUserId(customerUserID);
AppsFlyer.OnDeepLinkReceived += OnDeepLink;
#if UNITY_IOS
AppsFlyerSDK.AppsFlyer.waitForATTUserAuthorizationWithTimeoutInterval(30);
#endif
AppsFlyer.startSDK();
AppsFlyerSDK.AppsFlyerAdRevenue.start();
}
public async Task<string> GenInviteLink(string referrerUID, string referrerPID)
{
if (referrerUID == _referrerUID && !string.IsNullOrEmpty(_inviteLink))
return _inviteLink;
_inviteLink = string.Empty;
#if UNITY_EDITOR
await Awaiters.NextFrame;
#else
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("channel", "mobile_share");
parameters.Add("campaign", "friend_invite");
parameters.Add("deep_link_value", "friend_invite");
parameters.Add("deep_link_sub1", referrerUID);
parameters.Add("deep_link_sub2", referrerPID);
// Optional; makes the referrer ID available in the installs raw-data report
parameters.Add("af_sub1", referrerPID);
_tcs = new TaskCompletionSource<string>();
AppsFlyer.generateUserInviteLink(parameters, this);
_inviteLink = await _tcs.Task;
#endif
return _inviteLink;
}
#region Implement IAppsFlyerConversionData
public void onConversionDataSuccess(string conversionData)
{
Debug.Log("[AFDeepLinkHelper::didReceiveConversionData] success");
Dictionary<string, object> conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData);
_conversionDataDictionary = conversionDataDictionary;
// af_status and is_first_launch always received with onConversionDataSuccess, no need to check if the keys exist
AFState = _conversionDataDictionary["af_status"].ToString();
IsFirstLaunch = (bool)_conversionDataDictionary["is_first_launch"];
}
public void onConversionDataFail(string error)
{
Debug.LogWarning("[AFDeepLinkHelper::didReceiveConversionData] error: " + error);
_conversionDataDictionary = null;
}
public void onAppOpenAttribution(string attributionData)
{
Debug.Log("[AFDeepLinkHelper::onAppOpenAttribution] " + attributionData);
AttributionData = attributionData;
}
public void onAppOpenAttributionFailure(string error)
{
Debug.LogWarning("[AFDeepLinkHelper::onAppOpenAttributionFailure] error: " + error);
AttributionData = null;
}
#endregion // Implement IAppsFlyerConversionData
#region Implement IAppsFlyerUserInvite
public void onInviteLinkGenerated(string link)
{
if (_tcs != null)
{
_tcs.SetResult(link);
}
}
public void onInviteLinkGeneratedFailure(string error)
{
if (_tcs != null)
{
_tcs.SetResult(string.Empty);
}
}
public void onOpenStoreLinkGenerated(string link)
{
Debug.Log("[AFDeepLinkHelper::onOpenStoreLinkGenerated] " + link);
StoreLink = link;
}
#endregion // Implement IAppsFlyerUserInvite
#region Deeplink
/** All the DeepLink handling has to be done under the onDeepLink handler **/
void OnDeepLink(object sender, EventArgs args)
{
Debug.Log($"[AFDeepLinkHelper::onDeepLink] {args.GetType().Name}");
if (!(args is DeepLinkEventsArgs deepLinkEventArgs)) return;
Debug.Log($"[AFDeepLinkHelper::onDeepLink] DeepLink Status {deepLinkEventArgs.status.ToString()}");
switch (deepLinkEventArgs.status)
{
case DeepLinkStatus.FOUND:
DidReceivedDeepLink = true;
if (deepLinkEventArgs.isDeferred())
{
Debug.Log($"[AFDeepLinkHelper::onDeepLink] DeepLink is deferred");
}
else
{
Debug.Log($"[AFDeepLinkHelper::onDeepLink] This is a direct deep link");
}
_deepLinkParamsDictionary = GetDeepLinkParamsDictionary(deepLinkEventArgs);
break;
case DeepLinkStatus.NOT_FOUND:
Debug.Log($"[AFDeepLinkHelper::onDeepLink] DeepLink not found");
break;
default:
Debug.LogWarning($"[AFDeepLinkHelper::onDeepLink] DeepLink error");
break;
}
}
/** Get the DeepLink params depending on the device OS **/
private Dictionary<string, object> GetDeepLinkParamsDictionary(DeepLinkEventsArgs deepLinkEventArgs)
{
#if UNITY_IOS && !UNITY_EDITOR
if (deepLinkEventArgs.deepLink.ContainsKey("click_event") && deepLinkEventArgs.deepLink["click_event"] != null)
{
return deepLinkEventArgs.deepLink["click_event"] as Dictionary<string, object>;
}
#elif UNITY_ANDROID && !UNITY_EDITOR
return deepLinkEventArgs.deepLink;
#endif
return null;
}
#endregion // Deeplink
}