I'm struggling on solving a really annoying issue for android. We are running our PWA inside of a webview - that's how websites can be ported to android apps. I'm trying to solve the issue with detecting if it's running inside of a webview on android - if it is it shouldn't display "use app" button and cookie bar etc. The old android versions just refuses to detect this - hence still showing the button. Only the new ones detect it, android 11 etc.
Have used the following NPM package that is supposed to detect it but still to no success.
2 Answers
I faced the same problem. This package is-ua-webview is quite old (the last update was about 2 years ago) and I suggest it doesn't work in the right way.
I don't know why, but the author tries to detect WebView by 0.0.0 version.
'Android.*(wv|.0.0.0)', But as you can see in many sources there are combinations with devices and browsers that have Android.*.0.0.0 string in the User-Agent, but it's still not WebView, it's a mobile browser.
For example, this is the User-Agent string in Mobile Chrome browser on Samsung Galaxy S21 (Android 12) Mozilla/5.0 (Linux; Android 12; SM-G996B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36. It contains Android.*102.0.0.0 and this package defines this browser as a WebView.
Actually, I can't find how the .0.0.0 ending binds with the WebView (maybe just this: , but it's an article of 2014 year), but I found this helpful article about detecting WebView: Developer Chrome - webview user agent
We need to check Version/_X.X_ (Version/4.0 for example) in our User-Agent string. Even in this article was said:
Don't rely on the specific Chrome version number (for example, 30.0.0.0) as the version numbers changes with each release
Actually whole code of is-ua-webview package looks like this:
const rules = [ // if it says it's a webview, let's go with that 'WebView', // iOS webview will be the same as safari but missing "Safari" '(iPhone|iPod|iPad)(?!.*Safari)', // Android Lollipop and Above: webview will be the same as native but it will contain "wv" // Android KitKat to lollipop webview will put {version}.0.0.0 'Android.*(wv|.0.0.0)', // old chrome android webview agent 'Linux; U; Android' ] var webviewRegExp = new RegExp('(' + rules.join('|') + ')', 'ig') module.exports = function isWebview(ua) { return !!ua.match(webviewRegExp) } We can just replace the 'Android.*(wv|.0.0.0)', string to new 'Version/[0-9]\.[0-9]' according to this article Developer Chrome - webview user agent
Final solution:
const rules = [ // if it says it's a webview, let's go with that 'WebView', // iOS webview will be the same as safari but missing "Safari" '(iPhone|iPod|iPad)(?!.*Safari)', // 'Android.*Version/[0-9]\.[0-9]', // Also, we should save the wv detected for Lollipop // Android Lollipop and Above: webview will be the same as native but it will contain "wv" 'Android.*wv', // old chrome android webview agent 'Linux; U; Android' ] var webviewRegExp = new RegExp('(' + rules.join('|') + ')', 'ig') module.exports = function isWebview(ua) { return !!ua.match(webviewRegExp) } By the way, as I understood sometimes the user can see the whole functionality of the Chrome browser in WebView:
I hope it helps you. Thanks
you can explicitly set the agent string of the webview in your app to a unique string, and detect that agent string on your web app side. webview.getSettings().setUserAgentString("my-webview-agent-string");
6