I have packed all the class files and resources as a jar but on execution the sound files wont play. My package structure is:
+project
|_classes
|_ _*.class
|_resources
|_ _ *.jpg,*.wav
Code:
AudioInputStream inputStream = AudioSystem.getAudioInputStream(kidsClassRoom.class.getResourceAsStream("../resources/"+file));
getting a null when this line is executed!!
An alternate theory to those already presented. Often successful getResource() calls depend on the class loader instance that is called to locate them. For this reason, I would recommend to use an instance of a user defined object, from which to call getResource(). E.G.
// Sanity check
System.out.println("The value of 'file' is: " + file);
// Presuming kidsClassRoom1 is an instance of kidsClassRoom
AudioInputStream inputStream = AudioSystem.
getAudioInputStream(
kidsClassRoom1.
getClass().
getResourceAsStream("/resources/"+file));
You might also note that snippet uses the prefix of "/" for the resource. Contrary to what others are saying, I am confident that means 'from the root' of the resource path, in whatever Jar on the run-time class-path it is found. Leaving the '/' or '../' out will have the class loader searching for the resource in a sub-path of the class that this is occurring in.
Of course - make sure the Wav ends up in the Jar! Copy/rename the .jar to a .zip and double click it is the 'quick & dirty' way to examine the archive contents on Windows.
Create a package named resources as shown below
then
AudioSystem.getAudioInputStream(kidsClassRoom.class.getResourceAsStream("resources/"+file));
This is my function for playing a looping sound file in jars, it works fine for me.
It appears that getResourceAsStream() doesn't work with jars. however, getResource() does.
public synchronized void alarm() {
try {
crit = AudioSystem.getClip();
AudioInputStream inputStream1 = AudioSystem.getAudioInputStream(this.getClass().getResource("critical.wav"));
crit.open(inputStream1);
crit.loop(Clip.LOOP_CONTINUOUSLY);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
When you do getResourceAsStream, it is not relative to the current class, but the root of the archive. That is, first try to remove ../.
The important thing to note is that in the exported jar the resources are not stored as files (Read this somewhere, someone more knowledgeable please input). So it's best to get the resource as a URL Object first then pass that to the AudioInputStream Object.
URL url = YourClass.class.getResource(filename);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
If the resource is in a subfolder, remember to add it to your filename path.
Related
I have this directory structure:
root
resources
.png files
Music.mid
Sound.wav
src
.java files
and I play the sounds from the resources folder using this code
public void play() {
try {
URL defaultSound = getClass().getResource(filename);
AudioInputStream audioInputStream =
AudioSystem.getAudioInputStream(defaultSound);
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start( );
while (clip.isRunning()) {}
}
catch (Exception e) {
e.printStackTrace();
}
}
I pass to it filenames = /resources/Music.mid and /resources/Sound.wav.
It works fine when I run it in IDE, but when I package it into jar (all music files are inside the jar, I checked) it doesn't play sound and throws exception:
FileNotFoundException: syntax error in file name, directory name or disk name.
Why does this happen and how do I fix it?
getClass() returns a URL and not a File object. It does that because classloaders (which is what .getResource uses) are an abstract concept, and 'a resource' can be anything. It does not have to be a file. It can be an entry in a jar file (which is really a zip). It can be an entry in a jmod file (which is a custom container format introduced with JDK9). It can be a blob in a database column. A file on a webdav server. Or even generated on the fly every time you ask for the resource. Anything goes.
Clearly, your audio player library is obsolete or crappy. It DOES allow you to pass a URL to it, but the audio player library you're using will just crash out if that URL is anything except one that represents an actual file on disk.
When running in the IDE, it IS a file on disk. When running as a jar, it is as valid a resource as anything a classloader produces, but due to the failure of this player library to deal with any URL (other than file:// URLs), it crashes.
There are only two solutions:
Get a better library.
Find a temp dir, unpack the resource into it, then hand the temp file (or possibly a URL representing this temp file) to your library.
Option #2 is quite hairy. You need to find a location with write access, and you need to take care of deleting the file after. It's also a waste of disk cycles. But if you must, you can, of course, do so:
public void play() throws Exception {
File f = File.createTempFile("Sound.wav");
f.deleteOnExit();
try (InputStream in = YourPlayer.class.getResourceAsStream("/resources/Sound.wav");
OutputStream out = new FileOutputStream(f)) {
in.transferTo(out);
}
AudioInputStream audioInputStream =
AudioSystem.getAudioInputStream(f.toURI().toURL());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start( );
while (clip.isRunning()) {}
}
NB: getClass().getResource() is slightly wrong; the right syntax is ClassThisCodeIsIn.class.getResource. Usually both work, but there are cases where the latter works but the former doesn't (such as when you're subclassing). It's a good habit to never write code that is strictly inferior to something that's just as simple, even if in this particular case it probably doesn't matter.
Okay, I've been at this for hours, I've checked other questions for help and I've tried all of the suggestions but none seem to work.
I am packaging a folder (called "audio") into my project with a bunch of .wav files in it. I am trying to reference those files, however they never get referenced inside the JAR, only outside in a separate folder called "audio".
try {
Clip clip = AudioSystem.getClip();
InputStream inn = this.getClass().getClassLoader().getResourceAsStream("/audio/" + rangod + ".wav");
AudioInputStream inputStream = AudioSystem.getAudioInputStream(inn);
clip.open(inputStream);
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(-10.0f);
clip.start();
} catch (Exception e1) {
e1.printStackTrace();
}
The problem child seems to be
InputStream inn = this.getClass().getClassLoader().getResourceAsStream("/audio/" + rangod + ".wav");
From what I've seen on other questions similar to this, having the "/" in front of "audio" is supposed to reference the audio folder INSIDE my jar file where as removing the "/" from in front of "audio" is supposed to reference the audio folder in the same directory as my jar file (ie: /desktop/audio)
Both methods seem to reference the same folder outside of my jar, and neither the one inside my jar.
My hierarchy is this:
audio
----[audio files]
net
----fragbashers
--------rgp
------------[class files]
I fixed the issue, it was a really easy fix that I was overlooking. All my WAV files were saved in all lower case and I hadn't been converting the picked characters string to lowercase, so it didn't think the file existed.
I am trying the following code to play an mp3. The file is in the correct folder. An exception is thrown when opening the file.
Any ideas what could be wrong?
When trying to print the url on the third line it gives me a null pointer exception.
I am compiling with 1.8 to a min compat version of 1.6. Could this be related?
AudioInputStream audioIn = null;
URL url = this.getClass().getResource("./data/1.wav");
System.out.print(url.getFile());
try {
audioIn = AudioSystem.getAudioInputStream(url);
//audioInputStream = AudioSystem.getAudioInputStream(this.getClass().getResource(soundFile));
}
catch(Exception ex) {System.out.print("exception opening file");}
try{
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}
catch(Exception ex)
{
System.out.print("exception mediaplayer");
}
}
Instead of using a String var, you could use a Clip object. With Clip, it worked for me.
Oh I had to put the data folder in the src directory.
Still a problem though: when I compile as a jar file, it does not find the data folder. And I want the user to be able to put different things in there.
A URL can see into Jar, unlike a File address. So, you should be fine using the URL to obtain the file.
Two possible problems:
(1) if the file is an .mp3 and you are trying to load a .wav, there will of course be a mismatch as 1.mp3 <> 1.wav.
(2) putting the data into the src folder is not enough. It must also be in a subfolder of the folder that contains the "this" that you refer to. For example, if your code is in package "foo", the place to put the file would be src/foo/data/1.wav.
Do you have a library to decode the .mp3? If so, something like JavaZoom should work.
I've made an audio player and the jar was made with netbeans. To load the images I've used:
ClassLoader cl = this.getClass().getClassLoader();
URL playerIconURL = cl.getResource("tp/audioplayer/Images/icon.png");
if (playerIconURL != null){
ImageIcon playerIcon = new ImageIcon(playerIconURL);
frame.setIconImage(playerIcon.getImage());
}
else{
System.err.println("cannot load player icon");
}
I mention that the folder Images is in the src/tp/audioplayer.
When I'm running the application inside netbeans everything is allright, but when I execute the jar in command prompt,the application starts but it's blank and it blocks and I get:
Can you tell me what I've done wrong or what is the problem? Thanks in advance!
If tp is in your classpath you will have to load it with cl.getResource("/tp/audioplayer/Images/icon.png") if tp is NOT a source folder (but still added to the buildpath.
If you add tp as a sourcefolder then
cl.getResource("/audioplayer/Images/icon.png")
Note that jars are casesensitive, make sure you the case-sensitive file-path.
Try any of these:
// using getResourceAsStream
InputStream is = this.getClass().getResourceAsStream( "picture.gif" );
// or
InputStream is = MyClass.class.getResourceAsStream( "stuff.ser" );
// or
InputStream is = MyApp.class.getClassLoader().getResourceAsStream( "InWords.properties" );
The resource in the jar file must be qualified with same package name as the class you call getResourceAsStream from. Alternatively, you can use an absolute name beginning with a / where dots get mapped to /s. If you don’t have a lead /, you have a relative name, and the name of the package will be prepended. If you use a /, you must include the name of the package yourself, or whatever name the resource is filed under in the jar.
For example you could specify /com/mindprod/mypackage/mystuff.ser or /com.mindprod.mypackage.mystuff.ser or simply mystuff.ser. Don’t use Windows style filenames with . These are not filenames, but Java resources that live along with the class files either in jars or sometimes freestanding on disk, or on the server.
In theory, getResourceAsStream will look in the local classpath, in the jar and in the directory where the class file was loaded from.
This is the first time I've implemented sounds but I can't figure out where to actually place the sounds to play them. I am using Eclipse as my IDE and I've put my sounds in a folder called sounds.
The following code is what I've used to create one of the audioclip objects:
private final String background = "." + slash + "sounds" + slash + "background.wav";
main(....){
try {
backgroundClip = Applet.newAudioClip(new File(background).toURI().toURL());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I don't hear anything. When I remove the try/catch I get an error saying that it is unable to find the file. I placed my sound folder in both /src and /bin but neither can find it. where do I put it?
The base for your project is the level above the src folder. So using . will put you at your project folder.
Basically,
. = project_root
./src = default_package
./src/packagename = inside the package named "packagename"
./sounds/background.wav = a .wav file in the sounds folder, in the project_root
Using your current path, you need to put your .wav file in the sounds folder in the project_root.
The path will end up being project_root/sounds/background.wav.
See this thread to understand why application resources should be obtained by URL obtained from getResource(), rather than a File converted to an URL.