using System.Collections; using System.Collections.Generic; using UnityEngine; using AppsFlyerSDK; using System.Threading.Tasks; using System; public class AFDeepLinkHelper : MonoBehaviour, IAppsFlyerConversionData, IAppsFlyerUserInvite { public bool DidReceivedDeepLink {get; private set;} // marks if we got a DL and processed it private Dictionary _conversionDataDictionary; private Dictionary _deepLinkParamsDictionary; public bool IsFirstLaunch {get ; private set;} public string AFState {get ; private set;} public IReadOnlyDictionary DeepLinkParamsDictionary => _deepLinkParamsDictionary; public IReadOnlyDictionary ConversionDataDictionary => _conversionDataDictionary; public string AttributionData {get; private set;} private string _referrerUID; private string _inviteLink; private TaskCompletionSource _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 AFDeepLinkHelper Instance {get; private set;} public void Awake() { if (Instance != null && Instance != this) { Destroy(this); } else { Instance = 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 GenInviteLink(string referrerUID, string referrerPID) { if(referrerUID == _referrerUID && !string.IsNullOrEmpty(_inviteLink)) return _inviteLink; _inviteLink = string.Empty; Dictionary parameters = new Dictionary(); 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(); AppsFlyer.generateUserInviteLink(parameters, this); _inviteLink = await _tcs.Task; return _inviteLink; } #region Implement IAppsFlyerConversionData public void onConversionDataSuccess(string conversionData) { Debug.Log("[AFDeepLinkHelper::didReceiveConversionData] success" ); Dictionary 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) { 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 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; } #elif UNITY_ANDROID && !UNITY_EDITOR return deepLinkEventArgs.deepLink; #endif return null; } #endregion // Deeplink }