List icon 目录

发布日期 2019年7月30日

JxBrowser 7.1

全新的 JxBrowser 7.1 版本来啦!

在此更新中,我们专注于恢复暂时放弃的功能并扩展当前功能以提供新的可能性。

拦截鼠标和键盘事件

现在,您可以使用以下回调函数在鼠标和键盘事件发送到网页之前拦截这些事件

  • EnterMouseCallback
  • ExitMouseCallback
  • MoveMouseCallback
  • MoveMouseWheelCallback
  • PressKeyCallback
  • PressMouseCallback
  • ReleaseKeyCallback
  • ReleaseMouseCallback
  • TypeKeyCallback

以下示例展示了如何禁用鼠标滚轮:

browser.set(MoveMouseWheelCallback.class, params -> Response.suppress());

您可以使用这些回调函数来获取关于鼠标和键盘事件的通知,以便在您的应用程序中实现快捷键功能。

访问网页的位图

现在,您可以获取包含当前加载的网页像素的位图,该位图具有当前的 Browser 大小。以下示例演示如何获取位图、将其转换为 Java AWT 和 JavaFX 图像,并将其保存为 PNG 文件:

Swing

// 创建并运行 Chromium Engine。
Engine engine = Engine.newInstance(
        EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
Browser browser = engine.newBrowser();
// 调整 Browser 到所需的尺寸。
browser.resize(500, 500);
// 加载所需的网页并等待其完全加载。
browser.navigation().loadUrlAndWait("https://www.google.com");
// 获取当前加载的网页的位图。其大小将与当前 Browser 的大小相同。
Bitmap bitmap = browser.bitmap();
// 将位图转换为 java.awt.image.BufferedImage。
BufferedImage bufferedImage = BitmapUtil.toBufferedImage(bitmap);
// 将图像保存为 PNG 文件。
ImageIO.write(bufferedImage, "PNG", new File("bitmap.png"));

JavaFX

// 创建并运行 Chromium Engine。
Engine engine = Engine.newInstance(
        EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
Browser browser = engine.newBrowser();
// 调整 Browser 到所需的尺寸。
browser.resize(500, 500);
// 加载所需的网页并等待其完全加载。
browser.navigation().loadUrlAndWait("https://www.google.com");
// 获取当前加载的网页的位图。其大小将与当前 Browser 的大小相同。
Bitmap bitmap = browser.bitmap();
// 将位图转换为 javafx.scene.image.Image。
Image image = BitmapUtil.toImage(bitmap);
// 将 javafx.scene.image.Image 转换为 java.awt.image.BufferedImage。
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
// 将图像保存为 PNG 文件。
ImageIO.write(bufferedImage, "PNG", new File("bitmap.png"));

JavaScript-Java 桥接

@JsAccessible

现在,@JsAccessible 注解可以用于类上。这意味着,被 @JsAccessible 注解标记的注入 Java 对象的所有公共方法都可以从 JavaScript 访问。

自动类型转换

我们改进了 JavaScript-Java 桥接功能,并在从 JavaScript 调用注入 Java 对象的公共方法时引入了自动类型转换。在 V7.0 中,JavaScript 的 Number 只能转换为 Java 的 Double

现在,该库会自动将给定的 JavaScript Number 转换为所需的 Java 类型**(如果可能的话)**。如果检测到给定的数字不能在没有数据丢失的情况下转换为例如 Java 的 byte,那么库会抛出异常,并通知 JavaScript 没有适当的 Java 方法。如果给定的值可以在没有数据丢失的情况下转换,那么库会进行转换并调用适当的 Java 方法。

例如,如果您将以下 Java 对象注入到 JavaScript 中:


@JsAccessible
public final class JavaObject {

    public int method(int intValue) {
        return intValue;
    }
}

然后您可以从 JavaScript 调用它,并传递可以转换为 Number 的 JavaScript Integer 值,而不会丢失数据:

window.javaObject.method(123);

但是,如果您传递的 Double 值无法在没有数据丢失的情况下转换为 Integer,则会出现错误:

window.javaObject.method(3.14); // <- 错误

JsFunctionCallback

JavaScript-Java 桥接允许您将 Java 对象或原始值与 JavaScript 属性关联。现在,您可以将 JsFunctionCallback 与 JavaScript 属性关联,该属性将被视为可在 JavaScript 代码中调用的函数。

例如,您可以使用以下代码注册与 JsFunctionCallback 实例关联的 JavaScript 函数:

JsObject window = frame.executeJavaScript("window");
if (window != null) {
    window.putProperty("sayHello", (JsFunctionCallback) args ->
            "Hello, " + args[0]);
}

现在在 JavaScript 中,您可以按以下方式调用这个函数:

window.sayHello('John');

了解更多

WebStorage API

您可以直接从 Java 代码访问并处理本地存储(Local Storage)和会话存储(Session Storage):

WebStorage localStorage = frame.localStorage();
localStorage.putItem("car", "BMW");
localStorage.clear();

了解更多

远程调试 URL

在 7.1 版本中,我们恢复了允许获取特定 Browser 实例加载的网页的远程调试 URL 的功能。以下示例演示了如何实现:

browser.devTools().remoteDebuggingUrl().ifPresent(url -> {});

JFXPanel

JxBrowser 为 Swing 和 JavaFX 应用程序提供了两个 BrowserView 组件。我们建议您在 Swing 应用程序中使用 Swing 的 BrowserView,在 JavaFX 应用程序中使用 JavaFX 的 BrowserView

有时您可能需要将 JavaFX BrowserView 嵌入到 Swing 应用程序中。例如,如果您使用 JavaFX UI Toolkit 开发复杂的 Web Browser 控件,并且必须在 Swing/AWT 应用程序中显示此 JavaFX 控件。

现在您可以通过 JFXPanel 将 JavaFX 的 BrowserView 嵌入到 Swing/AWT 窗口中。这在所有支持的平台和所有渲染模式下都得到支持。

选择媒体设备

如果您的环境中存在多个网络摄像头和麦克风,并且某个网页想要使用其中之一,您可以使用 SelectMediaDeviceCallback 来告知网页应该使用哪个设备。

以下示例展示了如何在可用设备列表中选择第一个设备:

engine.mediaDevices().set(SelectMediaDeviceCallback.class, params ->
        Response.select(params.mediaDevices().get(0)));

如果您想禁止网页访问您的麦克风或网络摄像头,您可以使用 RequestPermissionCallback,如下所示:

engine.permissions().set(RequestPermissionCallback.class, (params, tell) -> {
    PermissionType type = params.permissionType();
    if (type == PermissionType.VIDEO_CAPTURE || type == PermissionType.AUDIO_CAPTURE) {
        tell.deny();
    } else {
        tell.grant();
    }
});

访问 HTTP 响应体

在 JxBrowser 7.0 中,我们引入了 BytesReceived 该事件允许获取从网络接收到的字节量信息。在本版本中,我们添加了 ResponseBytesReceived,允许访问 HTTP 响应体的字节内容:

network.on(ResponseBytesReceived.class, event -> {
    byte[] data = event.data();
});

隐藏滚动条

现在您可以使用以下方法隐藏滚动条:

browser.settings().hideScrollbars();

调用此方法后,加载在 Browser 实例中的网页将不再显示滚动条。这对于自助服务终端应用程序以及当你需要截取网页的位图时非常有用。

DOM API

Element

Element 已经被扩展了以下方法:

  • focus()blur() 允许以编程方式将键盘焦点设置到可聚焦的 HTML 元素并清除焦点。
  • outerHtml() 允许获取表示 Element 及其后代的 HTML 序列化的字符串。

Node.document()

从 V7.1 开始,您可以获取 Node 实例的 Document 实例。例如:

Document document = node.document();

I18N 国际化

现在,该库在浏览本地文件系统时支持国际化(I18N)。

i18n

Download API

我们对 JxBrowser API 进行了扩展,增加了允许您获取已启动下载的 Browser 实例的功能,具体可以通过以下代码实现:

downloads.set(StartDownloadCallback.class, (params, tell) -> {
    params.browser().ifPresent(browser -> {
        ...
    });
    tell.cancel();
});

请注意,下载开始时,Browser 实例可能已经关闭或不可用。这就是为什么在 API 中我们使用 Optional<Browser> 的原因。

禁用触摸菜单

我们对 EngineOptions 进行了扩展,增加了允许在 Windows 10 触摸设备上禁用触摸菜单的选项。以下代码段展示了如何禁用触摸菜单:

Engine engine = Engine.newInstance(
        EngineOptions.newBuilder(renderingMode)
                .disableTouchMenu()
                .build());

请求焦点事件

要获取当 JavaScript 通过 window.focus() 请求焦点时的通知,您可以使用 FocusRequested 事件:

browser.on(FocusRequested.class, event -> {});

Language API

Language 枚举已扩展了 Language.of(String language, String country) 静态方法,该方法获取对应语言和国家的 Language 枚举项。

如果您需要传递新的语言代码而不是旧的代码,我们建议您使用此方法而不是 Language.of(Locale) 因为 Java 的 Locale 会在内部将传递给构造函数的新语言代码转换为旧代码。这可能会导致无法找到旧代码对应的语言。因此,如果您想确保传递的语言代码不会被转换,请使用该方法并提供所需的语言和国家代码。

Certificate.toX509Certificate()

Certificate 类已扩展了 Optional<X509Certificate> toX509Certificate() 方法,该方法允许使用存储在证书 DER 编码字节数组中的数据初始化并获取 X.509 证书。

改进

  • 在 macOS 或 Linux 上检测到 Java 进程意外地被 kill -9 信号终止时,终止由该 Java 进程创建的 browsercore 进程。
  • 更新 Windows 系统上 browsercore.exe 进程的详细信息。
  • 当未找到 Node 时,XPathResult.asSingleNode() 返回一个空的 Optional,而不是抛出异常。
  • 为 Swing 和 JavaFX 的 BrowserView 组件提供了 StartDownloadCallback 的默认实现。现在,当您尝试下载文件时,将显示一个默认的保存文件对话框,您可以在其中选择下载并保存文件的位置。除非您注册自己的回调并覆盖默认行为。
  • 在 Windows 平台上,减少首次显示 Swing BrowserView 时的黑屏闪烁。

已修复的问题

  • 恢复对 macOS 10.10 的支持。
  • 在 macOS 和 Windows 上工作时,Linux 系统上会忽略 Engine 语言选项,并始终使用 ENGLISH_US 的问题。
  • 弹出窗口的主 Frame 绑定到不同的 Browser 实例。
  • 在包含不可见的 Swing BrowserView 组件的 JFrame 上移动时,可能会出现 java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location 错误。
  • 调用 BrowserView.setSize(0, 0) 时可能会抛出 java.lang.IllegalArgumentException 异常。
  • 尝试记录包含约 20MB 字符串的 RPC 请求时可能会导致 java.lang.OutOfMemoryError 错误。
  • StartNavigationCallback.Params.url() 法在应该返回带有协议的 URL 地址时,却返回了没有协议的 URL 地址。
  • console.log()alert() 中打印通过 JsObject.putProperty() 方法注册的属性时本机崩溃。
  • IFRAME 内的 PDF 文件在整个视图中打开,而不是在网页的 Frame 中打开。
  • 在创建 Browser 后立即关闭时可能会导致 java.lang.NullPointerException
  • 在使用与 Service Workers 相关的 JavaScript 的网页上出现 Failed to register a ServiceWorker 错误。
  • 当在 JavaFX 的 BrowserView 上移动光标时出现 java.lang.NoSuchMethodError: com.teamdev.jxbrowser.ui.internal.rpc.Bitmap.getPixels()Lcom/google/protobuf/ByteString; 错误。
  • 由于 QuotaExceededError 导致无法使用 IndexedDB,因此一些网站无法加载(例如 https://evernote.com)。

感谢您就使用 7.0 版本和从 JxBrowser 6.x 迁移过程中提供的所有反馈!

下载 JxBrowser 7.1

请提供您的电子邮箱地址,我们会尽快将下载说明发送给您。

发送...
请检查您的收件箱。

我们无法发送电子邮件。请使用直接链接下载JxBrowser。

如果您已经是我们的注册客户,您无需任何操作,即可轻松享受此次更新。

如果您希望深入了解并体验我们的产品,您可以申请评估许可证。

获取免费 30 天体验