如何使用Gradle在Java项目中访问资源?

9

我有一个使用Gradle文件构建的JavaFX项目,并且在Intellij中编写所有内容。 在其中,我使用javafx.scene.media.Media和javafx.scene.media.MediaPlayer来播放一些音乐。

public SoundPlayer(String filename) {
    String soundLocation = "\\src\\main\\resources\\sound\\" + fileName;
    String absolute = new File("").getAbsolutePath() + soundLocation;
    System.out.println(absolute);
    Media soundMedia = new Media(new File(absolute).toURI().toString());
    mediaPlayer = new MediaPlayer(soundMedia);
}

我一直在使用的项目目录是:

src/

|---main/

|---|---java/

|---|---|---sound.SoundPlayer

|---|---resources/

|---|---|---sound/

|---|---|---|---click.mp3

|---|---|---|---bgm.mp3

然而,当我尝试将其编译并转换为jar文件时,Gradle将目录更改为以下内容(在jar文件中的顶级目录):

sound/

|---SoundPlayer.class

|---click.mp3

|---bgm.mp3

这导致它抛出了一个Media Exception: MEDIA UNAVAILABLE。我已经尝试将文件更改为以下两种情况之一:

Media soundMedia = new Media(new File("sound\\" + fileName).toURI().toString());

并且

Media soundMedia = new Media(new File(fileName).toURI().toString());

…但我总是收到相同的异常。发生了什么事?


你能否分享一下你的Gradle构建文件? - Ankit
运行时源目录不会存在。 - undefined
1个回答

15
Gradle所做的事情完全是可以预料的。src/main/java和src/main/resources目录分别存储代码和资源。资源文件夹包含所有非Java代码,如图像、声音等。
创建JAR文件时,资源目录的内容将按原样复制(保持包结构)。请注意,click.mp3和bgm.mp3是sound包的成员。
因此,当您想要加载资源时,通常不应使用文件路径。而是使用包结构来进行。在这里,由于声音和SoundPlayer具有相同的包,即sound,您可以使用SoundPlayer类来加载资源,如下所示:
public SoundPlayer(String filename) {
    URL resource = SoundPlayer.class.getResource(filename);
    Media soundMedia = new Media(resource.toExternalForm());
    mediaPlayer = new MediaPlayer(soundMedia);
}

从Javadocs

public String toExternalForm() 构造此URL的字符串表示形式。通过调用此对象的流协议处理程序的toExternalForm方法来创建字符串。

实质上,toExternalForm()函数为给定的资源创建适当的URL。

这里是一个完整的示例。

// build.gradle
apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'


mainClassName = 'sound.Main'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

jar { manifest { attributes 'Main-Class': 'sound.Main' } }

和修改后的SoundPlayer
//sound.SoundPlayer
package sound;

import java.net.URL;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class SoundPlayer {

    private MediaPlayer mediaPlayer;

    public SoundPlayer(String filename) {
        URL resource = SoundPlayer.class.getResource(filename);
        Media soundMedia = new Media(resource.toExternalForm());
        mediaPlayer = new MediaPlayer(soundMedia);
    }

    public void play(){
        mediaPlayer.play();
    }
}

使用SoundPlayer的主类是:
// sound.Main
// This class does not actually create a JavaFX UI. Instead, it is
// only creating a JavaFX application to use Media
package sound;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 *
 * @author aga53
 */
public class Main extends Application{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        SoundPlayer s = new SoundPlayer("test.mp3");
        System.out.println("Hello World");
        s.play();
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接