简介
IOS常见的跳转方式有URL scheme和Universal Links。这两个均可以实现App之间的跳转,以及通过网页实现跳转到对应的App内。通过本文章可以了解到两者的区别和具体的使用方法,以及参数的传递。应对常见的几种跳转需求。
URL scheme:需要配置URL scheme,可以通过该URL直接启动App。该URL实际上不是真正可以访问的网页域名,因此如果App没有安装,就没有任何反应。并且URL scheme是各自开发者在App内设置的,所以可能出现冲突的情况。
Universal Links:配置实际可以访问的域名,并且根据配置表,可以将路径和对应的App进行关联。如果已经安装了App可以直接跳转到App。如果没有安装App,可以直接跳转到对应的网页。
官方文档:https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content?language=objc
配置Url Scheme
1.配置
打开Xcode工程,在Info.plist的URL Types添加一个新的Url Scheme。需要填入Identifier和URL Schemes
这里分别命名为youridentifier和yourscheme需要注意URL Schemes需要起的复杂一些,避免重名。
Tips:如果出现App A与App B也定义了相同的URL Scheme。那么访问URL Scheme的时候只会访问其中一个应用,另外一个App的URL Scheme就失效了
2.测试链接是否成功
设置完Url Scheme后,在测试设备上安装该应用。之后可以通过safari或者备忘录,直接通过URL Scheme访问。
Url Scheme的形式有点类似于网页。可以直接在Safari输入yourscheme://xxxxx 如果弹出提示框,是否访问该应用说明配置成功 。这里填写的yourscheme就是Info.plist中填写的URL Scheme。"://"之后填写的是自定义的参数。可以通过参数来得知启动的来源。
3.添加启动参数获取代码
Unity获取启动参数,需要通过继承UnityAppController的方式进行。在Assets/Plugins/IOS/目录下添加YourAppController.h和YourAppController.mm
对应代码如下:
SQL #ifndef YourAppController_h #define YourAppController_h #import "UnityAppController.h" @interface YourAppController : UnityAppController @end
#endif |
SQL #import #import "YourAppController.h" @implementation YourAppController - (void)applicationDidBecomeActive:(UIApplication*)application { [super applicationDidBecomeActive:application]; } - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { [super application:application didFinishLaunchingWithOptions:launchOptions];
return YES; } // UIApplicationOpenURLOptionsKey was added only in ios10 sdk, while we still support ios9 sdk - (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary*)options { [super application:app openURL:url options:options]; if(url) { UnitySendMessage("YourReceiver", "YourMethod", url.absoluteString.UTF8String); } return YES; } //进入 后台 - (void)applicationDidEnterBackground:(UIApplication*)application { [super applicationDidEnterBackground:application]; } //进入前台 - (void)applicationWillEnterForeground:(UIApplication*)application { [super applicationWillEnterForeground:application]; } @end //设置当前类为启动类 IMPL_APP_CONTROLLER_SUBCLASS(YourAppController); |
获取参数的函数为- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary*)options,获取完参数之后可以通过UnitySendMessage的方式,在C#端处理逻辑
配置Universal Links
1.开发者后台配置
在developer.apple.com的后台,点击对应的Identifiers,勾选Associated Domains
2.工程配置
打开Xcode工程,在Signing&Capabilities页签点击+Capability 之后选择Associated Domains
之后添加具体的Associated Domains。比如你的域名为yourdomains.com,填入的具体形式为applinks:yourdomains.com
3.apple-app-site-association配置
然后设置apple-app-site-association。apple-app-site-association的格式如下,details是一个列表。列表内是每个应用对应的配置。appID的格式是,前面为TeamID(可以在developer.apple.com查看),后面则是应用的bundleid。path为应用对应的路径,"*"为通配符。
下面的例子代表有三个app。打开yourdomains.com/path1/ 路径下的网页,访问app1。yourdomains.com/path2/ 代表访问app2。其他yourdomains.com/ 下的网页均访问app3。需要注意的是,配了下一级路径的,比如"paths": ["/path1/*"] 也要在结尾加上*。还有就是如果没有下一级路径比如下面的app3的"paths": ["*"]。建议配置在数组的末端。之前测试时,这个apple-app-site-association是顺序访问的,所以如果配在顶部,会出现所有网页均访问"*"的情况。
XML { "applinks": { "apps": [], "details": [{ "appID": "TEAMID.BUNDLEID1", "paths": ["/path1/*"] }, { "appID": "TEAMID.BUNDLEID2", "paths": ["/path2/*"] }, { "appID": "TEAMID.BUNDLEID3", "paths": ["*"] }
] } } |
4.上传apple-app-site-association到文件服
如果自己未搭建文件服务器可以直接使用阿里云。这里需要注意,必须将apple-app-site-association放置在根目录,或者根目录/.well-known/ 目录下
https://yourdomains.com/apple-app-site-association
https://yourdomains.com/.well-known/apple-app-site-association
5.测试链接是否成功
下面以访问app1为例子进行链接测试。前面的配置都完成之后,用测试设备安装应用,确保网络是正常的。
由于之前配置的Associated Domains为yourdomains.com,app1在apple-app-site-association内配置的路径为["/path1/*"],所以最后需要将域名和path拼在一起:https://yourdomains.com/app1
可以将该网址放在复制到备忘录,然后长按该路径。如果出现如下在"xxx"中打开的提示,说明Universal Links配置正确。并且可以直接点击该链接进入App。
也可以直接在safari浏览器输入上面的网址。网页的顶部会出现在"xxx"App中打开的提示。并且点击右侧的打开按钮,
6.注意事项
- apple-app-site-association不能有后缀名
- apple-app-site-association是在app第一次安装和后续更新的时候获取。如果网络不好,有可能出现没有获取到,导致Universal Link失效的情况
- 如果修改了apple-app-site-association的内容,apple-app-site-association生效需要等待一段时间。同时需要卸载重装后再测试
- 苹果会先访问.well-known/下的apple-app-site-association,如果不存在,再访问根目录下的文件,所以建议将文件存放在.well-known/下,减少访问服务器的次数
Unity内配置
上面修改Xcode工程,添加Url Scheme和AssociatedDomains的操作,也可以通过Editor的PostProcessBuild脚本。进行添加。具体代码如下
添加Url Scheme
XML public static void SetInfoList(string buildPath) { string listPath = buildPath + "/Info.plist"; PlistDocument plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(listPath));
// 在“info”标签栏的“URL type“添加“URL scheme” PlistElementArray urlArray = plist.root.CreateArray("CFBundleURLTypes"); PlistElementDict dict = urlArray.AddDict(); dict.SetString("CFBundleTypeRole", "Editor"); dict.SetString("CFBundleURLName", "youridentifier"); PlistElementArray urlSchemes = dict.CreateArray("CFBundleURLSchemes"); urlSchemes.AddString("yourscheme");
File.WriteAllText(listPath, plist.WriteToString()); } |
设置Associated Domains
XML // 设置Associated Domains public static void SetAssociatedDomains(string pbxProjectPath, string domainUrl) { //默认 Target Name, 你自己的可能不一样 string targetName = "Unity-iPhone"; //Set the entitlements file name to what you want but make sure it has this extension string entitlementsFileName = "my_app.entitlements";
var entitlements = new ProjectCapabilityManager(pbxProjectPath, entitlementsFileName, targetName); entitlements.AddAssociatedDomains(new string[] { "applinks:" + domainUrl });
entitlements.WriteToFile(); } |
IOS跳转的解决方案
跳转流程
下面举一个简单的邀请好友获取奖励的例子。
1.配置一个网页,负责承接跳转的业务和必要的信息展示。应用可以将该网址分享到IM工具,并且根据业务需要添加具体的参数。比如玩家A给玩家B分享了关于app1的邀请链接:
https://yourdomains.com/app1/index.html?type=invite&uid=10000
这里路径为Universal Link的地址。前端将网页部署在app1/index.html的位置。
分享的参数为type=invite&uid=10000 (参数可以自定义)
2.玩家B在IM工具内点开该链接后,如果玩家已经安装了该应用app1,可以直接跳转到应用内,并且将该参数传递给app1。如果未安装该应用,或者不支持直接跳转。可以在该网页内配置下载的按钮,或者其他相关的跳转链接。
3.假如玩家B通过上面的链接正常进入到app1内,可以获取type=invite&uid=10000的参数。玩家B与服务器通信,完成对玩家A的邀请奖励发放,跳转流程到此结束。
部分网页逻辑
有的IM软件(比如Messenger),点开Universal Link并不会直接跳转App。但是可以通过网页调用URL Scheme进行跳转。所以可以添加一下的逻辑,完成跳转操作。
网页启动的时候,先判断是不是IOS设备。如果是,可以直接通过URL Scheme跳转。
XML (function () { let userAgentInfo = navigator.userAgent; let Agents = [ "iPhone", "iPod", "iPad", ]; let search = location.search; for (let i = 0; i < Agents.length; i++) { //判断是不是IOS设备 if (userAgentInfo.indexOf(Agents[i]) > 0) { //获取网页中参数 let webParams = location.search; window.location.href = "yourscheme://"+webParams; break; } } })(); |