使用JDK 11播放规则和循环声音



我使用的是Java JDK 11.0.8(Eclipse下的"Installed JRE"设置为JDK-11.0.8(、Eclipse 2020-06和Codename One 6.0.0。

我最近从JDK8切换到JDK11,注意到在我的应用程序中播放声音选项已经不起作用了。。。

注意,我取消选中";Java 8〃;当我创建应用程序时,我只是试图在模拟器中解决问题(我并没有试图将应用程序部署到实际的移动设备上(。

我想玩一个";规则音";(我想从头到尾播放一个声音,当它结束时,我不需要从头开始重播(;循环声音";(声音应该在结束时开始,因此,我可以在背景中连续播放(。

因此,我有两个问题:

问题1-关于";规则音">

我只想创建一次Media对象,然后每当我需要播放相同的常规声音时重复使用它。

为此,我将媒体创建封装在一个类中,如下所示:

public class RegularSound {
private Media m;
public RegularSound(String fileName) {
try{
InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/"+fileName);
m = MediaManager.createMedia(is, "audio/wav");
}
catch(Exception e)
{
e.printStackTrace();
}

}

public void play() {
m.setTime(0);
m.play();
}
}

然后我实例化RegularSound对象并按如下方式播放:

mySound = new RegularSound("example.wav");
mySound.play();

请注意,example.wav直接复制在";src";我项目的目录。

这段代码曾经使用JDK 8,但使用JDK 11时,我得到了以下构建错误:

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: javax/media/ControllerListener
at com.codename1.impl.javase.JavaJMFSEPort$1.run(JavaJMFSEPort.java:67)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.ClassNotFoundException: javax.media.ControllerListener
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.ClassLoader.findSystemClass(ClassLoader.java:1247)
at com.codename1.impl.javase.ClassPathLoader.findClass(ClassPathLoader.java:269)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at com.codename1.impl.javase.ClassPathLoader.loadClass(ClassPathLoader.java:115)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at com.codename1.impl.javase.ClassPathLoader.loadClass(ClassPathLoader.java:107)
... 14 more

问题2-关于";循环声音">

对于循环声音,我创建了另一个类如下:

public class LoopingSound implements Runnable{
private Media m;
String fileName;

public LoopingSound(String fileName){
try{
InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/"+fileName);
m = MediaManager.createMedia(is, "audio/wav",this);
}
catch(Exception e)
{
e.printStackTrace();
}

}
public void pause()
{
m.pause();
}
public void play()
{
m.play();
}

public void run() {
m.setTime(0);
m.play();

}
}

但当我实例化LoopinSong的一个对象并尝试播放它时,我再次遇到构建错误…

所以,你能告诉我如何更改规则和循环声音的代码,这样我在使用JDK11时就不会收到上述错误吗?

更新

谢谢回复@shai-almog。我已经安装了CEF。但我在运行时在控制台上收到一些消息,我听不到播放的声音。。。我运行以下代码:

try {
InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/example.wav");
Media m = MediaManager.createMedia(is, "audio/wav");
m.play();
} catch (IOException e) {
e.printStackTrace();
}

当我运行此代码时,我在控制台上收到以下消息(它在最后抛出一个异常(:

Adding CEF to classpath
Retina Scale: 2.0
CEF Args: [--disable-gpu, --disable-software-rasterizer, --disable-gpu-compositing, --touch-events=enabled, --enable-media-stream, --device-scale-factor=4, --force-device-scale-factor=4, --autoplay-policy=no-user-gesture-required, --enable-usermedia-screen-capturing]
Using:
JCEF Version = 83.4.0.260
CEF Version = 83.4.0
Chromium Version = 83.0.4103.106
AppHandler.stateHasChanged: INITIALIZING
initialize on Thread[AWT-EventQueue-0,6,main] with library path C:Userspmuyan.codenameoneceflibwin64
Added scheme search://
Added scheme client://
Added scheme cn1stream://
DevTools listening on ws://127.0.0.1:8088/devtools/browser/591d3502-6fd6-4997-9131-9a2a352e47b1
AppHandler.stateHasChanged: INITIALIZED
Running ready callbacks
Exception in thread "AWT-EventQueue-0" Address changed to data:text/html,%3C!doctype%20html%3E%3Chtml%3E%3Chead%3E%3Cstyle%20type%3D'text%2Fcss'%3Edocument%2C%20body%20%7Bpadding%3A0%3Bmargin%3A0%3B%20width%3A100%25%3B%20height%3A%20100%25%7D%20video%2C%20audio%20%7Bmargin%3A0%3B%20padding%3A0%3B%20width%3A100%25%3B%20height%3A%20100%25%7D%3C%2Fstyle%3E%3C%2Fhead%3E%3Cbody%3E%3Caudio%20id%3D'cn1Media'%20width%3D'640'%20height%3D'480'%20style%3D'width%3A100%25%3Bheight%3A100%25'%20src%3D'https%3A%2F%2Fcn1app%2Fstreams%2F1'%2F%3E%3Cscript%3Ewindow.cn1Media%20%3D%20document.getElementById('cn1Media')%3Bfunction%20callback(data)%7B%20cefQuery(%7Brequest%3A'shouldNavigate%3A'%2BJSON.stringify(data)%2C%20onSuccess%3A%20function(response)%7B%7D%2C%20onFailure%3Afunction(error_code%2C%20error_message)%20%7B%20console.log(error_message)%7D%7D)%3B%7Dcn1Media.addEventListener('pause'%2C%20function()%7B%20callback(%7B'state'%3A'paused'%7D)%7D)%3Bcn1Media.addEventListener('play'%2C%20function()%7B%20callback(%7B'state'%3A'playing'%7D)%7D)%3Bcn1Media.addEventListener('ended'%2C%20function()%7B%20callback(%7B'state'%3A'ended'%7D)%7D)%3Bcn1Media.addEventListener('durationchange'%2C%20function()%7B%20callback(%7B'duration'%3A%20Math.floor(cn1Media.duration%20*%201000)%7D)%7D)%3Bcn1Media.addEventListener('timeupdate'%2C%20function()%7B%20callback(%7B'time'%3A%20Math.floor(cn1Media.currentTime%20*%201000)%7D)%7D)%3Bcn1Media.addEventListener('volumechange'%2C%20function()%7B%20callback(%7B'volume'%3A%20Math.round(cn1Media.volume%20*%20100)%7D)%7D)%3Bcn1Media.addEventListener('error'%2C%20function()%7B%20var%20msg%20%3D%20'Unknown%20Error'%3B%20try%20%7Bmsg%20%3D%20cn1Media.error.message%20%2B%20'.%20Code%3D'%2Bcn1Media.error.code%3B%7Dcatch(e)%7B%7D%20callback(%7B'error'%3A%20msg%7D)%7D)%3B%3C%2Fscript%3E%20%3C%2Fbody%3E%3C%2Fhtml%3E

更新2

我可以手动将Open JavaFX 11添加到Eclipse和在Eclipse下运行的Codename One应用程序中,同时使用JDK 11,如下所示:

Step1) Create JavaFX11 user library under Eclipse
Download JavaFX 11 from https://gluonhq.com/products/javafx/
unzip it -> creates javafx-sdk-11.0.2 folder
Create a User Library: Eclipse -> Window -> Preferences -> Java -> Build Path -> User Libraries -> New. 
Name it JavaFX11.
Hit "Add External JARs" and include all the jars under javafx-sdk-11.0.2lib
Step 2) Add the JavaFX11 library to the project:
Right click on project.
Select Build path -> Configure Build Path 
Goto Library tab->Add Library->User Library->Check JavaFX11->Apply and Close

现在,我可以听到Codename One应用程序中播放的声音。

然而,我需要从命令提示符运行我的应用程序,而运行应用程序的常规命令行已经不起作用了(应用程序无法从命令提示符找到JavaFX相关的类,我会收到上面列出的相同错误(。所以你能告诉我如何修改命令行,以便使用JavaFX的Codename One项目可以在命令提示符下运行吗?

这是我使用的常规命令行:

java -cp distProj.jar;JavaSE.jar com.codename1.impl.javase.Simulator com.mycompany.hi.Main

顺便说一句,我曾尝试在命令行中将javafx-sdk-11.0.2\lib下的javafx.media.jar添加到类路径(-cp(中,但没有成功。。。

更新3

我们使用以下命令行解决了这个问题:

java—模块路径C:\javafx-sdk-11.0.2\lib\—add modules=ALL-module-path-cp dist\Proj.jar;JavaSE.jar com.codename1.impl.JavaSE.Simulator com.mycompany.hi.Main

(其中C:\javafx-sdk-11.0.2\lib\是我们的(

谢谢!

TL;博士

按照这里的说明安装CEF,或者为您的VM切换到ZuluFX 11。

解释:

在我们集成CEF支持之前,这种方法一直有效——我们会为JDK 11安装动态下载JavaFX,但这导致了许多相关问题。因此,我们决定迁移到CEF,这仍在进行中,尽管正在进行JavaFX动态下载,但已经中断。一旦完成,CEF将自动安装,这将再次实现无缝。

这影响了JavaFX实现的浏览器组件和媒体这两个组件。

最新更新