ChatGPT解决这个技术问题 Extra ChatGPT

如何检查是否从 iPhone 上的网页安装了应用程序

我想创建一个网页,如果 iPhone 没有安装应用程序,该页面会将 iPhone 重定向到 App Store,但如果 iPhone 安装了应用程序,我希望它打开应用程序。

我已经在 iPhone 应用程序中实现了一个自定义 URL,所以我有一个应用程序的 URL,类似于:

myapp://

如果这个 URL 无效,我希望页面重定向到 App Store。这可能吗?

如果我没有在手机上安装应用程序并在 Safari 中写入 myapp:// URL,我得到的只是一条错误消息。

即使 JavaScript 存在丑陋的 hack,我也很想知道。

这在每个 iOS 版本中都在不断变化——iOS9 再次破坏了一切。我建议您使用 branch.io 之类的服务来为您解决这个问题。我帮助构建了 Branch 链接服务的一部分,它目前处理超过 6000 种不同的重定向边缘情况……太疯狂了。
2017 年,如果您需要通过电子邮件链接到您的应用,您应该看看我的回答:stackoverflow.com/questions/13044805/…

P
Peter Mortensen

据我所知,您无法通过浏览器检查是否安装了应用程序。

但是您可以尝试将手机重定向到应用程序,如果没有任何反应,将手机重定向到指定页面,如下所示:

setTimeout(function () { window.location = "https://itunes.apple.com/appdir"; }, 25);
window.location = "appname://";

如果第二行代码给出结果,则第一行永远不会执行。

类似的问题:

iPhone 浏览器:检查是否从浏览器安装了 iPhone 应用程序

是否可以为 iPhone 应用程序(如 YouTube 和地图)注册基于 http+域的 URL 方案?


目前在 iOS 6.1.2 中,这似乎只在 webapp 模式下有效。如果直接从浏览器使用应用程序,它会按预期打开外部应用程序,但也会触发超时并重定向浏览器。
如果未安装该应用程序,它会抛出一个丑陋的“找不到页面”警报。无论如何我们可以压制它
@AkshatAgarwal,您能否详细说明如何编写代码来抑制“找不到页面警报”
现在在 Android 和 iOS 中都有新的实现方式。查看 Android App LinksiOS Universal Links
它打开应用程序,但还将浏览器重定向到应用商店/播放商店。有什么方法/黑客可以防止这种情况吗?
P
Peter Mortensen

为了进一步接受答案,您有时需要添加额外的代码来处理启动应用程序后返回浏览器的人 - setTimeout 函数将在他们这样做时运行。所以,我做这样的事情:

var now = new Date().valueOf();
setTimeout(function () {
    if (new Date().valueOf() - now > 100) return;
    window.location = "https://itunes.apple.com/appdir";
}, 25);
window.location = "appname://";

这样,如果代码执行中出现冻结(即应用程序切换),它就不会运行。


这个解决方案比其他解决方案好得多,我不得不增加 50 的时间
我关于它在 iOS 7 上失败的评论是错误的:我只需将 100 毫秒增加到几秒钟(实际上不需要那么短)。
代替 itunes.apple.com/appdir,保存一个步骤(无需等待 http 重定向)并直接链接到应用商店 URL 方案。例如:itms://itunes.apple.com/us/app/yelp/id284910350
太棒了,它适用于 ios 应用程序,相同的代码在 android 应用程序中同时重定向到两个 url。你为安卓打开应用程序和游戏商店做过吗?
这始终打开我的应用程序和应用程序商店,即使在 50 岁时也是如此。iOS 12
b
brainjam

iOS Safari 有一项功能,允许您向网页添加“智能”横幅,该横幅将链接到您的应用(如果已安装)或 App Store。

为此,您可以向页面添加一个 meta 标记。如果您希望应用程序在加载时执行一些特殊操作,您甚至可以指定详细的应用程序 URL。

详细信息在 Apple 的 Promoting Apps with Smart App Banners 页面上。

该机制的优点是简单易行,呈现标准化的旗帜。缺点是您无法控制外观或位置。此外,如果该页面是在 Safari 以外的浏览器中查看的,那么所有的赌注都将被取消。


但如果用户没有安装它,它不会显示应用程序横幅
通用链接或智能横幅都不适合我。我需要有多个本机应用程序链接到不同的应用程序。每个都有一个 Check IF Installed,启动它,否则去商店。我也无法控制将所有权文件上传到通用链接的域。所以这两种选择对我来说都是无效的。需要一个纯 JavaScript 解决方案。
I
Imran Rasheed

截至 2017 年,似乎没有可靠的方法来检测是否安装了应用程序,并且重定向技巧不会在任何地方都有效。

对于像我这样需要直接从电子邮件中进行深度链接的人(很常见),值得注意以下几点:

使用 appScheme:// 发送电子邮件将无法正常工作,因为这些链接将在 Gmail 中被过滤

自动重定向到 appScheme:// 被 Chrome 阻止:我怀疑 Chrome 需要重定向与用户交互同步(如点击)

您现在可以在没有 appScheme:// 的情况下进行深度链接,这会更好,但它需要一个现代平台和额外的设置。安卓 iOS

值得注意的是,其他人已经对此进行了深入思考。如果您查看 Slack 如何实现他的“魔术链接”功能,您会注意到:

它发送带有常规 HTTP 链接的电子邮件(可以使用 Gmail)

该网页有一个链接到 appScheme:// 的大按钮(可以使用 Chrome)


P
Peter Mortensen

@Alistair 在 this answer 中指出,有时用户会在打开应用程序后返回浏览器。该答案的评论者表示,必须根据 iOS 版本更改使用的时间值。

当我们的团队不得不处理这个问题时,我们发现初始超时的时间值以及告诉我们是否已经返回浏览器必须进行调整,并且通常不适用于所有用户和设备。

与其使用任意时间差阈值来确定我们是否返回浏览器,不如检测“pagehide”和“pageshow”事件。

我开发了以下网页来帮助诊断发生了什么。它在事件展开时添加了 HTML 诊断,主要是因为使用控制台日志记录、警报或 Web Inspector、jsfiddle.net 等技术在此工作流程中都有其缺点。 JavaScript 不使用时间阈值,而是计算“pagehide”和“pageshow”事件的数量以查看它们是否已发生。我发现最稳健的策略是使用 1000 的初始超时(而不是其他人报告和建议的 25、50 或 100)。

这可以在本地服务器上提供,例如 python -m SimpleHTTPServer 并在 iOS Safari 上查看。

要使用它,请按“打开已安装的应用程序”或“未安装应用程序”链接。这些链接应分别导致地图应用程序或应用程序商店打开。然后,您可以返回 Safari 查看事件的顺序和时间。

(注意:这仅适用于 Safari。对于其他浏览器(如 Chrome),您必须为 pagehide/show-equivalent 事件安装处理程序)。

更新:正如@Mikko 在评论中指出的那样,我们正在使用的 pageshow/pagehide 事件显然在 iOS8 中不再支持。

<html>
<head>
</head>

<body>
<a href="maps://" onclick="clickHandler()">Open an installed app</a>
<br/><br/>
<a href="xmapsx://" onclick="clickHandler()">App not installed</a>
<br/>

<script>
    var hideShowCount = 0 ;
    window.addEventListener("pagehide", function() {
        hideShowCount++;
        showEventTime('pagehide');
    });

    window.addEventListener("pageshow", function() {
        hideShowCount++;
        showEventTime('pageshow');
    });

    function clickHandler(){
        var hideShowCountAtClick = hideShowCount;
        showEventTime('click');
        setTimeout(function () {
                      showEventTime('timeout function ' + (hideShowCount-hideShowCountAtClick) + ' hide/show events');
                      if (hideShowCount == hideShowCountAtClick){
                              // app is not installed, go to App Store
                           window.location = 'http://itunes.apple.com/app';
                      }
                   }, 1000);
    }

    function currentTime()
    {
        return Date.now()/1000;
    }

    function showEventTime(event){
        var time = currentTime() ;
        document.body.appendChild(document.createElement('br'));
        document.body.appendChild(document.createTextNode(time + ' ' + event));
    }
</script>
</body>

</html>

h
hampusohlsson

您可以查看这个试图解决问题的插件。它基于与 misemisa 和 Alastair 等描述的相同方法,但使用隐藏的 iframe。

https://github.com/hampusohlsson/browser-deeplink


我添加了这个,但即使我安装了应用程序,它也会重定向到 Appstore。
P
Peter Mortensen

我需要做这样的事情,我最终选择了以下解决方案。

我有一个特定的网站 URL,它将打开一个带有两个按钮的页面

按钮一进入网站 按钮二进入应用程序(iPhone / Android 手机 / 平板电脑)。如果未安装应用程序(如另一个 URL 或应用程序商店),您可以从此处回退到默认位置 Cookie 以记住用户的选择 Mobile Router Example

  查看我们的新应用或访问网站  
 
  获取移动应用程序 < /span>  
 
 
  访问 Website.com < /span>  
 
 
  ;


我需要这种类型的代码来满足我的要求,但无法放置我的链接。要求:如果安装了 app1,则转到 Link 1,否则转到 Link2。有人可以帮忙吗?
安装应用时需要取消设置 cookie,以防用户 1st 选择 web。
P
Peter Mortensen

在编译了一些答案后,我想出了以下代码。令我惊讶的是,计时器不会在 PC(Chrome 和 Firefox)或 Android Chrome 上冻结 - 触发器在后台工作,可见性检查是唯一可靠的信息。

var timestamp        = new Date().getTime();
var timerDelay       = 5000;
var processingBuffer = 2000;

var redirect = function(url) {
  //window.location = url;
  log('ts: ' + timestamp + '; redirecting to: ' + url);
}

var isPageHidden = function() {
    var browserSpecificProps = {hidden:1, mozHidden:1, msHidden:1, webkitHidden:1};
    for (var p in browserSpecificProps) {
        if(typeof document[p] !== "undefined"){
          return document[p];
      }
    }
    return false; // Actually inconclusive, assuming not
}
var elapsedMoreTimeThanTimerSet = function(){
  var elapsed = new Date().getTime() - timestamp;
  log('elapsed: ' + elapsed);
  return timerDelay + processingBuffer < elapsed;
}

var redirectToFallbackIfBrowserStillActive = function() {
  var elapsedMore = elapsedMoreTimeThanTimerSet();
  log('hidden:' + isPageHidden() + '; time: ' + elapsedMore);
  if (isPageHidden() || elapsedMore) {
    log('not redirecting');
  }else{
      redirect('appStoreUrl');
  }
}

var log = function(msg){
    document.getElementById('log').innerHTML += msg + "<br>";
}

setTimeout(redirectToFallbackIfBrowserStillActive, timerDelay);
redirect('nativeApp://');

JS Fiddle


r
rolinger

以下答案仍然有效,在 iOS 10 到 14 上进行了测试。它建立在早期答案的基础上。我添加了 window.close() 以摆脱重定向或页面返回后留在浏览器中的空标签窗口。如果修复了 4 个场景中的 2 个会留下空白标签的情况....也许其他人可以修复第 3 个 &第 4 名

<script>
var now = new Date().valueOf();
setTimeout(function () {
  // time stamp comaprison prevents redirecting to app store a 2nd time
  if (new Date().valueOf() - now > 100) {
    window.close() ;  // scenario #4
    // old way - "return" - but this would just leave a blank page in users browser
    //return;  
  }
  if (isIOS == 1) {
    // still can't avoid the "invalid address" safari pops up
    // but at least we can explain it to users
    var msg = "'invalid address' = MyApp NOT DETECTED.\n\nREDIRECTING TO APP STORE" ;
  } else {
    var msg = "MyApp NOT DETECTED\n\nREDIRECTING TO APP STORE" ;
  }
  if (window.confirm(msg)) {
    window.location = "<?=$storeUrl?>";
    // scenario #2 - will leave a blank tab in browser
  } else {
    window.close() ;  // scenario #3
  }
}, 50);
window.location = "<?=$mobileUrl?>";  
// scenario #1 - this will leave a blank tab
</script>

R
Ron Regev

我一直试图在 iOS15 的 Safari 扩展中实现相同的目标。似乎所有以前的策略都失败了——“打开方式”对话框和“无效地址”对话框完全相等,都是非阻塞的,因此基于计时器的解决方案提供不一致的结果,具体取决于加载页面所需的时间.

我的解决方法是在模态弹出窗口中创建一个应用商店重定向消息,该消息模仿系统提示的外观,将其隐藏在系统提示后面,并在选项卡失去焦点时使用事件侦听器将其关闭。 UX 还存在两个问题:

没有办法抑制“无效地址”提示。我们所能做的(如果我们不走通用链接路径)就是在之后用我们自己的提示来解释它。如果用户从“打开方式”提示中选择“取消”,他或她仍会看到我们的重定向提示。

以下代码受益于上述答案和用于创建模式弹出窗口的 this SO 代码。

// 更改以下变量以满足您的需要 var my_app_name = "My App"; var my_app_id = "id1438151717" var my_app_scheme = "myapp://do.this" function toggleModal(isModal, inputs, elems, msg) { for (const input of inputs) input.disabled = isModal; modal.style.display = isModal ? “块”:“无”; elems[0].textContent = isModal ?味精:“”; } function myConfirm(msg) { const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled); const modal = document.getElementById("modal"); const elems = modal.children[0].children; return new Promise((resolve) => { toggleModal(true, inputs, elems, msg); elems[3].onclick = () => resolve(true); elems[4].onclick = () => resolve( false); }).then(result => { toggleModal(false, inputs, elems, msg); 返回结果; }); } function redirectMessage() { var r = myConfirm("要下载" + my_app_name + ",点击确定。"); return r.then(ok => { if (ok) { console.log("重定向到 App Store..."); window.location = "itms-apps://itunes.apple.com/app/" + my_app_id; } else { console.log("用户取消重定向到 App Store"); } return ok; }); } function prepareListener() { document.addEventListener("visibilitychange", function() { const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled); const modal = document.getElementById("modal"); const elems = modal.children[0].children; if (!document.hasFocus()) { console.log("用户左选项卡。关闭模式弹出窗口") toggleModal(假,输入,元素,“”);}}); } function onTap() { setTimeout(function() { // 我们无法避免“无效地址”的 Safari 弹窗, // 但至少我们可以向用户解释。 // 我们将在它后面创建一个模态弹窗, // 如果应用程序打开并且我们离开选项卡redirectMessage() }, 50), // 事件监听器将自动关闭; window.location = my_app_scheme; } prepareListener() #modal { 显示:无;位置:固定; z-index:1;左:0;顶部:0;宽度:100%;高度:100%;溢出:自动;背景:rgb(0, 0, 0);背景:rgba(0, 0, 0, 0.4); font-family: "ms sans serif", arial, sans-serif;字体大小:中等;边框半径:15px; } #modal>div { 位置:相对;填充:10px;宽度:320px;高度:60px;边距:0 自动;最高:50%;边距顶部:-45px;背景:白色;边框:2px 开头;边框半径:15px; } #cancel_button { 位置:固定;对:50%;边距右:-95px;底部:50%;边距底部:-32px;填充:0;边框:无;背景:无;颜色:RGB(0、122、255);字体大小:中等;字体粗细:正常; } #ok_button { 位置:固定;对:50%;右边距:-140px;底部:50%;边距底部:-32px;填充:0;边框:无;背景:无;颜色:RGB(0、122、255);字体大小:中等;字体粗细:半粗体; }

点击此处打开应用


P
Peter Mortensen

日期解决方案比其他解决方案要好得多。我不得不像这样将时间增加到 50。

这是一个推特示例:

// On click of your event handler...
var twMessage = "Your Message to share";
var now = new Date().valueOf();
setTimeout(function () {
   if (new Date().valueOf() - now > 100) 
       return;
   var twitterUrl = "https://twitter.com/share?text=" + twMessage;
   window.open(twitterUrl, '_blank');
}, 50);
window.location = "twitter://post?message=" + twMessage;

移动 iOS Safari 上的唯一问题是您没有在设备上安装该应用程序,因此 Safari 会显示一个警报,在打开新 URL 时自动关闭。无论如何,这是一个很好的解决方案!


@AkshatAgarwal,因为这与 alastair 7 天后发布的解决方案相同
P
Peter Mortensen

我没有阅读所有这些答案,但您可能正在使用 iframe 并将源添加到“my app://whatever”。

然后定期检查页面的设置间隔是否为404。

您也可以使用 Ajax 调用。如果有 404 响应,则表示未安装该应用程序。


这不是 woking 解决方案。