Unity使用AppsFlyer动态生成DeepLink

提示:Unity接入AppsFlyer这里不进行介绍了(后面有时间我再单独写一个AppsFlyer的接入),可以查阅官方文档,写的很详细
Unity接入AppsFlyer官方文档


提示:这篇文字只介绍在Unity中如何使用AppsFlyer动态生成DeepLink


前言

为什么要使用AppsFlyer的DeepLink:

原因1:AppsFlyer是海外市场最大的归因平台,也可选择Adjust或Branch,这是海外最大的3个平台
原因2:DeepLink实际上就是一个网页,里面附带了许多参数,可以获取App安装来源的信息,这种功能实际上可以自己的后端实现,但是别人是实现好了的,直接用就行了。

一、AppsFlyer后台设置

1、进入AF后台,左侧菜单栏,点开互动,选择OneLink管理
2、选择对应的App
3、点击右侧3个点,点击添加OneLink模板
在这里插入图片描述

4、填写模板名称,选择App,填写子域名,这个域名可以随便取一个自己喜欢的。
5、跳转设置:若用户未安装应用,他会默认选择跳转到对应的市场,重点就设置一下用户已安装应用的情况,我们选择URI scheme备用方案,使用URI scheme调起应用,里面配置URI scheme,这个值需要和AndroidManifest里面的scheme对应,否则无法连接无法调起App
在这里插入图片描述
在这里插入图片描述

6、点击右下角创建模板即可。

二、生成动态DeepLink关键代码

1、需要继承IAppsFlyerUserInvite并实现里面的3个接口

public class AppsFlyerObjectScript : MonoBehaviour , IAppsFlyerConversionData , IAppsFlyerUserInvite



    public void onInviteLinkGenerated(string link)
    {
    
    
        AppsFlyer.AFLog("onInviteLinkGenerated", link);
        if(generateLinkHandle!=null)
        {
    
    
        	//生成DeepLink成功,这里需要写自己的逻辑,把Link返回给上层。
            //generateLinkHandle(link);
        }
    }

    public void onInviteLinkGeneratedFailure(string error)
    {
    
    
        AppsFlyer.AFLog("onInviteLinkGeneratedFailure", error);
    }

    public void onOpenStoreLinkGenerated(string link)
    {
    
    
        AppsFlyer.AFLog("onOpenStoreLinkGenerated", link);
    }

2、AF初始化时只需添加一句代码:AppsFlyer.setAppInviteOneLinkID(linkTemplate);

代码如下:

//linkTemplate是AF后台创建的模板ID。
AppsFlyer.setAppInviteOneLinkID(liknTemplate);

3、底层完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AppsFlyerSDK;
using System.Runtime.InteropServices;
using System;

// This class is intended to be used the the AppsFlyerObject.prefab

public class AppsFlyerObjectScript : MonoBehaviour, IAppsFlyerConversionData, IAppsFlyerUserInvite
{
    
    

    // These fields are set from the editor so do not modify!
    //******************************//
    public string devKey= "TWdfkBQ7ngU33bKkHDo4KW";//这个key需要换成自己AF的appKey
    public string iosdevKey= "";
    public string appID= "";
    public bool isDebug=false;
    public bool getConversionData=true;
    public static string deepLinkUrl = "";
    public static string afCallBackData = "";
    private string liknTemplate = "VEdu";//这个liknTemplate需要换成自己AF的模板ID
    private static Action<string> generateLinkHandle = null;
    public static string afAttributionData = "";
    //******************************//

#if UNITY_IPHONE
    [DllImport("__Internal")]
    private static extern string _getUrlFromAppsFlyer();
#endif
    void Start()
    {
    
    
        AppsFlyer.OnRequestResponse += AppsFlyerOnRequestResponse;
        AppsFlyer.OnInAppResponse += (sender, args) =>
        {
    
    
            var af_args = args as AppsFlyerRequestEventArgs;
            AppsFlyer.AFLog("OnInAppResponse", " status code " + af_args.statusCode);
        };
        // These fields are set from the editor so do not modify!
        //******************************//
        AppsFlyer.setIsDebug(isDebug);

#if UNITY_IOS && !UNITY_EDITOR
        AppsFlyer.initSDK(iosdevKey, appID,this);
#elif UNITY_ANDROID && !UNITY_EDITOR
        AppsFlyer.initSDK(devKey, appID,this);
#else

#endif
        //******************************//
        AppsFlyer.setAppInviteOneLinkID(liknTemplate);
        AppsFlyer.startSDK();

    }
    void AppsFlyerOnRequestResponse(object sender, EventArgs e)
    {
    
    
        var args = e as AppsFlyerRequestEventArgs;
        AppsFlyer.AFLog("AppsFlyerOnRequestResponse", " status code " + args.statusCode);
    }
    void Update()
    {
    
    

    }

    public static string GetAFDeepLinkUrl()
    {
    
    
#if UNITY_ANDROID
        if(!string.IsNullOrEmpty(deepLinkUrl))
        {
    
    
            string depurl=deepLinkUrl;
            deepLinkUrl="";
            return depurl;
        }
        else
        {
    
    
            return "";
        }
#elif UNITY_IPHONE
        string iosDeepUrl=_getUrlFromAppsFlyer();
        UnityEngine.Debug.Log("iosDeepUrl:-------:"+iosDeepUrl);
        return iosDeepUrl;
#endif
        return "";
    }
    // Mark AppsFlyer CallBacks
    public void onConversionDataSuccess(string conversionData)
    {
    
    
        afCallBackData = conversionData;
        AppsFlyer.AFLog("didReceiveConversionData", conversionData);
        Dictionary<string, object> conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData);
        // add deferred deeplink logic here
        bool afdp = conversionDataDictionary.ContainsKey("link");
        if (afdp == true)
        {
    
    
            object val = null;
            bool afdpvalue = conversionDataDictionary.TryGetValue("link", out val);
            if (afdpvalue == true)
            {
    
    
                deepLinkUrl = val as string;
            }
        }
        UnityEngine.Debug.Log("延迟深度链接:-------:" + deepLinkUrl);
    }

    public void onConversionDataFail(string error)
    {
    
    
        AppsFlyer.AFLog("didReceiveConversionDataWithError", error);
    }

    public void onAppOpenAttribution(string attributionData)
    {
    
    
        afAttributionData = attributionData;
        AppsFlyer.AFLog("onAppOpenAttribution", attributionData);
        Dictionary<string, object> attributionDataDictionary = AppsFlyer.CallbackStringToDictionary(attributionData);
        // add direct deeplink logic here
        bool afdp = attributionDataDictionary.ContainsKey("link");
        if (afdp == true)
        {
    
    
            object val = null;
            bool afdpvalue = attributionDataDictionary.TryGetValue("link", out val);
            if (afdpvalue == true)
            {
    
    
                deepLinkUrl = val as string;
            }
        }
        UnityEngine.Debug.Log("深度链接:-------:" + deepLinkUrl);
    }

    public void onAppOpenAttributionFailure(string error)
    {
    
    
        AppsFlyer.AFLog("onAppOpenAttributionFailure", error);
    }

    public static void TriggerLogEvent(string eventName, string[] keys, string[] values)
    {
    
    
        var afparameters = new Dictionary<string, string>();
        for (int i = 0; i < keys.Length; i++)
        {
    
    
            afparameters[keys[i]] = values[i];
        }
        AppsFlyer.sendEvent(
            eventName,
            afparameters
        );
    }

    public static string GetgetAppsFlyerId()
    {
    
    
        return AppsFlyer.getAppsFlyerId();
    }

    public static string GetAFCallBackData()
    {
    
    
        return afCallBackData;
    }

    public static string GetAFAttributionData()
    {
    
    
        return afAttributionData;
    }

	//生成DddpLink
    public void generateAppsFlyerLink(string[] keys, string[] values, Action<string> linkHandle)
    {
    
    
        generateLinkHandle = linkHandle;
        Dictionary<string, string> parameters = new Dictionary<string, string>();
        for (int i = 0; i < keys.Length; i++)
        {
    
    
            parameters[keys[i]] = values[i];
        }
        AppsFlyer.generateUserInviteLink(parameters, this);
    }

    public void onInviteLinkGenerated(string link)
    {
    
    
        AppsFlyer.AFLog("onInviteLinkGenerated", link);
        if(generateLinkHandle!=null)
        {
    
    
            generateLinkHandle(link);
        }
    }

    public void onInviteLinkGeneratedFailure(string error)
    {
    
    
        AppsFlyer.AFLog("onInviteLinkGeneratedFailure", error);
    }

    public void onOpenStoreLinkGenerated(string link)
    {
    
    
        AppsFlyer.AFLog("onOpenStoreLinkGenerated", link);
    }
}

4、业务层调用动态生成连接

//linkTemplate是AF后台创建的模板ID。
    public void generateShareGameLink()
    {
    
    
        GameObject go = GameObject.Find("SdkObj");
        AppsFlyerObjectScript Af = go.GetComponent<AppsFlyerObjectScript>();
        string param1 = "playerIdA";
        string param2 = "teamId";
        string param3 = "groupId";
        Dictionary<string, string> m = new();
        m.Add("af_channel", "custom_channel"); //自定义渠道名
        m.Add("af_dp", "mySchemeUrl://");//调起APP的scheme URL
        m.Add("c", "inviteGame");  //活动名称
        m.Add("deep_link_value", param1);//客户端APP内实现深度链接参数
        m.Add("deep_link_sub1", param2);//客户端APP内实现深度链接参数,deep_link_sub1到deep_link_sub10共10个参数可用
        m.Add("deep_link_sub2", param3);//客户端APP内实现深度链接参数,deep_link_sub1到deep_link_sub10共10个参数可用
        m.Add("is_retargeting", "false");//如果将此链接用于吸引现有及流失用户再次互动,请启用再营销,传True。这里默认传false
        m.Add("pid", "af_app_invites");//媒体渠道,默认,AF后台进行统计用
        m.Add("af_og_title", "Hello DeepLink");//供聊天软件抓取网页用的  社交媒体预览图谱 标题
        m.Add("af_og_description", "Welcome use DeepLink");//供聊天软件抓取网页用的  社交媒体预览图谱 描述
        m.Add("af_og_image", "https://www.baidu.com/123.png");//供聊天软件抓取网页用的  社交媒体预览图谱 展示图片
        Af.generateAppsFlyerLink(m, generateShareGameLinkHandle);
    }

    private void generateShareGameLinkHandle(string link)
    {
    
    
        //生成DeepLink的回调,这里需要自己实现逻辑
        //一般是调起分享
    }

5、应用场景举例

比如策划有这样一个需求:游戏里需要添加一个邀请好友的功能,玩家A点击了某个按钮,会跳转到第三方聊天软件,同时会生成一个连接,玩家可以将这个连接发送给自己的聊天平台的好友B,他的好友点击了连接下载或进入了游戏,那么玩家A获得了奖励,玩家B也获得了奖励。

那么玩家A点击邀请按钮生成DeepLink时,需要把自己在游戏里的ID带入,玩家B在进入游戏时可以获取到玩家A分享的DeepLink。客户端此时将DeepLink中携带的玩家A的游戏ID以及玩家B的游戏ID发送到服务器,即可发送奖励。

生成连接时deep_link_sub1到deep_link_sub10是可用的参数,他们会携带在Link里面,被邀请的玩家通过连接进入游戏,都可以轻松获取到这些参数,从而实现分享的玩家与被邀请玩家的关联。

连接的各种参数参加官方文档

AppsFlyer DeepLink的结构和参数