iOS 9 Safari中使用自定义URL scheme的iframe src无法工作

33
我使用这个解决方案 https://gist.github.com/davidwkeith/2662899 来实现在应用已安装时从网页跳转到我的应用。但是在 iOS 9 上无法正常工作,尽管在 Google Chrome 上还能够正常工作。但是使用自定义 URL scheme 的 iframe 无法从 Safari 中启动应用程序。
如果我替换
document.getElementById('loader').src = 'custom-protocol://my-app'
< p >(其中加载器为iframe)带< /p >
window.location = 'custom-protocol://my-app'

它将会运作。

系统:iOS 9 beta4和beta5

有人知道这个问题吗?这是iOS 9测试版的一个错误吗?或者这个问题不会被修复?


这个方案在未来的任何时候都可能不起作用。苹果很可能意识到禁用此功能将会推动更高程度的通用链接采用率。请参见下面我更详细的回答。 - st.derrick
2个回答

18

前面的回答只是部分实现了通用链接,缺少重要细节并且没有包含到App Store的回退机制。

首先,您不能再使用iframe的src来触发URI scheme。您正确地识别了这个问题。正如您所指出的,您仍然可以设置window.location = 'custom-protocol://my-app';。因此,如果您知道用户安装了您的应用程序,因为您之前已经从浏览器打开过他们的应用程序并且存储了可以在后端查找的cookie,那么您仍然可以安全地触发custom-protocol://

其次,您可以使用navigator.userAgent检测用户代理字符串。在iOS 9之前,您仍然可以使用iframe触发URI scheme,然后在超时后回退。在iOS 9上,您可以根据cookie选择是否触发URI scheme,然后带用户前往App Store。我在Branch工作,我们已经实现了利用cookie来记录用户是否可能拥有该应用程序。如果您对此有更多问题,请随时联系我们,或直接使用我们的解决方案。


实现通用链接并不像其他回答描述的那样简单。事实上,存在相当大的复杂性。以下是一个完整的步骤列表(我最近几周帮助了几个应用程序进行集成):

1. 配置您的应用程序以注册批准的域名

i. 在developer.apple.com上注册您的应用程序

ii. 在developer.apple.com上启用您的应用程序标识符的“关联域”

iii. 在您的Xcode项目中启用“关联域”

entitlements

iv. 在您的应用程序中添加适当的域名权限,applinks:yourdomain.com

applinks

2. 配置您的网站以托管“apple-app-site-association”文件

i. 购买一个域名或从现有域名中选择一个

ii. 为该域名获取SSL证书(您可以使用CloudFlare来实现!)

iii. 创建结构化的“apple-app-site-association”JSON文件

{
   "applinks": {
       "apps": [ ],
       "details": {
           "TEAM-IDENTIFIER.YOUR.BUNDLE.IDENTIFIER": {
               "paths": [
                   "*"
               ]
           }
       }
   }
}

iv. 用 SSL 证书对 JSON 文件进行签名


配置文件服务器:

apple-app-site-association 文件: - 必须使用头信息 'application/pkcs7-mime' 发送 - 必须从你���域名下的 endpoint:youdomain.com/apple-app-site-association 发送 - 必须返回 200 http 状态码。

示例 Express+Node:

var aasa = fs.readFileSync(__dirname + '/static/apple-app-site-association');
app.get('/apple-app-site-association', function(req, res, next) {
     res.set('Content-Type', 'application/pkcs7-mime');
     res.status(200).send(aasa);
});

credit: 改编自这篇博客文章


3
如果使用window.location = 'custom-protocol://my-app';,当用户未安装你的应用时,会从Safari中看到“无法打开页面”的警告提示。 - bobics
1
没错。这就是为什么在iOS 7和iOS 8上的iframe技巧非常好用。只要确定你可以接受错误消息,或者相当确信用户有你的应用程序,才会设置window.location='custom-protocol://'; - st.derrick
我还注意到从iOS9(Safari 601)开始,当识别到URL方案时,Safari也会提示用户是否要前往应用程序或停留。无论如何都有一个警报,为什么要烦恼呢? - Ge Rong

1

iOS9现在可以进行深度链接。请查看链接获取详细解释,但我列出了基本信息。

http://blog.hokolinks.com/how-to-implement-apple-universal-links-on-ios-9/

首先,您需要前往目标并单击“功能”。添加相关域。
接下来,您必须上传apple-app-site-association文件。
基本上,打开JSON编辑器并构建类似于此的内容。
{
  "applinks": {
"apps": [],
"details": {
  "TBEJCS6FFP.com.domain.App": {
    "paths":[ "*" ]
  }
}
  }
}

下一步,您需要在应用程序中支持通用链接。您需要实现。
extension AppDelegate {
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        let webpageURL = userActivity.webpageURL! // Always exists
        if !handleUniversalLink(URL: webpageURL) {
            UIApplication.sharedApplication().openURL(webpageURL)
        }
    }
    return true
}

private func handleUniversalLink(URL url: NSURL) -> Bool {
    if let components = NSURLComponents(URL: url, resolvingAgainstBaseURL: true), let host = components.host, let pathComponents = components.path?.pathComponents {
        switch host {
        case "domain.com":
            if pathComponents.count >= 4 {
                switch (pathComponents[0], pathComponents[1], pathComponents[2], pathComponents[3]) {
                case ("/", "path", "to", let something):
                    if validateSomething(something) {
                        presentSomethingViewController(something)
                        return true
                    }
                default:
                    return false
                }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接