iOS 9 safari iframe src与自定义url方案不工作。

时间:2023-01-23 15:12:33

I use this solution https://gist.github.com/davidwkeith/2662899 to redirect into my app from web if app installed. But it was broken in ios 9. It still work in google chrome, but iframe with custom url scheme not launching app in safari.

我使用这个解决方案https://gist.github.com/davidwkeith/2662899,如果应用程序安装了,可以从web重新定向到我的应用程序。但它在ios 9中被打破了。它仍然在谷歌chrome中工作,但iframe与自定义url计划在safari中不启动应用。

If i replace

如果我代替

document.getElementById('loader').src = 'custom-protocol://my-app'

(where loader is iframe) with

(加载器为iframe)。

window.location = 'custom-protocol://my-app'

it will be work.

它将工作。

os: iOS 9 beta4 and beta5

操作系统:ios9 beta4和beta5。

Anybody know this problem? Is it ios 9 beta bug? Or it will not be fixed?

有人知道这个问题吗?是ios9测试版的bug吗?或者它不会被修复?

2 个解决方案

#1


17  

The previous answer is a partial implementation of Universal Links that is missing critical details and doesn't include a fallback to the App Store.

之前的答案是部分的通用链接的实现,这些链接缺少关键的细节,不包括应用程序商店的回退。

First, you can no longer set iframe src in order to trigger a URI scheme. You've correctly identified that issue. As you noted, you can, however, still set window.location = 'custom-protocol://my-app';. So if you know that a user has your app because you've previously opened their app from the browser and have a cookie stored that can be looked up on your backend, you can still safely fire custom-protocol://.

首先,您不能再设置iframe src来触发URI方案。您已经正确地确定了这个问题。正如您所指出的,您仍然可以设置窗口。位置=“定制协议:/ / app”;。因此,如果你知道用户有你的应用程序,因为你之前已经从浏览器打开了他们的应用程序,并且有一个可以在你的后端查找的cookie,你仍然可以安全的使用定制的协议://。

Second, you can detect the user agent string using navigator.userAgent. Pre-iOS 9 you can still use the iframe to fire a URI scheme, then fallback after a timeout. On iOS 9, you can choose whether to fire the URI scheme or not based on cookies, then take the user to the App Store. I work on this at Branch and making use of cookies to recall whether a user likely has the app is something we've implemented. Feel free to reach out if you have more questions about that, or make use of our solution directly.

其次,您可以使用navigator.userAgent来检测用户代理字符串。在ios 9之前,您仍然可以使用iframe来触发一个URI方案,然后在超时后返回。在ios9中,您可以选择是否启动URI方案,或者不基于cookie,然后将用户带到App Store。我在分公司工作,利用cookie来回忆用户是否有应用程序是我们已经实现的。如果您有更多的问题,或者直接使用我们的解决方案,请随时联系我们。


Implementing Universal Links is not quite as simple as the other answer describes. In reality, there is considerably more complexity. Here's a complete list of steps (I've helped several apps integrate in recent weeks using these steps):

实现通用链接并不像其他答案所描述的那样简单。实际上,复杂性要大得多。下面是一个完整的步骤列表(最近几周,我通过这些步骤帮助了几个应用程序集成):

1. Configure your app to register approved domains

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

i. Registered your app at developer.apple.com if you haven't

我注册了你在developer。apple。com的应用程序。

ii. Enable ‘Associated Domains’ on your app identifier on developer.apple.com

二世。在开发者的app标识上启用“关联域”。

iii. Enable ‘Associated Domain’ on in your Xcode project

三世。在您的Xcode项目中启用“关联域”。

iOS 9 safari iframe src与自定义url方案不工作。

iv. Add the proper domain entitlement, applinks:yourdomain.com, in your app

4 .在app中添加适当的域名权限,applinks:yourdomain.com。

iOS 9 safari iframe src与自定义url方案不工作。

2. Configure your website to host the ‘apple-app-site-association’ file

2。配置您的网站,以主办“苹果应用-站点-协会”文件。

i. Buy a domain name or pick from your existing

我。买一个域名或从你现有的。

ii. Acquire SSL certification for the domain name (you can use CloudFlare for this!)

二世。获取域名的SSL证书(您可以使用CloudFlare !)

iii. Create structured ‘apple-app-site-association’ JSON file

三世。创建结构化的“apple-app-site-association”JSON文件。

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

iv. Sign the JSON file with the SSL certification

使用SSL证书在JSON文件上签名。

cat apple-app-site-association-unsigned | openssl smime -sign -inkey yourdomain.com.key -signer yourdomain.com.cert -certfile digicertintermediate.cert -noattr -nodetach -outform DER > apple-app-site-association

在你的网站上,你可以看到你的名字。这是苹果公司的产品。

v. Configure the file server

配置文件服务器。

The apple-app-site-association file: - must be sent with the header ‘application/pkcs7-mime’ - must be sent from the endpoint youdomain.com/apple-app-site-association - must return a 200 http code.

苹果应用程序-站点关联文件:-必须通过报头的“应用程序/pkcs7-mime”发送-必须从终点站youdomain.com/apple-app-site-association发送,必须返回200个http代码。

Example 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: borrowed liberally from this blog post

信用:从这篇博客文章中获得*。

#2


1  

Yes with iOS9 now you can deep link. Check the link for detailed explanation but I laid out the basics.

是的,有了iOS9,现在你可以深入链接。检查链接的详细说明,但我列出了基础。

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

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

first you must go to your target and click capabilities. Add the associated domain.

首先,你必须去你的目标和点击能力。添加相关的领域。

Next you must upload apple-app-site-association file.

接下来,您必须上传苹果应用程序-站点关联文件。

Basically open a JSON editor and construct something like this

基本上打开一个JSON编辑器,然后构造这样的东西。

{
  "applinks": {
"apps": [],
"details": {
  "TBEJCS6FFP.com.domain.App": {
    "paths":[ "*" ]
  }
}
  }
}

Next you must support Univeral links in your app. You need to implement

下一步,您必须支持应用程序中的Univeral链接。您需要实现。

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
                }

#1


17  

The previous answer is a partial implementation of Universal Links that is missing critical details and doesn't include a fallback to the App Store.

之前的答案是部分的通用链接的实现,这些链接缺少关键的细节,不包括应用程序商店的回退。

First, you can no longer set iframe src in order to trigger a URI scheme. You've correctly identified that issue. As you noted, you can, however, still set window.location = 'custom-protocol://my-app';. So if you know that a user has your app because you've previously opened their app from the browser and have a cookie stored that can be looked up on your backend, you can still safely fire custom-protocol://.

首先,您不能再设置iframe src来触发URI方案。您已经正确地确定了这个问题。正如您所指出的,您仍然可以设置窗口。位置=“定制协议:/ / app”;。因此,如果你知道用户有你的应用程序,因为你之前已经从浏览器打开了他们的应用程序,并且有一个可以在你的后端查找的cookie,你仍然可以安全的使用定制的协议://。

Second, you can detect the user agent string using navigator.userAgent. Pre-iOS 9 you can still use the iframe to fire a URI scheme, then fallback after a timeout. On iOS 9, you can choose whether to fire the URI scheme or not based on cookies, then take the user to the App Store. I work on this at Branch and making use of cookies to recall whether a user likely has the app is something we've implemented. Feel free to reach out if you have more questions about that, or make use of our solution directly.

其次,您可以使用navigator.userAgent来检测用户代理字符串。在ios 9之前,您仍然可以使用iframe来触发一个URI方案,然后在超时后返回。在ios9中,您可以选择是否启动URI方案,或者不基于cookie,然后将用户带到App Store。我在分公司工作,利用cookie来回忆用户是否有应用程序是我们已经实现的。如果您有更多的问题,或者直接使用我们的解决方案,请随时联系我们。


Implementing Universal Links is not quite as simple as the other answer describes. In reality, there is considerably more complexity. Here's a complete list of steps (I've helped several apps integrate in recent weeks using these steps):

实现通用链接并不像其他答案所描述的那样简单。实际上,复杂性要大得多。下面是一个完整的步骤列表(最近几周,我通过这些步骤帮助了几个应用程序集成):

1. Configure your app to register approved domains

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

i. Registered your app at developer.apple.com if you haven't

我注册了你在developer。apple。com的应用程序。

ii. Enable ‘Associated Domains’ on your app identifier on developer.apple.com

二世。在开发者的app标识上启用“关联域”。

iii. Enable ‘Associated Domain’ on in your Xcode project

三世。在您的Xcode项目中启用“关联域”。

iOS 9 safari iframe src与自定义url方案不工作。

iv. Add the proper domain entitlement, applinks:yourdomain.com, in your app

4 .在app中添加适当的域名权限,applinks:yourdomain.com。

iOS 9 safari iframe src与自定义url方案不工作。

2. Configure your website to host the ‘apple-app-site-association’ file

2。配置您的网站,以主办“苹果应用-站点-协会”文件。

i. Buy a domain name or pick from your existing

我。买一个域名或从你现有的。

ii. Acquire SSL certification for the domain name (you can use CloudFlare for this!)

二世。获取域名的SSL证书(您可以使用CloudFlare !)

iii. Create structured ‘apple-app-site-association’ JSON file

三世。创建结构化的“apple-app-site-association”JSON文件。

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

iv. Sign the JSON file with the SSL certification

使用SSL证书在JSON文件上签名。

cat apple-app-site-association-unsigned | openssl smime -sign -inkey yourdomain.com.key -signer yourdomain.com.cert -certfile digicertintermediate.cert -noattr -nodetach -outform DER > apple-app-site-association

在你的网站上,你可以看到你的名字。这是苹果公司的产品。

v. Configure the file server

配置文件服务器。

The apple-app-site-association file: - must be sent with the header ‘application/pkcs7-mime’ - must be sent from the endpoint youdomain.com/apple-app-site-association - must return a 200 http code.

苹果应用程序-站点关联文件:-必须通过报头的“应用程序/pkcs7-mime”发送-必须从终点站youdomain.com/apple-app-site-association发送,必须返回200个http代码。

Example 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: borrowed liberally from this blog post

信用:从这篇博客文章中获得*。

#2


1  

Yes with iOS9 now you can deep link. Check the link for detailed explanation but I laid out the basics.

是的,有了iOS9,现在你可以深入链接。检查链接的详细说明,但我列出了基础。

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

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

first you must go to your target and click capabilities. Add the associated domain.

首先,你必须去你的目标和点击能力。添加相关的领域。

Next you must upload apple-app-site-association file.

接下来,您必须上传苹果应用程序-站点关联文件。

Basically open a JSON editor and construct something like this

基本上打开一个JSON编辑器,然后构造这样的东西。

{
  "applinks": {
"apps": [],
"details": {
  "TBEJCS6FFP.com.domain.App": {
    "paths":[ "*" ]
  }
}
  }
}

Next you must support Univeral links in your app. You need to implement

下一步,您必须支持应用程序中的Univeral链接。您需要实现。

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
                }