JavaFX MediaPlayer doesn't release file handle - java

I am aware that this is possibly a duplicate. I've checked the other questions before and did not succeed in solving my problem. I am trying to build some sort of instant button app with javafx. At some point I play a file with the following code:
if(mediaPlayer != null){
mediaPlayer.stop();
}
File soundFile = new File(Config.getInstantSoundsDirectory() + File.separator + fileName);
Media mediaFile = new Media(soundFile.toURI().toString());
mediaPlayer = new MediaPlayer(mediaFile);
mediaPlayer.setOnEndOfMedia(() -> mediaPlayer.dispose());
mediaPlayer.play();
If I want to delete the file I am using following code:
try {
Files.deleteIfExists(Paths.get(Config.getInstantSoundsDirectory(), fileName));
} catch (IOException e1) {
e1.printStackTrace();
}
It works if I've never played the file before. If I did though, I will get an exception that says I can't delete it because some other process is using it. According to other posts the solution to remove the file handle from the file is to call dispose() on my mediaPlayer, as I am doing right when the file was played. Unfortunately the error persists. Am I maybe missing something ?
Thanks for your help.
Greets Ionic
Edit -> Here is my sample test code:
String filePath = Paths.get(".", "test.mp3").toString();
File soundFile = new File(filePath);
Media hit = new Media(soundFile.toURI().toString());
player = new MediaPlayer(hit);
player.setOnEndOfMedia(() -> {
player.dispose();
try {
Files.deleteIfExists(Paths.get(".", "test.mp3"));
} catch (IOException e) {
e.printStackTrace();
}
});
player.play();

Related

Needing to type full path to save file?

Okay, this is my first post here, sorry if i did something wrong. (please let me know if i did aswell)
So i've been trying to make a "data" folder with a audio(.wav) file in it when the runnable jar file is run but for some reason it doesn't work, i've tried to get this working for the last week but i finally kinda gave up on trying to get it working without help(other than searching around the internet) and therefore ask here.
So i have this code:
public static void loop(String path, int volume) {
try {
if (volume > 6) throw new IllegalArgumentException("Requested volume ("+volume+") is higher than allowed. (maximum 6)");
else if (volume < -80) throw new IllegalArgumentException("Requested volume ("+volume+") is lower than allowed. (minimum -80)");
else {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File(path)));
clip.loop(Clip.LOOP_CONTINUOUSLY);
FloatControl gain = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gain.setValue(volume);
clip.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
for looping a .wav file continuously and it works, then i try to save the file with this code:
public void save(String music, String output) {
try {
File sound = new File(music);
AudioInputStream ais = AudioSystem.getAudioInputStream(sound);
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(output));
} catch (IOException | UnsupportedAudioFileException e) {
e.printStackTrace();
}
}
And that seems to work aswell when i do something like this:
save("D:\\Eclipse\\eclipse\\workspace\\Test\\data\\music.wav", "C:\\Users\\Karim\\Desktop\\data\\test.wav");
loop("C:\\Users\\Karim\\Desktop\\data\\test.wav", -30);
But if i try to do this instead:
private File jar() {
try {
File jar = new File(Game.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
return jar;
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
private File data = new File(jar().getParentFile().getPath()+File.separator+"\\data");
private File music = new File(data.getPath()+"\\music.wav");
save(music.getPath(), "C:\\Users\\Karim\\Desktop\\data\\test.wav");
loop("C:\\Users\\Karim\\Desktop\\data\\test.wav", -30);
it won't save the file, why is that and what can i do to make it save?
Final Notes:
I'm pretty new to java.
I'm pretty new to programming in itself.
I don't want to use a library, i wanna try to make it work without and i'm so close.
If i forgot to say anything please let me know and i'll edit this post or make a comment.
EDIT: Just wanted to make it clear that this works in the IDE but not when i export it. Also i have the data folder both IN the 'src' folder and beside the 'src' folder, just for testing.

Android MediaPlayer - switch to next song

I generate a midi file and write it like this:
File output = new File("exampleout.mid");
I think I might need to change this, so it is in the right folder (just a readable/writable folder, perhaps Music/ )
Next I want to play this midi file with MediaPlayer, but I cannot figure out how to load the file.
mediaPlayer = MediaPlayer.create(this, R.raw.test3);
Only loads from the read only directory /res/raw. But if I try something like:
mediaPlayer = MediaPlayer.create(this, "file://exampleout");
It does not work because create needs an integer as input. I experimented with AssetFileDescriptor, but haven't figured it out yet.
Meanwhile, I want to generate a new midi file and load it in mediaPlayer (chained) to play when the first file finishes playing.
MediaPlayer mediaPlayer = MediaPlayer.create(Activity.this,R.raw.a1);
mediaPlayer.setOnCompletionListener(new musicCompletionListener());
mediaPlayer.start();
private class musicCompletionListener implements OnCompletionListener {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.setDataSource(WHATTOPUTHERE)
mediaPlayer.release();
}
}
My Problem is really how to call the file. I cannot use strings apparantly, and the r.raw directory is not possible due to its read only nature. I feel the solution is not so difficult, but I am just easing into java from c++, any help is much appreciated!
I stored the file in the cache dir, that works!
File output = new File(getCacheDir() + "/exampleout.mid");
And then calling the file:
String filePath = null;
File file = null;
FileInputStream inputStream = null;
try {
filePath = getCacheDir() + "/exampleout.mid";
file = new File(filePath);
inputStream = new FileInputStream(file);
if(inputStream.getFD().valid())
{
System.out.println("Valid!");
}
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
You have to nicely design the Architecture of your app then only you can achieve what you have asked.
According to me you can do the following.
Design an interface with the method midiReady(uri of midi file)
This interface is implemented by your activity which contains mediaplayer
As soon as midi file is generation is completed call the method midiReady(uri of midi file)
Now since your activity implements the interface callback is invoked on your activity and you can set the mediaplayer to play the midi file since in callback you have uri of your midi file.
The above metinoed points are just a faint idea what you can do.With above faint idea you can go forward for implementation.
Hope this will help.
Thanks.

Android MediaPlayer needs file at installation

I am dynamically generating midi files (in cache dir) with an android app.
After generation, I play the file with MediaPlayer within the same app.
When running the app for the first time, it already needs the file to be there in the cache directory (the app crashes). It works on the emulator if I use the filemanager to put a dummy file there first. How can I circumvent this?
I need the app to run on a tablet for the first time, without requiring the file.
I am using these commands now:
try {
filePath = getCacheDir() + "/optimuse" + song + ".mid";
file = new File(filePath);
inputStream = new FileInputStream(file);
if (inputStream.getFD().valid()) {
System.out.println("Valid!");
}
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Is there any way around this?
Thanks!
Maybe check whether the file exists before using it? You can achieve this using the File#exists() method.
First, you use the Context#getFileStreamPath(String) method - where the String is the filename of the file you are trying to access. Then you can call File#exists() on the returned object.

New to Java. Problems reading from file using Context and openFileInput

I've been trying to do this on my own for the past couple hours and am kinda losing it a little.
All I want to do is open a file, read it and display it to the console; that's it.
I'm using eclipse to develop for android 2.3.3.
I have tried using a bunch of different ways with code that I have found here, and on other sites. Here is what I have now and how its all called:
In the OnCreate function:
setContentView(new TestMap(this));
The testMap class:
TestMap(Context context){
super(context);
// might need to be on the panel class
loadTileFile("worldonelayout.txt", context);
in the same class:
private void loadTileFile (String filename, Context context){
FileInputStream input = null;
InputStreamReader reader = null;
char[] inputBuffer = new char[256];
String data = null;
try {
input = context.openFileInput("worldonelayout.txt");
reader = new InputStreamReader(input);
reader.read(inputBuffer);
data = new String(inputBuffer);
System.out.println(data);
Toast.makeText(context, "Text read", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "Text not read", Toast.LENGTH_SHORT).show();
} finally {
try {
input.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This code doesnt work. It always hits the exception.
"/data/data/com.name.somethingiremoved/files/worldonelayout.txt (No such file or directory)".
This happens at the first CATCH. BTW my file is in the root directory: Documents\Eclipse\workspace\project\worldonelayout.txt. I can also see the file in the browser on the left
From what I have seen here and on other sites, it is something to do with the Context class being derived from the Activity? I don't want to have this code in the same class as my activity. Is there a way round this?
If you need anything more from me, let me know.
The open file is looking for a file on the phone's file system, not on the computer's. Its telling you exactly where it expects to find it - on the phone under /data/data/com.name.somethingiremoved/files/worldonelayout.txt

Why do I get FileNotFoundException when I create and try to write to file on Android emulator?

First off, I am not trying to write to the SDCard. I want to write some information to a file that persists between uses of the app. It is essentially a file to hold favorites of the particular user. Here is what the code looks like:
try {
File file = new File("favorites.txt");
if (file.exists()) {
Log.d(TAG, "File does exist.");
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));
}
else {
Log.d(TAG, "File does not exist.");
return favDests;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
When running this code, we always get the "File does not exist." message in our DDMS log.
We have also tried the following code to no avail:
try {
File file = new File(GoLincoln.FAV_DEST_FILE);
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
It is this second portion of code that results in the FileNotFoundException.
I have read multiple tutorials on writing and reading files on Android and I believe I am following them pretty closely, so I am not sure why this code doesn't work successfully. I appreciate any help!
You shouldn't use the File class directly. Use Activity.getCacheDir() to get the cache dir which is specific to your application. Then use new File(cachedir, "filename.tmp") to create the file.
Preferences and SQLLite will both allow you to have persistent data without managing your own files.
To use shared preferences you grab it from your context, then you edit the values like so
mySharedPreferences = context.getSharedPreferences("DatabaseNameWhateverYouWant", 0);
mySharedPreferences.getEditor().putString("MyPreferenceName", "Value").commit();
To get a preference out
mySharedPreferences.getString("MyPreferenceName", "DefaultValue");
This is really the simplest way to do basic preferences, much easier then doing a file. More then strings are supported, most basic data types are available to be added to the Preferences class.

Categories