pup*_*eno 30 java javafx webview javafx-webview
非常简单.是否可以静音或控制JavaFX WebView的音量?我用谷歌搜索了一段时间,但我找不到任何提及.我查看了代码,WebView并且WebEngine似乎没有关于控制音量的任何内容.
我仍然需要MediaPlayer在同一个应用程序中的其他s工作和产生声音,所以,我不能将整个应用程序静音.
Mac*_*ski 11
目前,在WebView或WebEngine Control中没有用于声音系统的API .
但是你可以注入JavaScript来静音/取消静音并控制声音.此方法仅适用于HTML5元素<video>或<audio>,因为Flash或JS初始化音频等项目通常无法限制.我为您创建了示例程序:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
WebView myWebView = new WebView();
WebEngine engine = myWebView.getEngine();
//dirty code xD
Button btn = new Button("Load Youtube");
btn.setOnAction((ActionEvent event) -> engine.load("http://www.youtube.com/embed/A6hrw6KGdtM?autoplay=1"));
Button btn2 = new Button("Mute");
btn2.setOnAction((ActionEvent event) -> engine.executeScript(getJSAudioVideo(true)));
Button btn3 = new Button("Unmute");
btn3.setOnAction((ActionEvent event) -> engine.executeScript(getJSAudioVideo(false)));
Button btn4 = new Button("+");
btn4.setOnAction((ActionEvent event) -> engine.executeScript(getJSSoundVolume(0.9)));
Button btn5 = new Button("-");
btn5.setOnAction((ActionEvent event) -> engine.executeScript(getJSSoundVolume(0.1)));
VBox root = new VBox();
root.getChildren().addAll(myWebView, btn, btn2, btn3, btn4, btn5);
Scene scene = new Scene(root, 800, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("Mute a WebView in JavaFX, is it possible?");
primaryStage.show();
}
/**
* @param mute
* @return JS code for mute/unmute
*/
public String getJSAudioVideo(boolean mute){
return "var videos = document.querySelectorAll('video'),\n" +
" audios = document.querySelectorAll('listen');\n" +
" [].forEach.call(videos, function(video) { video.muted = "+String.valueOf(mute)+"; });\n" +
" [].forEach.call(audios, function(audio) { audio.muted = "+String.valueOf(mute)+"; });";
}
/**
* @param volume
* @return JS code for setting volume sound
*/
public String getJSSoundVolume(double volume){
//max 1.0, min 0.0 Default: 1.0
double _volume = (volume > 1.0 || volume < 0.0) ? 1.0 : volume;
return "var videos = document.querySelectorAll('video'),\n" +
" audios = document.querySelectorAll('listen');\n" +
" [].forEach.call(videos, function(video) { video.volume = "+String.valueOf(_volume)+"; });\n" +
" [].forEach.call(audios, function(audio) { audio.volume = "+String.valueOf(_volume)+"; });";
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
我们都知道它是API的一个缺失部分,那么你可以自己实现它呢?让我们来看看WebView到底是什么:
嵌入式浏览器组件基于WebKit [...] 默认情况下,WebKit不支持网页呈现.为了呈现和显示HTML内容,Oracle必须使用Java Graphics 2D API编写自己的渲染器.
这意味着引擎必须具有实现.WebKit的实现位于com.sun.webkit包中(类的很大一部分只是本机调用的包装器).当然,在大多数情况下,您不想使用com.sun.*类,但目前您正在使用JavaFX,因此它并不重要.
如果我们在太阳的源头跳一点,我们可以找到WCMediaPlayer.class一些抽象的音频方法,如:
protected abstract void setRate(float rate);
protected abstract void setVolume(float volume);
protected abstract void setMute(boolean mute);
protected abstract void setSize(int w, int h);
protected abstract void setPreservesPitch(boolean preserve);
Run Code Online (Sandbox Code Playgroud)
拜托Java,让我给你打电话:
volumeMethod = WCMediaPlayer.class.getDeclaredMethod("setVolume", float.class);
volumeMethod.setAccessible(true);
Run Code Online (Sandbox Code Playgroud)
感谢您的帮助,但我如何获得WCMediaPlayer实例?我们必须看一下参考文献new WCMediaPlayerImpl().疑难杂症!毕竟,WCGraphicsManager.class通过fwkCreateMediaPlayer()方法创建MediaPlayer ,它将指针和实例放入refMap:
Field refMapField = WCGraphicsManager.class.getDeclaredField("refMap");
refMapField.setAccessible(true);
Run Code Online (Sandbox Code Playgroud)
幸运的是,管理器已经公开getGraphicsManager()了获取实例的方法:
WCGraphicsManager graphicsManager = WCGraphicsManager.getGraphicsManager();
refMap = (Map<Integer, Ref>) refMapField.get(graphicsManager);
Run Code Online (Sandbox Code Playgroud)
捕获的地图包含Ref实例(还有其他WC*实例),因此您必须过滤它们:
Collection<WCMediaPlayer> mediaPlayers = refMap.values().stream()
.filter(ref -> ref instanceof WCMediaPlayer)
.map(ref -> (WCMediaPlayer) ref)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
您可能期望工作示例,所以这里是我使用的代码:
public class WebEngineTest extends Application {
private Map<Integer, Ref> refMap;
private Method volumeMethod;
@Override
@SuppressWarnings("unchecked")
public void start(Stage primaryStage) throws Exception {
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("https://www.youtube.com/watch?v=hRAZBSoAsgs");
Field refMapField = WCGraphicsManager.class.getDeclaredField("refMap");
refMapField.setAccessible(true);
volumeMethod = WCMediaPlayer.class.getDeclaredMethod("setVolume", float.class);
volumeMethod.setAccessible(true);
WCGraphicsManager graphicsManager = WCGraphicsManager.getGraphicsManager();
refMap = (Map<Integer, Ref>) refMapField.get(graphicsManager);
Button button = new Button("Volume");
button.setOnAction(event -> setVolume(0.1f));
Group group = new Group();
group.getChildren().addAll(webView, button);
Scene scene = new Scene(group, 625, 625);
primaryStage.setScene(scene);
primaryStage.show();
}
public void setVolume(float volume) {
Collection<WCMediaPlayer> mediaPlayers = this.getMediaPlayers();
mediaPlayers.forEach(mediaPlayer -> setVolumeMethod(mediaPlayer, volume));
}
private void setVolumeMethod(Object instance, Object... args) {
try {
volumeMethod.invoke(instance, args);
} catch (Exception e) {
e.printStackTrace();
}
}
private Collection<WCMediaPlayer> getMediaPlayers() {
return refMap.values().stream()
.filter(ref -> ref instanceof WCMediaPlayer)
.map(ref -> (WCMediaPlayer) ref)
.collect(Collectors.toList());
}
}
Run Code Online (Sandbox Code Playgroud)
最后,请记住这些调用的顺序.例如,在引擎状态refMap不是Refs之前不包含所有内容,SUCCEEDED或者如果根本没有创建图形元素则WCGraphicsManager.getGraphicsManager()返回null.
可能最好的方法是结合这些解决方案.如果没有使用JavaFX提供的scenerio和糟糕的API,很难支持Web技术组合.您还可以尝试嵌入其他浏览器,例如Chromium.
关于WebView,它是Node类的扩展.它封装了WebEngine对象,将HTML内容合并到应用程序的场景中,并提供应用效果和转换的属性和方法.在WebView对象上调用的getEngine()方法返回与之关联的Web引擎.资源
因此,WebView目前不支持任何用于静音/音量控制的API.有一个API来静音MediaPlayer中加载的内容(即.)
获取muteProperty:Source链接的状态
public BooleanProperty muteProperty()
Run Code Online (Sandbox Code Playgroud)
检查静音条件:源链接
public final boolean isMute()
Run Code Online (Sandbox Code Playgroud)
要将视频静音,请将值设置为true:源链接
public final void setMute(boolean value)
Run Code Online (Sandbox Code Playgroud)
或者使用JavaScript API来静音视频/音频:
getElementById("Your video Id");
Run Code Online (Sandbox Code Playgroud)
并将控件设置为静音:
vid.muted = true;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1146 次 |
| 最近记录: |