有没有办法检测扩展是不是在 iPad 和 iPhone 上运行
Posted
技术标签:
【中文标题】有没有办法检测扩展是不是在 iPad 和 iPhone 上运行【英文标题】:Is there a way to detect if extension is running on iPad vs iPhone有没有办法检测扩展是否在 iPad 和 iPhone 上运行 【发布时间】:2021-12-29 00:39:34 【问题描述】:我正在将扩展程序从 Chrome/Firefox 移植到 ios 上的 Safari。当扩展弹出窗口出现时,iOS 上的 Safari 上有两种不同的行为。在 iPhone 上,它从屏幕底部以全屏宽度菜单的形式出现。在 iPad 上,它的行为与 MacOS 上的 Safari 类似,并且弹出窗口从工具栏中的扩展图标下拉,并且是动态大小的。
我想在我的 javascript 代码中检测这两种不同的情况。在前一种情况下,我想避免设置弹出窗口的宽度(因为这会导致问题),在后一种情况下,我确实想设置宽度(就像我在 Chrome 等中所做的那样)。
我不确定这是否是检测 iPad 与 iPhone 的案例(但我很想知道如何做到这一点)。可能有一个屏幕尺寸足够大的 iPhone 会导致它使用后一种行为。
【问题讨论】:
所以window.navigator.userAgent
没有区别?
@matt 过去我发现这对于确定 ipad 与 iphone 是不可靠的。不过最近情况可能发生了变化
可以使用用户代理来确定 iPhone 还是 iPad。以下是我进行的一些快速测试: Mac 上的 Chrome:Mozilla/5.0(Macintosh;Intel Mac OS X 10_15_7)AppleWebKit/537.36(Khtml,如 Gecko)Chrome/96.0.4664.93 Safari/537.36 iPad Pro 12.9 英寸第 5 代 iOS 15模拟器:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) 版本/15.0 Safari/605.1.15 iPhone8 iOS 15.0 模拟器:Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1
因此可能有人可以在字符串中搜索“iPhone”。但是,正如 justinw 指出的那样,它在 iPad 上的拆分视图中可以表现得像 iPhone。所以我现在正在寻找一个测试,它会告诉我弹出窗口是否从底部以全窗口宽度出现
@Namaste 还请记住,如果用户请求网站的桌面版本,它可能不会显示在用户代理中的 iPad
或 iPhone
【参考方案1】:
虽然通过使用browser.runtime.getPlatformInfo()
来确定 macOS 与 iOS 相当简单,但确定 iOS 与 iPadOS 则更加困难。
当扩展弹出窗口出现时,iOS 上的 Safari 上有两种不同的行为。在 iPhone 上,它从屏幕底部以全屏宽度菜单的形式出现。在 iPad 上,它的行为类似于 MacOS 上的 Safari,并且弹出窗口从工具栏中的扩展图标下拉,并且是动态大小的。
请记住,在 iPadOS 上,当浏览器处于拆分视图时,弹出窗口也可以像在 iOS 上一样显示。因此,跟踪window resize events 并在所有拆分视图大小中测试弹出窗口进出拆分视图非常重要。
我发现唯一完整的解决方案是结合使用 Swift、Javascript 和 CSS。
Swift 方面
在您的 WebExtension 或任何您喜欢的地方,您可以创建一个简单的函数来返回您所在的平台。我在browser.runtime.getPlatformInfo()
上使用它,因为后者无法区分 iOS 和 iPadOS。比如:
func getPlatform() -> String
var platform:String
#if os(iOS)
if UIDevice.current.userInterfaceIdiom == .pad
platform = "ipados"
else
platform = "ios"
#elseif os(macOS)
platform = "macos"
#endif
return platform
为了与您的应用程序的 swift 端进行通信,您需要使用 native messaging from the javascript side - 并将适当的消息处理程序放在您的 swift 端。
background.js
browser.runtime.sendNativeMessage(name: "getPlatformFromSwiftSide", response =>
if (response.platform === "ipados")
...
else if (response.platform === "ios")
...
);
SafariWebExtensionHandler.swift
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling
func beginRequest(with context: NSExtensionContext)
let item = context.inputItems[0] as? NSExtensionItem
let message = item?.userInfo?[SFExtensionMessageKey] as? [String: Any]
guard let name = message?["name"] as? String else return
let response = NSExtensionItem()
if name == "getPlatformFromSwiftSide"
let platform = getPlatform()
response.userInfo = [SFExtensionMessageKey: ["platform": platform]]
context.completeRequest(returningItems: [response], completionHandler: nil)
此时您可以区分 iPadOS 和 iOS。但是,您仍然存在浏览器是否处于拆分视图中的问题。如前所述,对于拆分视图中的某些尺寸,iPadOS 上的弹出窗口布局不同,您必须考虑到这一点。
目前,除了 CSS 媒体查询或 Javascript matchMedia
调用之外,我不知道有任何方法可以轻松确定这一点。
此外,从弹出窗口调用window
(或在弹出窗口上下文中使用媒体查询)不会指示浏览器的大小,而是指示弹出窗口。由于我们不知道浏览器的大小来确定如何调整弹出窗口的大小,我知道的唯一可靠的方法是使用browser.tabs.sendMessage
,向内容脚本发送一条消息,请求浏览器window
大小。
所有这一切似乎都比它需要的复杂,但我知道目前没有其他替代方案。
【讨论】:
谢谢。那里有很多有用的信息。我不知道拆分视图。我刚刚在模拟器中针对 iPad Pro 12.9 英寸(第 5 代)和 iPad Air 第 4 代测试了我的扩展。我在这两种情况下都进行了拆分视图,但在这两种情况下,扩展图标仍然显示在 URL 栏中,并且弹出窗口从顶部向下。所以我还没有找到弹出窗口在 iPad 上表现得像 iPhone 的情况。您知道实现这一目标的方法吗? 没关系 - 我找到了办法。在任一 iPad 上,如果它处于纵向模式并使用拆分视图,则弹出菜单的行为就像在 iPhone 上一样。同样在横向模式下,拆分视图中的窗口顶部有一个“...”,它有一个菜单,可让您使一个拆分窗格小于另一个。这会导致类似 iPhone 的弹出窗口。 @Namaste 还请记住,您可以重新调整拆分视图的大小,因此在横向视图中,您可以将其设为四分之一宽度,而不是一半宽度。如果您认为它为您提供了足够的解决方案,请不要忘记接受答案 接受了答案,因为它回答了标题问题,还为我提供了很多有用的信息。我为我的实际问题找到了一个不同的解决方案,即确定扩展弹出窗口是否是从屏幕底部出现的固定宽度窗口。我的解决方案是先测试platformOS是否为ios。如果是这样,那么设置一个 onresize 处理程序。在第一个 onresize 调用中,我测试了 window.outerWidth 并可以使用它来确定这是否是一个固定宽度的菜单。在我的扩展中,如果 outerWidth以上是关于有没有办法检测扩展是不是在 iPad 和 iPhone 上运行的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在我正在开发的网站中检测 iPadOS/iPad 设备?