- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
NSLog(@"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!url == %@",url);
//初始化MSDK
WGPlatform *plat = WGPlatform::GetInstance();
WGPlatformObserver *ob = plat->GetObserver();
if (!ob)
//设置回调
MyObserver* ob = MyObserver::GetInstance();
plat->WGSetObserver(ob);
plat->WGSetADObserver(ob);
plat->WGSetGroupObserver(ob);
//透传URL参数给MSDK
return [WGInterface HandleOpenURL:url];
10 Universal Link
10.1 什么是 Universal Link
Universal Link 是 Apple 从 iOS 9 引入的一种打通 web 和 app 之间跳转的机制。在 Safari 或者 WebView 中打开与 app 关联的链接时,会自动跳转到 app 并且不丢失参数内容。Universal Link 解决了 URL Scheme 的部分问题:
当跳转失败时,会直接在 Safari/WebView 中打开链接;
可以借助 Universal Link 统一 web 端和 native 的路由;
跳转时不会弹出提示框,体验更好。
有关 Universal Link 相关知识可查看:
Apple官方文档。
关于 Universal Link 的接入流程可参考iOS Universal Link教程。
Enabling Universal Links。
苹果官方的UL测试工具。
10.2 Universal Link 使用
要使用 Universal Link,要将域名和 app 关联起来,这个关联是双向的:
域名对 app 的认证:在 web 服务器根目录放一个名为 apple-app-site-association 的 json 文件,里面描述哪些路径会跳转到哪个 app。
App 对域名的认证:在 Xcode 里设置 Associated Domains,将域名添加进去。
"applinks": {
"apps": [],
"details": [{
"paths": ["/app/*", "/qq_conn/100703379/*"],
"appID": "JBS4AWYMFX.com.tencent.itop.example"
"paths": ["/app/*", "/qq_conn/100703379/*"],
"appID": "JBS4AWYMFX.com.tencent.imsdk2"
注意事项:
域名必须通过 HTTPS 访问 Universal Link 才能生效;
apple-app-site-association 只能放在域名根目录下,不能有跳转;
系统会在 app 初次安装、升级时去对应的域名下拉 apple-app-site-association 文件,如果 Universal Link 不可达,而配置都正常的话,可以尝试重启手机或重装 app。
10.3 Universal Link 运作流程
app 第一次启动或者更新版本后第一次启动(实际结果,未体现在苹果官方文档上);
app 向工程里配置的域名发起 Get 请求拉取 apple-app-site-association Json 文件;
app 将 apple-app-site-association 注册到系统;
由任意 WebView 发起跳转 url;
如果命中了 apple-app-site-association 注册过的通用链接,则打开 app,触发 Universal Link delegate;
没命中,WebView 继续跳转 url。
在进行 apple-app-site-association 以及 app Xcode 工程配置之后,整个 Universal Link 运作流程完全由系统控制。
注意:在上面第2步出现 apple-app-site-association 文件访问不可用时,会导致新安装用户后续都不能正常登录(在微信/手Q App授权界面无法跳转回游戏App),除非卸载重装。
10.4 接入MSDK Universal link授权登录能力
10.4.1 MSDK&QQ&微信版本支持情况
MSDK版本
MSDK 从V3.3.9版本开始支持;合入QQ OpenSDK 3.3.7、微信OpenSDK 1.8.6版本。
QQ App版本
QQ App 8.1.3及其以上版本支持。
微信 App版本
微信 App 7.0.7及其以上版本支持。
iOS系统版本
QQ需要 iOS13 及以上版本支持;微信需要 iOS12 及以上版本支持。
注意事项:
1. 因某些原因QQ平台现已关闭OpenSDK 3.3.6版本(MSDK V3.3.8)的Universal Link授权登录能力,业务需要测试QQ平台该能力的需更新至OpenSDK 3.3.7版本,该版本OpenSDK已合入MSDK V3.3.9版本。
2. 如果项目组有多款游戏,那么每一款游戏的Universal Link链接要保证唯一,不可以多款游戏共用一个链接。
10.4.2 新增weixinULAPI scheme白名单
info.plist中新增weixinULAPI跳转scheme白名单,否则会造成无法授权登录、分享等问题。
若接入的是 MSDKV3 Unity 版本,可直接在 \Assets\Msdk\Editor\Resources\MSDKInfo.plis 中添加。
10.4.3 开启AppleID Associated Domains能力
根据Apple官方文档找证书管理相关同学申请开通AppleID Associated Domains的能力,如下图所示:
AppleID开启了Associated Domains的能力之后请重新生成签名描述文件。
注意事项:
因目前企业签名证书暂不具备Universal Link能力,请各业务务必使用开发签名证书调试
10.4.4 飞鹰系统配置Universal Link相关参数
在飞鹰系统中配置Universal Link,配置路径在:游戏管理 -> 我的游戏 -> SDK参数 -> 搜索:编辑iOS信息 ,如下图所示:
备注:Universal Link不强制要求部署在官网域名下,只要确保部署地方高可用即可;以下描述以部署在官网下作为举例说明
其中Universal Link一栏填写业务官网下的一个子目录且需为https链接,例如:https://xxx.com/app/,注意结尾必须要有/;URL Scheme一栏填写业务的QQ跳转scheme,格式为tencent+qqappid,例如:tencent100703379;如果业务有单独的 iPad 版本,需要在飞鹰选择 iPad 版本配置。请选择上图中“有单独的 iPad 版”,并填写对应参数。
填写完之后点击提交iOS信息审核按钮保存。
注意事项:
保存之后请企业微信联系微信侧接口人wxgame审核开通权限;
若有QQ相关报错提示,请先做好下一步:10.4.5 配置apple-app-site-association
此处有任何报错均可企业微信联系MSDK助手处理
10.4.5 配置apple-app-site-association
配置样例如下:
"applinks": {
"apps": [],
"details": [{
"appID": "JBS4AWYMFX.com.tencent.newmsdk2",
"paths": ["/app/*", "/qq_conn/100703379/*"]
"appID": "JBS4AWYMFX.com.tencent.itop.example",
"paths": ["/app/*", "/qq_conn/100703379/*"]
其中appID参数需修改为业务自身的签名证书team id + bundle id,paths参数中的/app字符需替换为上一步骤10.4.4 飞鹰系统配置Universal Link相关参数中设置的官网地址.com后面的部分,例如上一步骤中配置的地址为https://xxx.com/client/,则此处的/app/*需替换为/client/*;另外QQ互联侧要求paths 参数中必须配置为/qq_conn/QQ AppID/格式,其中qq_conn为固定字段,QQ AppID填写为业务自身的QQ appid,如:/qq_conn/100703379/,否则飞鹰同步信息到QQ互联会校验失败。如需配置多个appID和paths,请参考上述事例。改好之后将文本保存为名称为apple-app-site-association的文件(注意不能加任何后缀),并将文件放置在上一步骤10.4.4 飞鹰系统配置Universal Link相关参数中设置的官网地址的根目录,需访问https://xxx.com/apple-app-site-association地址可正常下载到该文件。
10.4.6 配置Xcode Capabilities
在Xcode工程Capabilities标签下,开启Associated Domains并配置Domains,Domains固定写applinks:+官网域名,注意无需加https://样例如下:
若接入的是 MSDKV3 Unity 版本且 Unity 引擎版本为 Unity 2017 及以上版本,可参考 \assets\msdk\editor\scripts\xuporter\xcodepostprocess.cs 中的实现,样例如下:
// Need create entitlements
string relativeEntitlementFilePath = "Unity-iPhone/xxxxxx.entitlements";
Debug.Log("entitlementsPath : " + relativeEntitlementFilePath);
string absoluteEntitlementFilePath = pathToBuiltProject + "/" + relativeEntitlementFilePath;
PlistDocument tempEntitlements = new PlistDocument();
string key_associatedDomains = "com.apple.developer.associated-domains";
var arr = (tempEntitlements.root[key_associatedDomains] = new PlistElementArray()) as PlistElementArray;
// wiki.ssl.msdk.qq.com 需要替换成游戏自己域名
arr.values.Add(new PlistElementString("applinks:wiki.ssl.msdk.qq.com"));
proj.AddCapability(target_1, PBXCapabilityType.AssociatedDomains, relativeEntitlementFilePath);
string projPath_1 = UnityEditor.iOS.Xcode.PBXProject.GetPBXProjectPath(pathToBuiltProject);
File.WriteAllText(projPath_1, proj.WriteToString());
tempEntitlements.WriteToFile(absoluteEntitlementFilePath);
10.4.7 配置info.plist
在info.plist中新增类型为string名称为WX_UNIVERSAL_LINK的配置项,值填写飞鹰系统配置的Universal Link ,示例如下:
若接入的是 MSDKV3 Unity 版本,可直接在 \Assets\Msdk\Editor\Resources\MSDKInfo.plis 中添加。
10.4.8 配置实现iOS入口函数
需实现-application:continueUserActivity:restorationHandler:入口函数,在该函数中实现MSDK的初始化以及设置相关事件回调,并将相关参数调用WGPlatform::GetInstance()->WGHandleOpenUniversalLink((unsigned char *)[urlStr UTF8String]);接口透传给MSDK,样例如下:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
NSLog(@"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!activityType == %@ webpageURL == %@",userActivity.activityType, userActivity.webpageURL);
WGPlatform* plat = WGPlatform::GetInstance();
WGPlatformObserver *ob = plat->GetObserver();
if (!ob)
MyObserver* ob = MyObserver::GetInstance();
WGPlatform::GetInstance()->WGSetObserver(ob);
WGPlatform::GetInstance()->WGSetGroupObserver(ob);
WGPlatform::GetInstance()->WGSetWebviewObserver(ob);
WGPlatform::GetInstance()->WGSetEmbeddedWebViewObserver(ob);
if (userActivity && [userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb])
NSURL *webpageUrl = userActivity.webpageURL;
if (webpageUrl)
NSString *urlStr = [webpageUrl absoluteString];
return plat->WGHandleOpenUniversalLink((unsigned char *)[urlStr UTF8String]);
return YES;
若接入的是 MSDKV3 Unity 版本,可参考 \Assets\Msdk\Editor\Scripts\MsdkNativeCode.cs 中的实现,样例如下:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
NSLog(@""MSDK handle openUniversalLink activityType == %@ webpageURL ==%@"",userActivity.activityType, userActivity.webpageURL);
WGPlatform* plat = WGPlatform::GetInstance();
if (userActivity && [userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb])
NSURL *webpageUrl = userActivity.webpageURL;
if (webpageUrl)
NSString *urlStr = [webpageUrl absoluteString];
return plat->WGHandleOpenUniversalLink((unsigned char *)[urlStr UTF8String]);
return YES;
注意事项:
接入Apollo/GCloud组件的业务需按照Apollo/GCloud的方式实现该入口函数,具体可咨询Apollo/GCloud组件相关同学。
10.4.9 如何验证
微信 Universal Link 接入成功验证指引请参考 微信官方文档相关说明。
手Q Universal Link 接入成功验证指引请参考 手Q官方文档相关说明。
需拉起平台授权登录成功以及拉起平台分享成功后可通过MSDK日志查看是否是通过Universal Link授权:
日志打印 isUniversalLink:1 时说明是通过Universal Link授权,如下图日志:
日志打印 isUniversalLink:0 时说明是通过scheme授权,如下图日志:
1.因目前企业签名证书暂不具备Universal Link能力,请各业务务必使用开发签名证书调试。
2.请各业务务必按照验收标准验证授权登录以及分享流程。
11 将游戏的最低支持版本设置为iOS8.0或以上
务必将游戏的 Deployment Target 设置为8.0或者以上,否则在iOS8.0以下系统运行会发生crash,设置方式如下图所示:
12 开启Background Modes
在Xcode工程 Capabilities 标签下开启 Background Modes 并勾选 Remote notifications 选项,如下图所示:
初始化MSDK
游戏可在AppDelegate.m中以下两个游戏启动的入口初始化MSDK并设置回调Observer,注意需先引入头文件#import <MSDK/MSDK.h>。
入口1 正常启动
参考示例:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//初始化MSDK
WGPlatform *plat = WGPlatform::GetInstance();
WGPlatformObserver *ob = plat->GetObserver();
if (!ob)
//设置回调
MyObserver *ob = MyObserver::GetInstance();
plat->WGSetObserver(ob);
plat->WGSetGroupObserver(ob);
plat->WGSetWebviewObserver(ob);
return YES;
入口2 从平台拉起
示例代码:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
NSLog(@"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!url == %@",url);
//初始化MSDK
WGPlatform *plat = WGPlatform::GetInstance();
WGPlatformObserver *ob = plat->GetObserver();
if (!ob)
//设置回调
MyObserver* ob = MyObserver::GetInstance();
plat->WGSetObserver(ob);
plat->WGSetADObserver(ob);
plat->WGSetGroupObserver(ob);
//透传URL参数给MSDK
return [WGInterface HandleOpenURL:url];
处理登录回调、平台拉起回调
因登录回调、平台拉起回调可在游戏未调用相关接口时触发, 所以需要在游戏初始化MSDK前注册。
登录事件结果的通知,游戏在手Q/微信的登录态以登录回调为准,详细设置参考登录模块回调设置。
示例代码:
void MyObserver::OnLoginNotify(LoginRet& loginRet)
if(loginRet.flag == eFlag_Succ)
//登录成功
//游戏TODO:进入游戏
else if (loginRet.flag == eFlag_NeedRealNameAuth)
//需要进行实名认证,业务可自行设置实名认证流程,在info.plist中配置MSDK_REAL_NAME_AUTH_SWITCH(3.2.14及其以上版本必须配置为1)
//0,业务无需做任何操作保持在登录页即可,MSDK自动弹出实名注册界面引导用户注册,注册完引导用户重新登录
//1,业务无需做任何操作保持在登录页即可,MSDK自动弹出实名注册界面引导用户注册,业务需再次监听登录回调,实名注册成功MSDK会自动调用本地票据登录接口进行自动登录
//2,业务自定义实名认证界面,自行实现实名认证流程
//自定义界面认证流程
//1 弹出实名认证界面给用户填写相关信息
//2 调用WGSetRealNameAuthObserver接口设置实名认证回调
//3 调用MSDK实名认证接口进行认证并等待回调
//4 处理OnRealNameAuthNotify回调
//登录失败
//游戏TODO:根据flag提示玩家相关信息
平台拉起回调
手Q、微信中拉起游戏时会回到此回调,回调中包含拉起的账号,平台透传数据等信息,详细设置参考登录模块异账号处理。
示例代码:
void MyObserver::OnWakeupNotify(WakeupRet& wakeupRet)
switch (wakeupRet.flag)
case eFlag_Succ:
//本地账号登录成功,可直接进入游戏,或也可调用自动登录接口WGLogin(),等待登录回调
break;
case eFlag_NeedLogin:
//没有有效的票据,登出游戏让用户重新登录
break;
case eFlag_UrlLogin:
//本地无账号信息,自动用拉起的账号登录,需等待登录回调
break;
case eFlag_NeedSelectAccount:
//需要弹出提示框让用户选择登录的账号,并根据用户的选择调用WGSwitchUser接口
break;
case eFlag_AccountRefresh:
//外部账号和已登录账号相同,使用外部票据更新本地票据,需等待登录回调
break;
default:
break;
开关配置接口
MSDK 3.3.22版本开始新增开关配置接口,在用户同意用户协议条款之后,业务可调用该接口开启MSDK以及MSDK所包含的第三方组件对相关信息的获取;在开关开启之前,MSDK不会获取相关信息。
c++接口:
* 设置是否允许获取相关信息
void WGSetCouldCollectSensitiveInfo(bool couldCollect);
注意事项:
用户勾选同意协议相关条款后务必主动调用该接口。
【重点】手Q OpenSDK 3.5.7版本开始更新了权限相关功能,接入方未调用SetCouldCollectSensitiveInfo授权前无法使用手Q OpenSDK的各项功能。日志中会打印 “用户未授权,暂时无法使用QQ登录及分享等功能”。
设置信息字段接口
MSDK 3.3.28版本开始新增设置信息字段接口,业务可自行获取相关信息字段,调用该接口设置到MSDK以及MSDK所包含的第三方组件(目前支持该能力的有灯塔组件)。
MSDKSensitive::SetSensitiveInfo("{\"WiFiMacAddress\":\"xxx\", \"WiFiName\":\"xxx\", \"Idfa\":\"xxx\"}");
注意事项:
灯塔iOS目前支持WiFiMacAddress、WiFiName、Idfa字段。
关于微信 OpenSDK iOS 15 系统的适配说明
Xcode13.0 以及以上版本编译出的 App 在 iOS 15.0 以及以上系统上被限制了 URL Scheme query 的数量为 50。对于 plist 中 LSApplicationQueriesSchemes 配置的 scheme 数量超过 50 的 App,可能会导致:
微信 OpenSDK 某些接口返回错误结果;
无法使用 Universal Link 拉起微信,引发分享消息到微信后,应用名被添加 "未验证应用" 的问题。
使用 13.0 以及以上版本 Xcode 编译 App 的开发者需要适配以确保微信 OpenSDK 的正常使用。
从 iOS 9 开始,iOS 支持在工程 plist 中配置 LSApplicationQueriesSchemes。
将其他 App 的 scheme 配置到 LSApplicationQueriesScheme 中后,可以通过以下代码判断是否可 以通过 scheme 跳转对于的 App。
BOOL ret = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin://"]];
在接入微信 OpenSDK 时,接入文档有要求在 LSApplicationQueriesScheme添加 weixin 和 weixinULAPI (如上面截图所示)。
iOS 15系统相关变更
和苹果确认, 在 iOS 15 系统上,使用 Xcode 13 编译出的 App, LSApplicationQueriesSchemes 的数量会限制为50个。
第 50 个之后的 scheme 配置会不生效,以下代码会返回 NO
BOOL ret = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"otherAppScheme://"]];
微信 OpenSDK 适配建议
如果 LSApplicationQueriesSchemes 配置的 scheme 数量小于 50,或者 "weixin" 和 "weixinULAPI" 这两个 sheme 在前 50,无需适配。
使用 Xcode 12 以及以下版本 Xcode 编译的 App 目前暂不需要适配。
确保 "weixin" 和 "weixinULAPI" 配置在 LSApplicationQueriesSchemes 的前 50。否则以下接口可能会在 iOS 15 系统上返回错误结果或者表现异常:
[WXApi isWXAppInstalled]:安装微信的情况下,也返回 NO
[WXApi isWXAppSupportApi]:支持的情况下,也返回 NO
[WXApi isWXAppSupportStateAPI]:支持的情况下,也返回 NO
[WXApi sendAuthReq:viewController:delegatecompletion]:会判断微信未安装,拉起网页授权
所有的接口都会无法使用 Universal Link 拉起微信,降级使用 scheme 拉起微信,导致未验证应用问题