[M] deep link

This commit is contained in:
2025-01-15 18:53:22 +08:00
parent 0332758335
commit 90e54158f1
13 changed files with 1348 additions and 1 deletions

View File

@@ -0,0 +1,206 @@
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<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 AFDeepLinkHelper Instance {get; private set;}
public void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
}
public void Init()
{
AppsFlyer.setIsDebug(true);
AppsFlyer.setAppInviteOneLinkID("jT1Q");
AppsFlyer.initSDK("rSySeWtvKabfbPZE7Lmx7C", "6505145935", this);
AppsFlyer.OnDeepLinkReceived += OnDeepLink;
AppsFlyer.startSDK();
}
public async Task<string> GenInviteLink(string referrerUID, string referrerPID)
{
if(referrerUID == _referrerUID && !string.IsNullOrEmpty(_inviteLink))
return _inviteLink;
_inviteLink = string.Empty;
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;
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)
{
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
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 523a95a3b13874c0d9fa51543e9024ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
using System.Text;
using AppsFlyerSDK;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class AFInit
{
public Text text {get; set;}
[Btn("Clear")]
public void Clear()
{
text.text = "";
}
[Btn("Init AF")]
public void InitAF()
{
AFDeepLinkHelper.Instance.Init();
text.text = $"Init AF {AppsFlyer.CallBackObjectName}\n";
}
[Btn("Gen Url")]
public async void GenInviteUrl()
{
var url = await AFDeepLinkHelper.Instance.GenInviteLink("Mustapha", "123456");
if(url != null)
{
Debug.Log($"[AFInit::GenInviteUrl] {url}");
text.text = $"{url}\n";
}
else
{
text.text = $"Error\n";
}
}
[Btn("DeepLinkData")]
public void DeepLinkData()
{
if(AFDeepLinkHelper.Instance.DidReceivedDeepLink)
{
var sb = new StringBuilder();
sb.Append($"DeepLinkData \n");
foreach(var item in AFDeepLinkHelper.Instance.DeepLinkParamsDictionary)
{
sb.Append($"{item.Key} : {item.Value}\n");
sb.AppendLine();
}
var data = sb.ToString();
text.text = data;
Debug.Log($"[AFInit::DeepLinkData]\r\n{data}");
}
else
text.text = $"No DL\n";
}
[Btn("Referrer")]
public void Referer()
{
if(AFDeepLinkHelper.Instance.GetDLReferer(out string pid, out string uid))
{
text.text = $"Referrer pid:{pid} uid:{uid}\n";
}
else
{
text.text = $"No Referrer\n";
}
}
[Btn("SDK Test")]
public void SDKTest()
{
SceneManager.LoadScene("SampleScene");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 517033da1396840dc92b14ef319d1606
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
public class OneLinkTest : MonoBehaviour
{
[SerializeField] private GameObject btnContainer;
[SerializeField] private GameObject btn;
[SerializeField] private Text message;
void Start()
{
var aFInit = new AFInit();
aFInit.text = message;
// Get funcs methods witch has Btn attribute
var methods = aFInit.GetType().GetMethods();
foreach (var method in methods)
{
var btnAttr = method.GetCustomAttribute<BtnAttribute>();
if (btnAttr == null)
{
continue;
}
var btnObj = Instantiate(btn, btnContainer.transform);
btnObj.GetComponentInChildren<Text>().text = btnAttr.btnName;
btnObj.GetComponent<Button>().onClick.AddListener(() => method.Invoke(aFInit, null));
btnObj.SetActive(true);
}
}
}
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class BtnAttribute : Attribute
{
public string btnName;
public BtnAttribute(string btnName)
{
this.btnName = btnName;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6214202362ba44a71a557a55ce271445
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: