检测在 Android 股票浏览器上作为主屏幕应用程序运行的 Web 应用程序
Posted
技术标签:
【中文标题】检测在 Android 股票浏览器上作为主屏幕应用程序运行的 Web 应用程序【英文标题】:Detect web app running as homescreen app on Android Stock Browser 【发布时间】:2019-04-22 01:05:45 【问题描述】:我们正在构建一个必须用作独立/主屏幕应用程序的网络应用程序。在 Chrome 和 Safari 中,我们可以使用window.navigator.standalone
或window.matchMedia('(display-mode: standalone)')
检测它是从浏览器还是从类似本机的浏览器容器中查看的。这两个选项似乎都不适用于默认的 android 股票浏览器/三星 Internet。此外,我们也无法在 manifest.json 中使用 start_url
,因为我们需要将令牌传递给每个用户唯一的主屏幕应用程序。
在使用安卓股票浏览器添加应用时,是否可以检测是否从主屏幕打开应用?
相关
Check if web app is added to home screen on Android(仅适用于 Android 上的 chrome) Detect if page is viewed in samsung stock browser or as a standalone web app(未答复) Bug report: Does not detect the display-mode style【问题讨论】:
嗯....三星互联网是否支持您的manifest.json
?除非您专门针对三星手机,否则我希望它们中的大多数都安装了 Chrome 或 Firefox——否则,看起来您在这里无能为力。你能扩展你的start_url
挂断吗?为什么不能用 user_token=xxx&pwa=true
生成清单,然后用 javascript 解析出来?
用户收到一封包含用户令牌链接的电子邮件。这意味着用户令牌当时仅在客户端知道。从技术上讲,我可以在服务器端使用 php 从查询字符串中获取用户令牌,并在客户端请求时以自定义 manifest.json 将其返回 - 或者更可怕的是,设置一个 cookie,然后将其发送回manifest.json 调用。这两种选择都不是很好 - 或者我认为非常可靠。目前 manifest.json 对所有用户都是相同的。
可能是您最好的选择,仅在用户登录后包含您的清单并将其包含在您的 start_url
中,假设令牌是永久性的,因为您将无法启动已安装的网络应用程序来自电子邮件链接。
任何支持你的清单的东西都应该支持matchMedia
。所以我猜三星/原生安卓网络只是在创建一个书签式的快捷方式?显然不是这里的专家,希望有经验的人可以补充一下。
有趣的是,它不是一个书签,因为如果是它,它就会有地址栏。浏览器的显示模式设置存在错误,这导致了我们遇到的问题,但除此之外我还没有发现太多其他问题。
【参考方案1】:
据我所知,无法直接检测应用程序是在三星浏览器中运行,还是作为三星浏览器中的独立应用程序运行。我能找到的唯一区别是window.innerHeight
,因为它不包括地址栏。使用window.screen.height
可以计算出一个比率。由于此浏览器可以在许多不同的设备上使用,这不一定对您有帮助。 window.innerHeight
对于独立应用程序应该更大,但您不一定知道独立应用程序与浏览器体验相比有多大。
// Imperfect solution
if ((window.innerHeight / window.screen.height) > 0.9)
// Some probability of this being a standalone app.
我发现的另一种解决方案是通过 javascript 设置清单文件,允许我们在启动 url 中为每个单独的用户设置唯一令牌。这种方法有几个缺点。通过 javascript 设置清单文件在技术上是不受支持的,当您以这种方式创建清单文件时,您的应用将永远不会安装为网络 apk。 Firefox 根本不支持动态生成的清单文件,而 ios 会缓存清单文件,这可能会自行导致问题。 Chrome 开发工具也不会总是显示清单文件中的内容。以下部分来自this medium article。
// This approach has many caveats. Be aware of all of them before using this solution
import manifestBase from '../manifest.json';
const myToken = window.localStorage.getItem('myToken');
const manifest = ...manifestBase ;
manifest.start_url = `$window.location.origin?standalone=true&myToken=$myToken`;
const stringManifest = JSON.stringify(manifest);
const blob = new Blob([stringManifest], type: 'application/json');
const manifestURL = URL.createObjectURL(blob);
document.querySelector('meta[rel=manifest]').setAttribute('href', manifestURL);
您可以通过将清单元标记的 href
属性设置为合理的默认值来解决 FireFox 的问题。如果您的唯一信息经常更改.. 甚至根本更改,您将无法在 ios 中解决问题。如果您的起始 url 不是动态的,则根本不要通过 javascript 设置清单文件,而是使用一些信息(例如上面的 standalone=true
查询字符串)设置起始 url,以便您将独立应用程序与浏览器 url 区分开来.
我发现的另一件事是,将浏览器模式设置为其他任何值,例如 fullscreen
并不能“修复”三星浏览器的错误。它永远不会将显示模式设置为浏览器以外的任何东西,因此也无法检测到它。
【讨论】:
【参考方案2】:这是我今晚想出的,在我用头撞了我在整个地方找到的所有“解决方案”之后,这些“解决方案”根本不起作用。我这里的理论是,任何手机上的任务栏都是 30px 或更小,所以从屏幕高度中减去 html 的内部高度,如果剩下 30px 或更小,则创建全屏规则,例如...
var flScrn = (screen.height - innerHeight );
if (flScrn < 30)
$('.installprompt').css("display","none");
【讨论】:
【参考方案3】:我遇到了同样的问题。在清单的 start_url 参数中提供参数的所有解决方案都不起作用,因为:
manifest 的 start_url 中的参数将被忽略(没有找到记录的位置,但在我的所有测试中都是这种情况) 如果 url 参数仍然传递给 PWA,在 Android 上的 Chrome 中,您无法将该值存储在 cookie 中以仅可用于 PWA,因为 PWA 的 cookie 将与浏览器共享为此处描述:[如何使用独立浏览器分离 PWA 会话和 cookie?][1] [1]:How to separate PWA session and cookie with a standalone browser? ( PWA as private tab )
(忘记使用子域或类似的东西尝试变通办法,因为 PWA 只能在安装它的同一个域上工作)。
我想出了一个也适用于 Android 股票浏览器的解决方法(在三星 Galaxy S7 Edge 上试用过):
在清单中,为 PWA 指定一个唯一的起始 url(因为 url 参数将被忽略):
...
"start_url": "/pwa_start",
...
在 start_url 中定义的页面上,使用这样的 url 参数提供到您要调用的实际页面的重定向(php 中的示例):
<?php header('location: /?is_pwa=1'); ?>
使以下 javascript 函数成为您用来检查网站是否作为 PWA 运行的唯一方法,并确保它在您网站的所有页面上都可用,并且在页面上至少被调用一次您正在重定向到:
// Return true if the website is currently running as PWA-App, otherwise false
function isPWA()
// Try default method (only true if supported and running as PWA)
if (window.matchMedia('(display-mode: standalone)').matches) return true;
// Alternative method:
if (!(window.sessionStorage || false)) return false; // Session storage not supported
if (self.location.href.indexOf('?is_pwa=1') >= 0)
window.sessionStorage.setItem('isPWA', '1');
return window.sessionStorage.getItem('isPWA') == '1';
如果页面作为 PWA 运行,您可以使用 javascript 进一步将 css 类添加到您的
-tag 中。通过这种方式,您可以创建和使用诸如“hidden-pwa”或“visible-pwa”之类的 css 类来在 PWA 和浏览器中显示不同的内容。【讨论】:
以上是关于检测在 Android 股票浏览器上作为主屏幕应用程序运行的 Web 应用程序的主要内容,如果未能解决你的问题,请参考以下文章