IntelliJ IDEA добавляет ресурсы в JAR
Я получил приложение, которое работает с ресурсами (.wav .png- файлы). Я хочу включить эти ресурсы в мой.jar, когда я создаю свой проект.
Запуск приложения из IDE работает хорошо.
Как описано здесь, я создал resources-folder
на том же уровне моего src-folder
Мой проект-структура:
ProjectName --
|
out
|
resources --
| |
| sounds
| |
| images
src --
|
...
Как описано здесь, я пометил папку resources
как Resources root
,
Как описано здесь, я создал свои собственные артефакты в Project structure
, Вот как они выглядят:
Кусок кода, который работает с аудиофайлом, например:
new Media(new File("resources/sounds/login_sound.wav").toURI().toString());
Когда я пытаюсь запустить jar через терминал, я получаю следующую ошибку:
Caused by: MediaException: MEDIA_UNAVAILABLE : /home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav (File or directory not found)
Полная трассировка стека:
moritz@Momix:~/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar$ java -jar TheFloorIsLavaGUI.jar
Gtk-Message: 12:33:12.649: Failed to load module "canberra-gtk-module"
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: MediaException: MEDIA_UNAVAILABLE : /home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav (Datei oder Verzeichnis nicht gefunden)
at javafx.scene.media.Media.<init>(Media.java:407)
at managers.SoundManager.playSong(SoundManager.java:71)
at main.TheFloorIsLavaGUI.start(TheFloorIsLavaGUI.java:39)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
... 1 more
Exception running application main.TheFloorIsLavaGUI
Любые советы? Спасибо
1 ответ
TL;DR:
Загрузите файл из пути к классам, а не из файловой системы:
new Media(
Test.class.getResource(
"resources/sounds/login_sound.wav"
).toURI().toString())`
Пояснение: здесь происходит несколько вещей:
- Вы пытаетесь загрузить файл с пути
/your/home/.../project/out/artifacts/.../resources/...
, По маркировкеresources
в качестве папки ресурсов вы указываете IntelliJ поместить все файлы в корень пути к классам, как показано на скриншоте.
Он не помещает этот файл в файловую систему, но включает его в банку
При запуске из IDE,
new File("resources/sounds/login_sound.wav").toURI()
оценивает/home/moritz/IdeaProjects/TheFloorIsLavaGUI/resources/sounds/login_sound.wav
где находится файл в вашем проекте. При запуске из банки, он оценивает путь в выходной папке,/home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav
, который не является тем местом, куда его помещает сборка.
Теперь правильный способ справиться с этим - загрузить ресурсы не из файловой системы, а из пути к классам. Попробуйте запустить следующее из IDE и из банки, чтобы увидеть разницу
System.out.println(new File("foo.wav").toURI().toString());
System.out.println( Test.class.getResource("foo.wav").toURI().toString());
// From IDE
file:/Users/.../untitled/foo.wav
file:/ Users/.../untitled/out/production/untitled/foo.wav
// From Jar
file:/Users/.../untitled/out/artifacts/foo.wav
jar:file: /Users/.../untitled/out/artifacts/untitled_jar/untitled.jar!/foo.wav
Обратите внимание, что Media
принимает JAR URI: https://docs.oracle.com/javafx/2/api/javafx/scene/media/Media.html
Так что то, что вам нужно, на самом деле просто. Изменить загрузку WAV с new Media(new File("resources/sounds/login_sound.wav").toURI().toString());
в new Media(Test.class.getResource("resources/sounds/login_sound.wav").toURI().toString())
Кроме того: вы можете захотеть взглянуть на инструменты сборки, такие как gradle или maven, а не на сборку из IDE.