如果已安装应用,则重定向到该应用,否则重定向到App Store。

81

我知道在iOS上可以通过注册自定义方案(例如so://)直接链接到应用程序,也可以通过iTunes链接到应用商店。

在许多情况下,理想的流程是提供一个链接,如果已安装该应用程序,则重定向到该应用程序,否则重定向到商店。这是否可能,如果可能,如何实现?

为了明确情况,场景是我正在iPhone上从电子邮件中打开链接(http),邀请我加入应用程序中的一个组。如果用户在该设备上安装了该应用,则应该打开它,否则http链接应重定向到iTunes。


1
我认为理想的解决方案是,您可以通过一条指令将重定向到itunes链接。类似于:https://itunes.apple.com/us/app/clear/id492134154?mt=8&uo=4&open=true,其中open=true告诉ios应用商店打开该应用... - ConfusedNoob
8个回答

71

我认为更简单的方法是在您的服务器上设置一个页面,其中包含以下Javascript代码:

(function() {
  var app = {
    launchApp: function() {
      window.location.replace("myapp://");
      this.timer = setTimeout(this.openWebApp, 1000);
    },

    openWebApp: function() {
      window.location.replace("http://itunesstorelink/");
    }
  };

  app.launchApp();
})();

这基本上试图重定向到您的应用程序,并设置一个超时时间,如果失败就重定向到应用商店。

你甚至可以让代码更加智能,检查用户代理以确定他们是iOS用户、Android用户还是Web用户,然后适当地将其重定向。


13
如果应用程序未通过此方法安装,则iOS会抛出一个相当不友好的“Safari无法打开页面,因为地址无效”的消息。 - Real World
3
听起来像是iOS 11的一个新添加功能。针对这个话题,我建议使用通用链接。也许值得撰写一篇新答案来概述它的工作原理。 - BananaNeil
3
它过去曾经能够在 iOS 12 上正常运行,但现在不能工作了。我相信可能是出了其他问题,因为它突然停止工作了。 - StealthTrails
2
是的,这在IOS 12之前曾经有效,但现在不幸的是它会同时打开一个应用和链接。 - Jaymin
有什么办法可以解决iOS 12+同时打开应用和链接的问题吗? - manuelgr
显示剩余6条评论

34

无法进行此项检查。

不过,有一个很好的解决方法。

基本思路如下:

  1. 第一次打开您的应用程序时,从您的应用程序内部打开移动Safari,访问预定义的URL在您的服务器上
  2. 在该URL上,向用户的移动Safari设置一个cookie, 如appInstalled
  3. 然后通过已注册的主题(与FB在SSO中使用的相同)将用户带回到您的应用程序
  4. 所有电子邮件链接都指向您的网站,但是在网站上,您可以检查浏览器是否为移动版Safari以及是否存在appInstalled cookie
  5. 如果浏览器不是移动Safari或未找到cookie,则重定向到AppStore,或停留在您的网页中。
  6. 如果#4的条件为真,则将用户重定向到已注册主题的应用程序中
  7. 如果用户删除了应用程序,因此自定义url主题失败,则具有故障转移重定向到AppStore

最后两个步骤在此SO帖子中有详细说明。


1
请注意,在第一步中,我尝试使用应用程序内部的Web视图替换Safari浏览器,但由于它们不共享相同的Cookie存储,因此无法实现。 - Federico
很遗憾,这需要更新 iOS 客户端。 - BananaNeil
当用户从设置中清除网站数据时,这将无法工作。 - Nishad
没有人说这是完美的解决方案,但那时它是最好的可用选择。 - Lefteris
2
这个答案还准确吗?有人知道吗?我看到像BOA和Medium这样的应用程序甚至在没有尝试打开Safari的情况下就打开了! - Mohy Eldeen

16
如果您在电子邮件中链接到一个包含设置了您App的自定义方案的iframe的网页,iOS会自动重定向到该位置。如果该应用程序未安装,则不会发生任何事情。这使您可以深入链接到已安装的应用程序中,或者如果未安装,则重定向到应用商店。
例如,如果您安装了Twitter应用,并导航到包含以下标记的网页,则将立即重定向到该应用程序。如果您没有安装Twitter应用,则会看到文本“未安装Twitter应用程序”。
<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    </head>
    <body>
        <iframe src="twitter://" width="0" height="0"></iframe>
        <p>The Twitter App is not installed</p>
    </body>
</html>

如果应用程序未安装,则以下是一个更详细的重定向到App Store的示例:

<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    <script src='//code.jquery.com/jquery-1.11.2.min.js'></script>
    <script src='//mobileesp.googlecode.com/svn/JavaScript/mdetect.js'></script>
    <script>
      (function ($, MobileEsp) {
        // On document ready, redirect to the App on the App store.
        $(function () {
          if (typeof MobileEsp.DetectIos !== 'undefined' && MobileEsp.DetectIos()) {
            // Add an iframe to twitter://, and then an iframe for the app store
            // link. If the first fails to redirect to the Twitter app, the
            // second will redirect to the app on the App Store. We use jQuery
            // to add this after the document is fully loaded, so if the user
            // comes back to the browser, they see the content they expect.
            $('body').append('<iframe class="twitter-detect" src="twitter://" />')
              .append('<iframe class="twitter-detect" src="itms-apps://itunes.com/apps/twitter" />');
          }
        });
      })(jQuery, MobileEsp);
    </script>
    <style type="text/css">
      .twitter-detect {
        display: none;
      }
    </style>
    </head>
    <body>
    <p>Website content.</p>
    </body>
</html>

仅供记录,这是我们在Syfy.com上正在进行的工作。访问http://www.syfy.com/live,如果您已经安装了应用程序,则会自动将您深入链接到该网站。 - q0rban
这是问题的正确答案。我不是检测页面中的iOS,而是在get请求中检查user-agent标头,并提供重定向页面或一个包含要求用户在iOS设备中打开链接的页面。出于好奇,您是如何知道iframe会以这种方式运作的?找不到iframe HTML文档中的相关信息。 - Carlos Guzman
1
谢谢@CarlosGuzman!我不知道它会这样工作,我只是不断尝试不同的方法直到它成功了! :) - q0rban
那真是个好发现!不幸的是,这在 iOS 8 上似乎不再起作用了。你是否发现在 iOS 8 及更高版本中仍然可以使用它?似乎与苹果阻止 App Store 自动重定向有关。 - Carlos Guzman
1
因为直接从 SVN 存储库下载代码而被踩,存储库所有者可以随时向存储库中推送加密货币挖掘程序。 - sesm

16

“智能应用横幅”- 不确定它们何时出现,但在寻找相同内容后发现本帖子,然后是关于智能应用横幅的跟进。

智能应用横幅是每个页面头部的单行html元标记,用于向用户提供您的应用程序,以便获得更好的网络体验:

<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">

该图标显示在页面顶部,并带有“在应用中打开此页面”或转到App Store的选项。

输入图像描述

iPhone上这个页面的元数据如下(当然是匿名的):

<meta name="apple-itunes-app" content="app-id=605841731, app-argument=lync://confjoin?url=https://meet.rtc.yourcorporatedomain.com/firstName.lastName/conferenceID">

Apple开发者文档 - 使用智能应用横幅宣传应用


10

是的,这很容易。这需要你想要打开的应用程序在plist中声明一个url scheme:

//if you can open your app
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"yourapp://"]])
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"yourapp://"]];
}
else
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"ituneappstorelink"]];
}

抱歉,我的情境可能不太清晰 - 这假设我是从另一个应用程序打开的。在这种情况下,它将通过 HTTP 网络链接从电子邮件或短信中打开 - 因此远程 Web 服务器需要重定向到适当的链接。 - ConfusedNoob
你可能需要链接到一个网页,该网页尝试通过Javascript以相同的方式打开应用程序,如果无法打开,则重定向到iTunes链接。我没有这方面的源代码,但它可以起作用。 - rooster117

5

有几个简单的步骤可以实现此操作

步骤1

进入 -> 项目(选择目标) -> 信息 -> URL类型

enter image description here

在Xcode中创建URL Scheme

在此输入图像描述 这里的URL Scheme是myApp(最好将所有字符都小写)。

步骤2

如果您计划从URL接收参数/查询字符串,请设置委托。

这里是代码:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {

     NSLog(@"APP : simple action %@",url.scheme);

    if ([url.scheme hasPrefix:@"myapp"]) {

        NSLog(@"APP inside simple %@",url.absoluteString);


        NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url
                                                    resolvingAgainstBaseURL:NO];
        NSArray *queryItems = urlComponents.queryItems;
        NSString * abc = [self valueForKey:@"abc"
                           fromQueryItems:queryItems];
        NSString * xyz = [self valueForKey:@"xyz"
                           fromQueryItems:queryItems];


        NSLog(@"Sid up = %@", abc);

        NSLog(@"PID up = %@", xyz);

      // you can do anything you want to do here



        return YES;
    }
return NO;
}

Xcode端工作结束。

第三步

参考@BananaNeil的代码,因为我不是前端开发人员。

(function() {
  var app = {
    launchApp: function() {
      window.location.replace("myApp://share?abc=12&xyz=123");
      this.timer = setTimeout(this.openWebApp, 1000);
    },

    openWebApp: function() {
      window.location.replace("http://itunesstorelink/");
    }
  };

  app.launchApp();
})();

希望这将对你们所有人有所帮助。

@aftab 我尝试了第三步,我想知道你在新版本中是否遇到了任何问题?当我运行这段代码时,发生的情况是应用程序会打开,然后立即打开应用商店。 - Phoenix
@Phoenix 嗯,到目前为止我没有遇到任何问题,但我可以再检查一下,如果有任何问题,我会编辑答案。 - AFTAB MUHAMMED KHAN
@Phoenix,你收到任何相同问题的解决方案了吗? - shikha kochar
@Phoenix,你找到这个的解决方案了吗? - Yogendra Patel

2
这里有许多复杂的边缘情况,所以最简单的解决方案是让其他人处理这些问题。这就是https://branch.io/的作用。您可以使用他们的免费计划来实现您想要的功能,并获得一些额外的功能:
- 统计信息 - 您可以在链接中传递信息,即使用户必须先安装应用程序,也会检索到该信息。 - 链接将在桌面上工作(默认情况下,它将向您的移动设备发送安装链接)
我与Branch.io没有关联,但我确实使用了他们的产品。

2

如果有人仍然被这个问题困扰并需要最简单的解决方案,你会喜欢 node-deeplink

1.) 如果应用已安装:通过深度链接调用应用程序将始终调用根组件的componentDidMount。因此,您可以在那里附加侦听器。例如:

Linking.getInitialURL()
      .then(url => {
        if (url) {
          this.handleOpenURL({ url });
        }
      })
      .catch(console.error);

    Linking.addEventListener('url', this.handleOpenURL);



handleOpenURL(event) {
    if (event) {
      console.log('event = ', event);
      const url = event.url;
      const route = url.replace(/.*?:\/\//g, '');
      console.log('route = ', route);
      if(route.match(/\/([^\/]+)\/?$/)) {
        const id = route.match(/\/([^\/]+)\/?$/)[1];
        const routeName = route.split('/')[0];

        if (routeName === 'privatealbum') {
          Actions.privateAlbum({ albumId: id });
        }
      }
    }
  }

2.) 如果应用程序未安装:只需在您的服务器上设置路由,node-deeplink包将处理当应用程序未安装在您的移动设备上时,从Web浏览器到应用商店的桥接。

通过这种方式,这两种情况都可以轻松处理。


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