JavaFX problem with playing audio: Unsupported protocol "file"

155 Views Asked by At

I'm trying to use javafx.scene.media.AudioClip to play audio included with .jar file, but I'm constantly getting hit with this error:

Exception in thread "main" java.lang.UnsupportedOperationException: Unsupported protocol "file"
        at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:241)
        at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.<init>(NativeMediaAudioClip.java:53)
        at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.load(NativeMediaAudioClip.java:63)
        at com.sun.media.jfxmediaimpl.AudioClipProvider.load(AudioClipProvider.java:66)
        at com.sun.media.jfxmedia.AudioClip.load(AudioClip.java:135)
        at javafx.scene.media.AudioClip.<init>(AudioClip.java:83)
        at main.Main.main(Main.java:77)

I simplified my code as much as possible, omitting abstractions and additional methods to make sure that the error is actually in the AudioClip:

package main;

import javafx.scene.media.AudioClip;

public class Main {
    public static void main(String[] args) {
        AudioClip clip = new AudioClip(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
        clip.play();
    }
}

(I also tried using .toString() instead of toExternalForm())

I made sure that the sound file is actually included in .jar in the correct path. For example this way of playing audio via JavaX AudioInputStream and Clip works just fine:

    public static void main(String[] args) throws LineUnavailableException, IOException, UnsupportedAudioFileException, InterruptedException {
        AudioInputStream ais = AudioSystem.getAudioInputStream(Main.class.getResource("/sound/ambience/randomScare.wav"));
        Clip clip = AudioSystem.getClip();
        clip.open(ais);
        ais.close();

        clip.start();
        Thread.sleep()
    }

(But I can't use this in final product, as it supports only uncompressed .wav format)

I have no idea what could be causing that problem, as even official javadoc states:

source - URL string from which to load the audio clip. This can be an HTTP, file or jar source.

Some more information that possibly can help with finding solution: I'm using org.openjfx:javafx-media, version 21-ea+24 from maven central repository (and I also tried switching back to version 20.0.1):

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>21-ea+24</version>
        </dependency>

Maven project is setup with java version 1.17:

    <properties>
        <maven.compiler.source>1.17</maven.compiler.source>
        <maven.compiler.target>1.17</maven.compiler.target>
        <exec.mainClass>main.Main</exec.mainClass>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

And I run it using Zulu 18 (Zulu18.32+13-CA (build 18.0.2.1+1)) on Windows 10 (Build 19044)

I will appreciate any help (and hope that I've given all needed information).

Update: I tried running the .jar build with github workspaces (that .jar worked just fine for my friend), and got different error:

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: no glib-lite in java.library.path: C:\Program Files\Zulu\zulu-18\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\Zulu\zulu-18\bin\;C:\Program Files\Zulu\zulu-19\bin\;C:\ProgramData\Oracle\Java\javapath;C:\Program Files\Common Files\Oracle\Java\javapath;C:\ProgramData\Oracle\Java\jdk-16.0.1;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Common Files\Autodesk Shared\;C:\Program Files\dotnet\;C:\Program Files\spwn\;C:\Program Files\Kotlin\kotlinc_1_6_10;C:\Program Files\Kotlin\kotlinc_1_6_10\bin;C:\Program Files\Kotlin\konaco_1_6_10;C:\Program Files\Kotlin\konaco_1_6_10\bin;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\ffmpeg\bin;C:\Program Files\Git\cmd;C:\Program Files\PuTTY\;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\Scripts\;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\;C:\Users\Kofiy\AppData\Local\Microsoft\WindowsApps;C:\jdk-16.0.1\bin;C:\jdk-16.0.1\bin\;C:\jdk-16.0.1\bin\javac.exe;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.1.2\bin;C:\Users\Kofiy\AppData\Local\GitHubDesktop\bin;C:\Users\Kofiy\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.2\bin;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310;C:\Users\Kofiy\AppData\Local\Programs\Python\Python310\Scripts;C:\Users\Kofiy\.dotnet\tools;.
        at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2434)
        at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:848)
        at java.base/java.lang.System.loadLibrary(System.java:2015)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:168)
        at com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:56)
        at com.sun.media.jfxmediaimpl.NativeMediaManager.lambda$new$0(NativeMediaManager.java:111)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
        at com.sun.media.jfxmediaimpl.NativeMediaManager.<init>(NativeMediaManager.java:108)
        at com.sun.media.jfxmediaimpl.NativeMediaManager$NativeMediaManagerInitializer.<clinit>(NativeMediaManager.java:78)
        at com.sun.media.jfxmediaimpl.NativeMediaManager.getDefaultInstance(NativeMediaManager.java:90)
        at com.sun.media.jfxmedia.MediaManager.canPlayProtocol(MediaManager.java:78)
        at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:240)
        at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.<init>(NativeMediaAudioClip.java:53)
        at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.load(NativeMediaAudioClip.java:63)
        at com.sun.media.jfxmediaimpl.AudioClipProvider.load(AudioClipProvider.java:66)
        at com.sun.media.jfxmedia.AudioClip.load(AudioClip.java:135)
        at javafx.scene.media.AudioClip.<init>(AudioClip.java:83)
        at main.Sound.playMP3(Sound.java:222)
        at main.GamePanel.startGame(GamePanel.java:1624)
        at main.KeyHandler.keyPressed(KeyHandler.java:126)
        at java.desktop/java.awt.Component.processKeyEvent(Component.java:6574)
        at java.desktop/javax.swing.JComponent.processKeyEvent(JComponent.java:2905)
        at java.desktop/java.awt.Component.processEvent(Component.java:6393)
        at java.desktop/java.awt.Container.processEvent(Container.java:2266)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4991)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
        at java.desktop/java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1952)
        at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:883)
        at java.desktop/java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1146)
        at java.desktop/java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:1020)
        at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:848)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4872)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
        at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
        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)

(((The error in now in AWT-EventQueue-0 because it's full version of the project and not mine simplified code that I wrote earlier)))

And I also tried running .jar with doubleclicking on it, and both .jar built on my system via IntelJ IDEA and .jar built on GitHub workspaces showed this error: Error: A JNI error has occurred, please check your installation and try again

PS: This JNI visual error actually appears whenever I double click on any .jar, what's also very strange PS 2: The JNI visual error is because I messed up and had Java 1.8 as default JRE

So it does in fact look like the problem with my installation, so I will just try reinstalling JDK, verifying system files etc.

2

There are 2 best solutions below

4
g00se On

This is not an answer but I'm putting this out there to show you what happens for me. In both cases the sound plays and I use your toExternalForm to print to stdout. When running it from the jar:

goose@t410:/tmp/sound$ java -cp /tmp/sound/target/sound-1.0-SNAPSHOT.jar fx.sound.App
jar:file:/tmp/sound/target/sound-1.0-SNAPSHOT.jar!/sound/ambience/testSound.mp3

then with Maven:

goose@t410:/tmp/sound$ mvnt javafx:run
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< com.technojeeves:sound >-----------------------
[INFO] Building sound 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] >>> javafx-maven-plugin:0.0.6:run (default-cli) > process-classes @ sound >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ sound ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ sound ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] <<< javafx-maven-plugin:0.0.6:run (default-cli) < process-classes @ sound <<<
[INFO] 
[INFO] 
[INFO] --- javafx-maven-plugin:0.0.6:run (default-cli) @ sound ---
[INFO] Toolchain in javafx-maven-plugin null
[WARNING] Module name not found in <mainClass>. Module name will be assumed from module-info.java
file:/tmp/sound/target/classes/sound/ambience/testSound.mp3
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.320 s
[INFO] Finished at: 2023-07-20T23:13:32+01:00
[INFO] ------------------------------------------------------------------------
goose@t410:/tmp/sound$ 

Code used to run the clip:

package main;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.media.AudioClip;

public class Main extends Application {
    @Override
    public void start(Stage stage) {
        AudioClip clip = new AudioClip(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
        System.out.println(Main.class.getResource("/sound/ambience/testSound.mp3").toExternalForm());
        clip.play();
        //Platform.exit();
    }


    public static void main(String[] args) {
        launch();
    }

}
0
kofiy On

In the end issue was in fact with JavaFX not being initialized.

As a simple test workaround I created very simple JavaFX app that just starts the actual JavaX application.

(Although in the future I will probably rewrite a big piece of the code to avoid this VERY BAD workaround. (But at least it works for now...))