在 Android Stock Browser 上将 Web 应用程序 运行 检测为主屏幕应用程序
Detect web app running as homescreen app on Android Stock Browser
我们正在构建一个必须用作独立/主屏幕应用程序的网络应用程序。在 Chrome 和 Safari 中,我们可以检测它是从浏览器还是从具有 window.navigator.standalone
或 window.matchMedia('(display-mode: standalone)')
的类似本机的浏览器容器中查看的。这两个选项似乎都不适用于默认的 Android stock browser/Samsung Internet。此外,我们也无法在 manifest.json 中使用 start_url
,因为我们需要将令牌传递给每个用户唯一的主屏幕应用程序。
是否可以检测在使用 android stock 浏览器添加应用程序时是否从主屏幕打开该应用程序?
相关
- 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
据我所知,无法直接检测应用程序在三星浏览器中是 运行,还是在三星浏览器中作为独立应用程序。我能找到的唯一区别是 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 设置清单文件在技术上不受支持,当您以这种方式创建清单文件时,您的应用将永远不会安装为 Web apk。 Firefox 根本不支持动态生成的清单文件,而 ios 缓存清单文件本身可能会导致问题。 Chrome devtools 也不会总是显示清单文件中的内容。以下部分来自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
不会 "fix" 三星浏览器的错误。它永远不会将显示模式设置为浏览器以外的任何模式,因此也无法通过这种方式检测到它。
这就是我今晚想到的,我的头撞到了所有 "solutions" 我发现到处都是不起作用的东西。我的理论是任何 phone 上的任务栏都是 30px 或更少,所以从屏幕高度减去 html 的内部高度,如果剩下 30px 或更少,创建全屏规则, 例如...
var flScrn = (screen.height - innerHeight );
if (flScrn < 30) {
$('.installprompt').css("display","none");
}
我遇到了同样的问题。在清单的 start_url 参数中提供参数的所有解决方案都不起作用,因为:
- 清单 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 Stock 浏览器(在 Samsung Galaxy S7 Edge 上试过):
在清单中,为 PWA 指定一个唯一的开始 url(因为 url 参数将被忽略):
...
"start_url": "/pwa_start",
...
在 start_url 中定义的页面上,使用这样的 url 参数提供到您要调用的实际页面的重定向([= 中的示例55=]):
<?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 class。通过这种方式,您可以创建和使用 css class 等 "hidden-pwa" 或 "visible-pwa" 来在 PWA 和浏览器中显示不同的内容。
我们正在构建一个必须用作独立/主屏幕应用程序的网络应用程序。在 Chrome 和 Safari 中,我们可以检测它是从浏览器还是从具有 window.navigator.standalone
或 window.matchMedia('(display-mode: standalone)')
的类似本机的浏览器容器中查看的。这两个选项似乎都不适用于默认的 Android stock browser/Samsung Internet。此外,我们也无法在 manifest.json 中使用 start_url
,因为我们需要将令牌传递给每个用户唯一的主屏幕应用程序。
是否可以检测在使用 android stock 浏览器添加应用程序时是否从主屏幕打开该应用程序?
相关
- 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
据我所知,无法直接检测应用程序在三星浏览器中是 运行,还是在三星浏览器中作为独立应用程序。我能找到的唯一区别是 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 设置清单文件在技术上不受支持,当您以这种方式创建清单文件时,您的应用将永远不会安装为 Web apk。 Firefox 根本不支持动态生成的清单文件,而 ios 缓存清单文件本身可能会导致问题。 Chrome devtools 也不会总是显示清单文件中的内容。以下部分来自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
不会 "fix" 三星浏览器的错误。它永远不会将显示模式设置为浏览器以外的任何模式,因此也无法通过这种方式检测到它。
这就是我今晚想到的,我的头撞到了所有 "solutions" 我发现到处都是不起作用的东西。我的理论是任何 phone 上的任务栏都是 30px 或更少,所以从屏幕高度减去 html 的内部高度,如果剩下 30px 或更少,创建全屏规则, 例如...
var flScrn = (screen.height - innerHeight );
if (flScrn < 30) {
$('.installprompt').css("display","none");
}
我遇到了同样的问题。在清单的 start_url 参数中提供参数的所有解决方案都不起作用,因为:
- 清单 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 Stock 浏览器(在 Samsung Galaxy S7 Edge 上试过):
在清单中,为 PWA 指定一个唯一的开始 url(因为 url 参数将被忽略):
... "start_url": "/pwa_start", ...
在 start_url 中定义的页面上,使用这样的 url 参数提供到您要调用的实际页面的重定向([= 中的示例55=]):
<?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 class。通过这种方式,您可以创建和使用 css class 等 "hidden-pwa" 或 "visible-pwa" 来在 PWA 和浏览器中显示不同的内容。