Deep Link
为 Android 应用配置 Deep Link
步骤1:创建指向应用内容的 deep link
在的应用清单中, 为网站 URI 创建一个 intent 过滤器,并配置应用程序使用相关的故意数据,以便用户能够在应用程序中达到正确的内容。
当点击的链接或程序化请求调用网页 URL intent 时,Android 系统会按顺序尝试执行以下每项操作,直到请求成功为止:
- 如果用户指定了可以处理该 URL 的首选应用,就打开此应用。
- 打开唯一可以处理该 URL 的应用。
- 允许用户从对话框中选择应用。
步骤2:配置 Player Network SDK
版本要求:Player Network SDK 版本 1.12.00 及以上
在应用清单中,为应用创建 intent 过滤器,并将应用配置为使用来自相关 intent 的数据,以便将用户引导至应用中的正确内容。
<action>
指定 ACTION_VIEW intent 操作,以便能够从 Google 搜索中访问此 intent 过滤器。
<data>
添加一个或多个
<data>
标记,每个标记都代表一个解析为 Activity 的 URL 格式。<data>
标记必须至少包含android:scheme
属性。 添加更多属性,以进一步细化 Activity 接受的 URL 类型。例如,您可能拥有多个接受相似 URL 的 Activity,(这些 URL 只是路径名称有所不同)。在这种情况下,请使用android:path
属性或其pathPattern
或pathPrefix
变体区分系统应针对不同 URL 路径打开哪个 Activity。
<category>
包含
BROWSABLE
类别。如果要从网络浏览器中访问 intent 过滤器,就必须提供该类别。否则,在浏览器中点击链接便无法解析为您的应用。 此外,还要包含DEFAULT
类别。这样您的应用才可以响应隐式 intent。否则,只有在 intent 指定您的应用组件名称时,Activity 才能启动。
以下 XML 代码段展示了如何在清单中为 deep link 指定 intent 过滤器。URL “example://gizmos” 和 “http://www.example.com/gizmos” 都会解析到此 Activity。
<activity
android:name="com.example.android.GizmosActivity"
android:label="@string/title_gizmos" >
<intent-filter android:label="@string/filter_view_http_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URLs that begin with "http://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
</intent-filter>
<intent-filter android:label="@string/filter_view_example_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URLs that begin with "example://gizmos” -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
请注意,<data>
元素是这两个 intent 过滤器的唯一区别。虽然同一过滤器可以包含多个 <data>
元素,但如果您想要声明唯一网址 (例如特定的 scheme
和 host
组合),则创建单独的过滤器很重要,因为同一 intent 过滤器中的多个 <data>
元素实际上会合并在一起以涵盖合并后属性的所有变体。例如,请参见以下示例:
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
<data android:scheme="app" android:host="open.my.app" />
</intent-filter>
看起来这似乎仅支持 https://www.example.com
和 app://open.my.app
。但是,实际上除了这两种之外,它还支持 app://www.example.com
和 https://open.my.app
。
当向应用清单添加包含 Activity 内容 URL 的 intent 过滤器后,Android 可以在运行时将所有包含匹配 URL 的 Intents
转发到您的应用。
步骤3: 验证 Android 应用链接
将应用配置为要求验证应用链接。然后,在您的网站上发布 Digital Asset Links JSON 文件,以通过 Google Search Console 验证所有权。
Android 应用链接是一种特殊类型的 deep link,可让网站网址直接在 Android 应用中打开相应内容,无需用户选择应用。
如需验证您对应用和网站的所有权,您需要执行以下步骤:
- 在清单中请求自动验证应用链接。这样即可向 Android 系统说明其应该验证您的应用是否属于 intent 过滤器中使用的网址网域。
- 通过在以下位置托管 Digital Asset Links JSON 文件,声明您的网站和 intent 过滤器之间的关系:
https://domain.name/.well-known/assetlinks.json
您必须在网站上发布 Digital Asset Links JSON 文件,以指示与网站相关联的 Android 应用并验证应用的网址 intent。JSON 文件使用下列字段标识关联的应用:
- package_name: 在应用的
build.gradle
文件中声明的应用 ID。 - sha256_cert_fingerprints: 应用的签名证书的 SHA256 指纹。您可以利用 Java 密钥工具,通过以下命令生成该指纹:
$ keytool -list -v -keystore my-release-key.keystore
此字段支持多个指纹,这些指纹可用于支持不同版本的应用,例如调试版 build 和正式版 build。
以下 assetlinks.json
示例文件可为 com.example Android 应用授予链接打开权限:
[{
"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"]
}
}]
步骤4:接收 Android intent 数据
调用正确的方法检索与传入 Intent
。
- Unity
- Unreal Engine
在主 Activity 的 onCreate
和 onResume
中调用 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
和 onResume
里调用 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>
步骤5:测试配置
安装应用并在 Android 文本编辑器打开测试链接。
在 Android 文本应用 (例如便签) 中点击链接跳转应用后,在日志中包含
[ (intl_deeplink_manager.cpp:37) Receive]
字样。使用 adb 测试 intent 过滤器 URL 的一般语法为:
$ adb shell am start
-W -a android.intent.action.VIEW
-d <URL> <PACKAGE>例如,以下命令试图查看与指定 URL 相关的目标应用 Activity。
$ adb shell am start
-W -a android.intent.action.VIEW
-d "example://gizmos" com.example.android
在微信中打开链接时,因为微信内置浏览器的限制,不会跳转应用。
多商店渠道包
对于不同包名的渠道包,可使用 android:pathPrefix
属性进行区分,例如 渠道 A 添加了 android:pathPrefix="/sample"
则如果同时安装了 渠道 A 和 渠道 B 包,使用 http://sdk-deeplink-confs.intlgame.com/sample 链接会拉起渠道 A。
链接会拉起渠道 A。
[{
"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"]
}
}]
为 iOS 应用配置 Universal Link
步骤1:配置 Web 服务器
配置 JSON 文件 apple-app-site-association
并将其添加在 Web 服务器的根目录。Universal Link 不需要部署在官网的域名下,只需部署在确保可以访问的高级目录中。若需部署在官网,请参见下文中的示例或 支持 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
键的值是一个字符串数组,用于指定应用程序支持的网站路径以及不与应用程序关联的网站路径。指定不作为通用链接处理的区域时,将"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 能力根据 Apple 官方文档 支持 Associated Domains 联系证书管理相关负责人申请开通 AppleID Associated Domains 的能力。
AppleID 开启了 Associated Domains 的能力之后请重新生成签名描述文件。
配置 Xcode Capabilities。在 Xcode 工程中的 Signing & Capabilities 中开启 Associated Domains ,并将 Domains 设置为
applinks: + official website domain
。
配置 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" });
支持 Unreal Engine 版本 4.25 到 4.27。
- 修改 UE 引擎路径下的文件
/Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/IOSExports.cs
,在 UE4 中添加Entitlement
。
此处方法为设置多个或者一个通用链接域名的情况,可以考虑通过 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 版本 1.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 delegate。
- 如果没命中,则 WebView 继续跳转 URL。
为应用配置 AppsFlyer One Link
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
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"});
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
的游戏主 Activity 节点下添加在 步骤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>
更多信息,请参见 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"),
集成测试
进入 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 数据。更多信息,请参见: