通过 JavaScript 打开应用程序 (iOS/Android),后备重定向到 App/Play 商店(2016 版)

Open an app (iOS/Android) via JavaScript, with a fallback redirect to App/Play store (2016 edition)

给定:网站、iOS 和 Android 应用程序、已注册的 urlscheme "myapp://"。

目标:在网站上向 iOS/Android 台安装了应用程序的设备显示 link。单击 link 应打开应用程序并调用特定逻辑(由应用程序处理,本质上类似于来自苹果的 "universal links",但不会隐藏网站 links)。

由于安全限制,如果没有 webview cookie 魔术,检测应用程序是否已安装会很麻烦。鉴于此,尝试通过 JavaScript 打开应用程序并在失败时调用回退重定向的最佳方法是什么?

来自该线程的解决方案: 不适用于 iOS10。不确定 Android。

在 2016 年,仅靠 Javascript 是不可能实现的

您仍然可以在 Android 上使用该方法,但 Apple 在 iOS 9.2 中进行了更改,这意味着这在 iOS 设备上基本上没有用。


它过去是如何工作的 iOS

过去的做法是尝试通过将 window.location 设置为您想要的自定义 URI 路径来在 Javascript 中打开应用程序。

window.location = “imdb://title/tt3569230”;

应用未安装

问题是当应用程序未安装时,它会显示“无法打开页面”错误。我相信你们都看过了。这是深度 linking 的祸根。 iOS 7和iOS 8期间曾有过一段辉煌的时期,可以绕过这个,但黄金时代已经过去了。

为了避免这种情况,您必须在您的页面中添加一些 Javascript,以便您重定向到 App Store。这样,用户就不会在屏幕上留下错误。

window.location = 'imdb://title/tt3569230';
setTimeout(function() {
  window.location = 'itms-apps://itunes.apple.com/us/app/imdb-movies-tv/id342792525'
}, 250);

已安装应用程序

应用程序安装后,会显示以下模态,提示用户是否要打开应用程序:

现在发生的事情是,在 iOS 9 中,Apple 将 Open in "[app]" 模式从 Javascript blocking 模态到 non-blocking 模态。这意味着当您尝试通过 Javascript 重定向到自定义 URI 方案打开应用程序时,模态将不再阻止 Javascript 执行,因此回退重定向到 App Store 将在用户点击 'Open' 按钮.

之前立即执行

Branch.io(全面披露:我在 Branch 团队),我们在 iOS 9.2 测试版中看到了这一点,并希望我们的 Apple 雷达(错误报告)和有影响力的合作伙伴可以激励 Apple 在发布前解决它。不幸的是,对于 iOS 开发人员来说,事实并非如此。 Apple 对我们的担忧的回应非常清楚地表明了他们希望每个人都做的事情:采用通用链接。


2016 年解决方案

让单一 link 随处可用的唯一方法(包括路由到已安装的应用程序或未安装的后备 Web URL)必须包括在 iOS 上使用通用链接.当然,iOS 中并非所有地方都支持通用链接,因此在特定的边缘情况下仍然需要自定义 URI 方案(Chrome 和 Gmail 是两个重要的例子)。您需要检测这些并构建自定义处理。

大多数公司没有资源来为此投入一名 full-time 名工程师(或两名),这就是为什么 Pinterest、Tinder、Airbnb、Jet.com、Yummly 等拥有全部采用 linking 平台,例如 Branch.io 或 Firebase 动态链接。

所以它在 ios 上的工作方式是在安装应用程序时不总是打开商店,就像这样:

function isIOS() {
    const iDevices = [
        'iPad Simulator',
        'iPhone Simulator',
        'iPod Simulator',
        'iPad',
        'iPhone',
        'iPod'
    ];

    if (navigator.platform) {
        while (iDevices.length) {
            if (navigator.platform === iDevices.pop()) {
                return true;
            }
        }
    }

    return false;
}

let openedApp = false;

function openAppOrStore() {
    setTimeout(function () {
        if (!openedApp) {
            window.location = "https://apps.apple.com/us/app/petleo/id1462882016";
        }
    }, 25);
    const parts = window.location.href.split('/');
    const consultationId = parts[parts.length - 2];
    const iosLink = "petleo://consultations/" + consultationId;
    try {
        window.location = iosLink;
        if (window.location.href.indexOf("petleo://") !== -1) {
            openedApp = true;
        }
    } catch (e) {   
    }
}

setTimeout(function () {
    if (window.location.href.indexOf('consultation') !== -1) {
        if (isIOS()) {
            openAppOrStore();
        }
    }
}, 25);