Deep Link
Deep link 和 universal link 分别是在 Android 和 iOS 设备上打开您的应用中特定页面的方法。
为 Android 应用配置 deep link
Deep link 为一种重定向 URI,可用于将访问者转向应用中的内容,而 web link 则是使用 HTTP 或 HTTPS 协议的 deep link。要在 Android 创建 deep link,可通过在应用的 activity 中添加 intent-filter
来实现。由于玩家设备上的其他应用(例如系统浏览器)可能也有办法处理相同类型的 intent,玩家可选择使用其他应用来打开您的 deep link。
Android 6.0(API 级别 23)及更高版本支持使用 Android 应用链接(Android App Links),通过添加到 web link 中的 autoVerify
属性,将您的应用设置为某种链接类型的默认处理应用。Android 系统将自动校验您的应用是否符合 intent-filter
中所指定的 host 网域。然而,需注意玩家仍可通过手动修改系统设置来选择该链接类型的默认处理应用。
更多信息,请参见 处理 Android 应用链接。
步骤1:配置 Player Network SDK
Player Network SDK V1.12.00 及以上
在
AndroidManifest.xml
中添加 URI 相关的intent-filter
,并配置您的 URI 数据。自定义协议链接
配置 deep link:
scheme
- 自定义协议host
- 自定义 host 网域pathPrefix
(可选)- 自定义页面路径前缀,详见 多商店渠道包
Deep link
lipass://app/xxxxxx
代码示例:<activity
android:name=".ExampleActivity"
android:exported="true"
...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="lipass"
android:host="app" />
</intent-filter>
</activity>HTTP/HTTPS 协议链接
选择配置 web link(HTTP/HTTPS 协议的 deep link)或 Android App Link(用于设置默认处理程序,含自动校验的 web link):
scheme
- http 或 httpshost
- 自定义 host 网域pathPrefix
(可选)- 自定义页面路径前缀,详见 多商店渠道包
Web link
https://www.levelinfinite.com/app/xxxxxx
代码示例:<activity
android:name=".ExampleActivity"
android:exported="true"
...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
<data android:scheme="https"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
</intent-filter>
</activity>Android App Link
https://www.levelinfinite.com/app/xxxxxx
代码示例(Android 6.0 及更高版本支持):<activity
android:name=".ExampleActivity"
android:exported="true"
...>
<intent-filter android:autoVerify="true"><!-- 开启自动校验 -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
<data android:scheme="https"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
</intent-filter>
</activity>代码示例:
<activity
android:name=".ExampleActivity"
android:exported="true"
...>
<intent-filter>
<!-- 该 intent-filter 支持 deep link `lipass://app/xxxxxx` -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="lipass"
android:host="app" />
</intent-filter>
<intent-filter android:autoVerify="true">
<!-- 该 intent-filter 支持 Android App Link `https://www.levelinfinite.com/app/xxxxxx` -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
<data android:scheme="https"
android:host="www.levelinfinite.com"
android:pathPrefix="/app" />
</intent-filter>
</activity>处理 intent 数据。
- Unity
- Unreal Engine
在
MainActivity
的onCreate
和onNewIntent
中调用getData()
和getAction()
方法,检索与传入Intent
相关联的数据和操作。@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
if (data != null) {
INTLSDK.Deeplink.receive(data.toString());
}
}
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
INTLSDK.onNewIntent(intent);
Uri appLinkData = intent.getData();
if (appLinkData != null) {
INTLSDK.Deeplink.receive(appLinkData.toString());
}
}在游戏的 XML 文件中对应的
onCreate
和onNewIntent
里调用getData()
和getAction()
方法,检索与传入Intent
相关联的数据和操作。<!--GameActivity.java onCreate code -->
<gameActivityOnCreateAdditions>
<insert>
setFullScreen();
RequestDynamicPermissions();
INTLSDK.initialize(this);
Intent appLinkIntent = getIntent();
String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData();
android.util.Log.i("deeplink", "appLinkAction = " + appLinkAction + ", appLinkData = " + appLinkData);
if (appLinkData != null) {
INTLSDK.Deeplink.receive(appLinkData.toString());
}
</insert>
</gameActivityOnCreateAdditions>
<!--GameActivity.java OnNewIntent code-->
<gameActivityOnNewIntentAdditions>
<insert>
INTLSDK.onNewIntent(newIntent);
Uri appLinkData = newIntent.getData();
if (appLinkData != null) {
INTLSDK.Deeplink.receive(appLinkData.toString());
}
</insert>
</gameActivityOnNewIntentAdditions>
步骤2:配置官网
此步骤仅适用于已配置 Android App Link 场景,如果您的应用未使用 Android App Link 则为可选配置。
通过 Google Search Console 验证您对应用和网域的所有权,在以下位置部署 Digital Asset Links JSON 文件:
https://domain.name/.well-known/assetlinks.json
Digital Asset Links JSON 文件使用下列字段标识关联的应用:
package_name: 在应用的
build.gradle
文件中声明的应用 ID。sha256_cert_fingerprints: 应用的签名证书的 SHA256 指纹。此字段支持多个指纹,这些指纹可用于支持不同版本的应用,例如调试版 build 和正式版 build。
您可以利用 Java 密钥工具,通过以下命令生成该指纹:
$ keytool -list -v -keystore my-release-key.keystore
以下 assetlinks.json
示例文件可为 android_app
授予打开 com.example
链接的权限:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
}
}]
[可选] 多商店渠道包
对于不同包名的渠道包,可使用 android:pathPrefix
属性进行区分,例如 渠道 A 添加了 android:pathPrefix="/sample"
则如果同时安装了渠道A和渠道B包,使用 http://sdk-deeplink-confs.intlgame.com/sample
链接会拉起渠道A。
多商店渠道包 JSON 文件配置示例:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.puppies.app",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.monkeys.app",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8: 8A:04:96:B2:3F:CF:44:E5"]
}
}]
步骤3:测试 deep link
因为微信内置浏览器的限制,在微信中打开链接时不会跳转应用。
安装应用后,在 Android 文本编辑器打开测试链接:
在 Android 文本应用 (例如便签) 中点击链接跳转应用后,在日志中包含
[ (intl_deeplink_manager.cpp:37) Receive]
字样。使用 adb 测试 intent-filter URL 的一般语法为:
$ adb shell am start
-W -a android.intent.action.VIEW
-d "URL" PACKAGE例如,以下命令试图查看与
lipass://app/xxxxxx
相关的目标应用 activity。$ adb shell am start
-W -a android.intent.action.VIEW
-d "lipass://app/xxxxxx" com.example.android_app
调用网页 URI 时,Android 系统会依序尝试执行下列操作,直到请求成功为止:
- 如果已指定该链接类型的默认处理应用,则打开此应用。
- 打开唯一可以处理该链接类型的应用。
- 允许玩家从对话框中选择应用打开。
为 iOS 应用配置 universal link
步骤1:配置 Web 服务器
配置 JSON 文件 apple-app-site-association
并将其添加在 Web 服务器的根目录。Universal link 不需要部署在官网的域名下,只需部署在确保可以访问的高级目录中。若需部署在官网,请参见下文中的示例或 Supporting associated domains。
将 universal link 部署在官网域名的配置:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "9JA89QQLNQ.com.apple.wwdc",
"paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
},
{
"appID": "ABCD1234.com.apple.wwdc",
"paths": [ "*" ]
}
]
}
}
apps
键必须存在,其值必须是空数组details
键对应一个字典数组,网站支持每个应用程序一部字典,数组中字典的顺序决定了系统在查找匹配项时遵循的顺序,因此可以指定一个应用程序来处理网站的特定部分。- 每个特定应用程序的字典都包含一个
appID
键和一个paths
链:appID
键的值是团队 ID 或应用 ID 前缀,后跟Bundle ID。paths
键的值是一个字符串数组,用于指定应用程序支持的网站路径以及不与应用程序关联的网站路径。指定不作为 universal link 处理的区域时,将"NOT"
(包括空格)添加到路径字符串的开头,例如"paths": [ "/wwdc/news/", "NOT/videos/wwdc/2010/*", "/videos/wwdc/201?/*"]
。由于系统paths
会按照指定的顺序评估数组中的每个路径,并在找到正匹配或负匹配时停止评估,因此需在低优先级路径之前指定高优先级路径。
对于重签名的 App,必须将重签名证书的 appID
以及 paths
键也配置在这里。
在 apple-app-site-association
文件中指定网站路径 paths
的方法:
- 用
*
指定整个网站。 - 用一个特定的 URL 指定一个特定的链接,例如
/wwdc/news/
。 - 用
*
匹配任何字符串,并将*
附加到特定的 URL 以指定网站的一部分,例如/videos/wwdc/2015/*
。 - 用
?
匹配任何单个字符,并将两个通配符(*
和?
) 组合在一个路径中,例如/foo/*/bar/201?/mypage
。
在 paths
数组中指定网站路径的字符串必须区分大小写。
步骤2:配置 associated domains
开启 AppleID Associated Domains 能力需联系证书管理相关负责人申请开通。更多详情,请参见 Supporting associated domains。
开启 Associated Domains 能力后,请重新生成签名描述文件。
配置 Xcode 能力。在 Xcode 工程中的 Signing & Capabilities 中开启 Associated Domains,并在 Domains 添加您的域名,格式为
applinks:your_link
。注意配置 Domains 时无需添加
https://
。
游戏也可以通过代码和配置自动添加开启 Associated Domains。
- Unity
- Unreal Engine
可以在 PostProcess 中添加以下代码:
#if UNITY_2019_3_OR_NEWER
var capManager = new UnityEditor.iOS.Xcode.ProjectCapabilityManager(projPath, entitlementsFilePath, targetGuid: targetProjectName);
#else
var capManager = new UnityEditor.iOS.Xcode.ProjectCapabilityManager(projPath, entitlementsFilePath, targetProjectName);
#endif
capManager.AddAssociatedDomains(new string[] { "your_link1", "your_link2", "your_link3" });
在 UE4 中添加
Entitlement
,修改 Unreal Engine 路径下的以下文件:/Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/IOSExports.cs
注意此处方法为设置多个或者一个 universal link 域名的情况,可以考虑通过 array 的形式获取链接并写入对应位置,设置完毕后需要重新运行
UnrealBuildTool.sln
,并重新生成解决方案其中AssociatedDomains
、bEnableAssociatedDomains
等参数名称可以根据需要自行配置修改。// for AssociatedDomains with Apple
bool bEnableAssociatedDomains = false;
string domainsListString = null;
PlatformGameConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AssociatedDomains", out domainsListString);
PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableAssociatedDomains", out bEnableAssociatedDomains);
if(bEnableAssociatedDomains && domainsListString.Length > 0){
Text.AppendLine("\t<key>com.apple.developer.associated-domains</key>");
Text.AppendLine("\t<array>");
string[] domainList = domainsListString.Split(',');
for(int i = 0;i<domainList.Count();i++)
{
Text.AppendLine(string.Format("<string>{0}</string>", domainList[i]));
}
Text.AppendLine("\t</array>");
}在
DefaultEngine.ini
中找到/Script/IOSRuntimeSettings.IOSRuntimeSettings
添加以下配置:bEnableAssociatedDomains=True
AssociatedDomains=your_link1,your_link2,your_link3
步骤3:配置 Player Network SDK
Player Network SDK V1.12.00 及以上
- Unity
- Unreal Engine
由于当前 INTLCore 对该入口方法 hook 不生效,所以在 Unity 的 UnityAppController.mm
文件的 UnityAppController
类中添加 iOS 的生命周期入口函数。
目前 XCodePostProcess.cs
代码已经自动在编译后的处理流程中添加了 application:continueUserActivity:restorationHandler
方法 (函数中不需要额外添加代码)。
不要在 UnityAppController
的子类中添加生命周期入口函数。确保入口函数是在跟 application:openURL:options:
等系统生命周期函数在同一个类中。
- (BOOL)application:(UIApplication *)application continueUserActivity:
(NSUserActivity *)userActivity restorationHandler:(void(^)
(NSArray<id<UIUserActivityRestoring>> *
__nullablerestorableObjects))restorationHandler {
return YES;
}
在 iOS 中实现一个 iOSAppDelegate 类别,并将其放入 INTLSDK/Source/INTLCore/Private/iOS
插件。
该方案使用 iOS category 实现,存在被其他 SDK 替换掉的风险,游戏务必验证 URL 是否生效。
新建一个 IOSAppDelegate+INTL.mm
文件,内容如下:
# define WITH_INTLSDK 1
# if WITH_INTLSDK
# ifdef __APPLE__
# import <Foundation>
# import "IOSAppDelegate.h"//UE4
# include "CoreDelegates.h"//UE4
# include "INTLApplicationDelegate.h"
@interface IOSAppDelegate(INTLSDK)
@end
@implementation IOSAppDelegate(INTLSDK)
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
NSLog(@"IOSAppDelegate(INTLSDK) continueUserActivity ");
return [[INTLApplicationDelegate sharedInstance] application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
@end
# endif
# endif
步骤4:测试 universal link
因为微信内置浏览器的限制,在微信中打开链接时不会跳转应用。
在 iOS 备忘录中点击应用的链接后,应跳转至应用并在日志中记录:
INTLApplicationDelegate:continueUserActivity:restorationHandler
示例:
在安装或更新后首次打开应用时,系统会从对应的域名请求 apple-app-site-association
文件。当配置正确但 universal link 不可访问时,请尝试重启手机或重新安装应用。
进行 apple-app-site-association
以及应用的 Xcode 工程配置之后,整个 universal link 运作流程完全由系统控制。据推断,在安装或更新后,首次打开应用时会发生以下情况:
- App 向工程里配置的域名发起
Get
请求拉取apple-app-site-association
文件。 - App 将
apple-app-site-association
注册到系统。 - 在 WebView 中打开 URL 时根据注册的
apple-app-site-association
URL 检查打开的 URL。 - 如果命中了注册过的 universal link,则打开应用触发 universal link delegate。
- 如果没命中,则 WebView 继续跳转 URL。
为应用配置 AppsFlyer OneLink
AppsFlyer 支持 AppsFlyer SDK 提供的以下深度链接功能:
深度链接(Deep linking):深度链接发生在目标应用程序已经安装的情况下。配置的深度链接会将用户发送到特定的应用内位置或完成特定的应用内活动。
延迟深度链接(Deferred deep linking):延迟深度链接发生在目标应用程序未安装时。配置的深度链接会将用户发送到特定应用商店中目标应用的下载页面。当用户安装并打开应用时,延迟深度链接会将用户发送到目标应用内位置或完成目标应用内活动。
AppsFlyer OneLink 是 AppsFlyer 独有的功能,指的是跨平台功能的归属链接,支持将用户从各种源平台(如电子邮件、社交媒体、网络、二维码等)转发到目标应用程序,在此过程中还会转发用户的 ID。运营团队需要确认返回的 ID 是 OpenID 还是设备 ID,然后在最终数据分析中使用得到的用户 ID 将相关渠道归属于受邀用户。
步骤1:在 AppsFlyer 控制台上创建一个应用
根据 AppsFlyer 文档 添加应用程序 来创建您的应用程序。
步骤2:配置 OneLink
如果是 OneLink 管理的新手,请根据新客户使用指引配置 OneLink 模板。更多信息,请参见 OneLink 模板
在右上角,点击菜单图标后选择添加 OneLink 模板,并记录模板 ID。
在 OneLink 设置页面,输入模板名称,子域名,并选择之前创建的应用程序。
记录输入的子域名。对于 Android 应用程序,在 When app is installed 部分,点击 Use App Links to launch the app 添加 keystore 的 SHA-256。更多信息,请参见 Android initial setup。
复制并保存 AppsFlyer 后台生成的
intent-filter
代码。保存 OneLink 模板。
步骤3:配置 Player Network SDK
Android
在
INTLConfig.ini
的[AppsFlyer]
节点下添加以下代码,并将{OneLink_Template_ID}
替换为 步骤2 记录的模板 ID。APPSFLYER_APP_INVITE_ONELINK_ID_ANDROID = {OneLink_Template_ID}
若
INTLConfig.ini
中的[Android LifeCycle]
不包含 AppsFlyer,则添加 AppsFlyer。LIFECYCLE = WeChat,QQ,Twitter,Adjust,Facebook,Google,Line,VK,Garena,Discord,Dmm,Update,Firebase,KaKao,WhatsApp,Permission,GooglePGS,AppsFlyer
在
AndroidManifest.xml
的游戏MainActivity
节点下添加在 步骤2 中保存的 Androidintent-filter
代码。
此代码用于打开游戏,请根据实际情况替换{Subdomain}
和{OneLink_Template_ID}
。<activity
android:name="com.intlgame.unity.MainActivity"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="{Subdomain}.onelink.me"
android:pathPrefix="/{OneLink_Template_ID}"
android:scheme="https" />
</intent-filter>
</activity>
iOS
- Unity
- Unreal Engine
在
INTLConfig.ini
的[AppsFlyer]
节点下添加以下代码,并将{OneLink_Template_ID}
替换为 步骤2 记录的模板 ID。APPSFLYER_APP_INVITE_ONELINK_ID_IOS = {OneLink_Template_ID}
在
Assets\INTLSDK\Editor\XUPorter\XCodePostProcess.cs
中,将从步骤2中得到的子域名 (例如appslinks:subdomain.onelink.me
) 添加到该行。capManager.AddAssociatedDomains(new string[] { "appslinks:subdomain.onelink.me"});
更多信息,请参见 OneLink 链接与用户体验。
步骤4:调用 OneLink 接口
设置生成 OneLink 的回调。
- Unity
- Unreal Engine
INTLAPI.AddExtendResultObserver(OnExtendEvent);//设置回调
INTLExtend.Invoke("AppsFlyer", "generateInviteLinkUrl", paramsJsonString);// paramsJsonString是需要传送给OneLink的信息
public void OnExtendEvent(INTLExtendResult extendResult)
{
if ("generateInviteLinkUrl".Equals(extendResult.ExtendMethodName))//生成 OneLink 的方法
{
if (extendResult.RetCode == 0)//OneLink 生成成功
{
string inviteUrl = extendResult.RetMsg;//生成的 OneLink,可以分享给其他玩家
//TODO:share link to other players
}
else//OneLink 生成失败
{
//TODO: handle OneLink Failed result
}
}
}- 回调类继承
IINTLPluginObserver
类 - 回调类根据需要实现
IINTLPluginObserver
类的方法
FINTLExtendEvent extendEvent;
extendEvent.AddUObject(this, &UFriendWindow::OnExtendResult_Implementation);
UINTLSDKAPI::ExtendInvoke(EINTLLoginChannel::kChannelAppsFlyer,TEXT("generateInviteLinkUrl"), paramsJsonString);// paramsJsonString是需要传送给OneLink的信息
void UFriendWindow::OnExtendResult_Implementation(FINTLExtendResult ret) {
if (ret.ExtendMethodName.Equals(TEXT("generateInviteLinkUrl")))
{
if (ret.RetCode == 0)//OneLink生成成功
{
FString inviteURL = ret.RetMsg;//生成的OneLink,可以分享给其他玩家
//TODO:share link to other players
}
}
}设置被分享链接的用户点击生成的 OneLink 后的结果回调。
- Unity
- Unreal Engine
生成 OneLink 和点击 OneLink 共用一个回调,通过回调中的
INTLExtendResult
的参数区分。INTLAPI.AddExtendResultObserver(OnExtendEvent);//设置回调
public void OnExtendEvent(INTLExtendResult extendResult)
{
if ("OnOneLinkResult".Equals(extendResult.ExtendMethodName))//OneLink 点击回调
{
if (extendResult.RetCode == 0)//OneLink 点击回调成功
{
string jsonParameter = extendResult.ExtraJson;//点击 OneLink 后 AF 返回的参数
//TODO:Handle OneLink Parameter
}
else//OneLink 点击回调失败
{
//TODO: handle OneLink Failed result
}
}
}FINTLExtendEvent extendEvent;
extendEvent.AddUObject(this, &UFriendWindow::OnExtendResult_Implementation);
void UFriendWindow::OnExtendResult_Implementation(FINTLExtendResult ret) {
if (ret.ExtendMethodName.Equals(TEXT("OnOneLinkResult")))//OneLink点击回调
{
if (ret.RetCode == 0)// OneLink 点击回调成功
{
FString jsonParameter = ret.ExtraJson;// 点击 OneLink 后AF返回的参数
//TODO:Handle OneLink Parameter
}
else// OneLink 点击回调失败
{
//TODO: handle OneLink Failed result
}
}
}参考以下代码生成 OneLink,并根据实际情况替换代码中的参数。
- Unity
- Unreal Engine
StringBuilder sb = new StringBuilder();
sb.Append("{");
sb.Append("\"deep_link_value\":\"abc\"").Append(","); //<TARGET_VIEW>
sb.Append("\"deep_link_sub1\":\"1234\"").Append(",");//<PROMO_CODE>
sb.Append("\"deep_link_sub2\":\"1234\"").Append(",");//<REFERRER_ID(openid)>
sb.Append("\"channel\":\"mobile_share\"").Append(",");//Channel
sb.Append("\"campaign\":\"summer_sale\"");//Campaign
//其他参数,可选
sb.Append("\"deep_link_sub3\":\"1234\"").Append(",");
sb.Append("\"deep_link_sub4\":\"1234\"").Append(",");
sb.Append("\"deep_link_sub5\":\"1234\"").Append(",");
sb.Append("\"deep_link_sub6\":\"1234\"").Append(",");
sb.Append("\"deep_link_sub7\":\"1234\"").Append(",");
sb.Append("\"deep_link_sub8\":\"1234\"").Append(",");
sb.Append("\"af_sub4\":\"12324\"").Append(",");
sb.Append("\"af_sub5\":\"dfasdf\"").Append(",");
sb.Append("}");
String paramsJsonString = sb.ToString();
INTLExtend.Invoke("AppsFlyer", "generateInviteLinkUrl", paramsJsonString);FString ParamsJsonString = TEXT("");
const TSharedRef<TJsonWriter<>> JsonWriter = TJsonWriterFactory<>::Create(&ParamsJsonString);
JsonWriter->WriteObjectStart();
JsonWriter->WriteValue(TEXT("deep_link_value"),TEXT("abc"));
JsonWriter->WriteValue(TEXT("deep_link_sub1"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub2"),TEXT("1234"));
JsonWriter->WriteValue(TEXT(""),TEXT("1234"));
JsonWriter->WriteValue(TEXT(""),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub3"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub4"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub5"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub6"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub7"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("deep_link_sub8"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("af_sub4"),TEXT("1234"));
JsonWriter->WriteValue(TEXT("af_sub5"),TEXT("dfasdf"));
JsonWriter->WriteObjectEnd();
JsonWriter->Close();
UINTLSDKAPI::ExtendInvoke(EINTLLoginChannel::kChannelAppsFlyer,TEXT("generateInviteLinkUrl"),
步骤4:测试 OneLink 集成
进入 AppsFlyer 控制台。
在左侧边栏中,单击 SDK Integration Tests。
选择要测试的应用程序,点击 Run test。
在 Run non-organic install test 页面,选择测试设备并选择 Other。
扫描二维码并安装应用。
若要再次测试激活,请删除该应用程序并重新启动测试。
参考文档
AppsFlyer 深度链接和 OneLink:Deep linking
iOS | Android |
---|---|
初始设置 | 初始设置 |
统一 deep linking | 统一 deep linking |
旧版本 API | 旧版本 API |
使用 iOS 私人中继的延迟 deep link | 使用 Android 私人中继的延迟 deep link |
用户邀请属性 | 用户邀请属性 |
客户端接口
Deep link 回调处理
Deep link observer 处理 deep link 数据相关的回调函数。更多信息,请参见:
- Unity
- Unreal Engine
API | 函数定义 |
---|---|
SetDeepLinkObserver | 设置 deep link 回调,通知游戏引擎层是否有数据到达,收到回调后,需要手动调 Fetch 函数获取数据。 |
RemoveDeepLinkObserver | 移除 deep link 的回调 |
API | 函数定义 |
---|---|
SetDeepLinkObserver | 设置 INTL deep link 模块 BaseResult 的回调,通知游戏引擎层是否有数据到达,收到回调后,需要手动调 Fetch 函数获取数据。 |
GetDeepLinkObserver | 获取 BaseResult 的回调。 |
OnDeepLinkResult_Implementation | 实现 INTL deep link BaseResult 的回调 |
Fetch
Fetch
接口获取 SDK 缓存的 deep link 数据。更多信息,请参见: