Android MediaPlayer - switch to next song - java

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.

Related

android mediaplayer url not found

I have some mp3 file in my web server.
I have to use in my app.
My mp3 on server might increase or decrease.(teacher would upload new file or delete old file
My mp3 name is T1.mp3, T2.mp3, T3.mp3, etc.
I have a next button,I hope when mp3 file not found,it would show it is last one.
EX: I am in T40.mp3 I click next to go to T41.mp3, but T41 was delete by teacher,
So, I would show this file not found.
I try it but it can not show and will be shutdown...
how can I do?
this is my code:
private ImageView.OnClickListener nextbtn=new ImageView.OnClickListener(){
#Override
public void onClick(View v) {
String tmp=url; //url=www.XXX......
T++;
tmp+="/"+filename[T]; //filename is number ex:T21.mp3
try {
totalTime=0;
mediaplayer.reset();
mediaplayer.setDataSource(tmp);
mediaplayer.prepare();
totalTime=mediaplayer.getDuration();
if(mediaplayer.getDuration()==0){
//show that mp3 is not found
mytoast("not found");
}
else{
totalTime=mediaplayer.getDuration();
}
mediaplayer.start();
} catch (IllegalStateException e) { }
catch (IOException e) { }
}
};
thanks
You can replace the 2 empty catch blocks with
catch (Throwable e) {
mytoast("not found"); // or something else happened
}
Also, check out this question, it by itself provides a method to check if a file is playable.

MediaRecorder Start Failed Error

I want to recording a call voice but i get MediaRecorder:start failed : -2147483648
It's my call record code block
public void SesKayitBaslat(String number) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/ASesKaydi");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
recorder = new MediaRecorder();
//recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
Log.e("Eror","1");
e.printStackTrace();
} catch (IOException e) {
Log.e("Eror","2");
e.printStackTrace();
}
if(!recordstarted)
{
recorder.start();
recordstarted = true;
}
Log.e("Kayit:", "Başladı");
}
What is my error ? Can anyone help me ? I Tried MediaRecorder.AudioSource.VOICE_CALL AND MediaRecorder.AudioSource.VOICE_COMMUNICATION
When i used Voice_Communication type i didn't get voice of caller.
code 2147483648 refers to MEDIA_ERROR_SYSTEM (low-level system error).
Based on the documentation:
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
In other words, the MediaRecorder instance that you expect to be there might actually not exist anymore since you're within a different BroadcastReceiver instance than the one that created the MediaRecorder. Its not a great idea to perform this task in BroadcastReceiver since it will only execute for 10 seconds after which System could declare app as not responding.
One solution would be to execute this code to Service

JavaFX MediaPlayer doesn't release file handle

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();

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.

Restoring data using AsyncTask

I have a saving method that runs during onPause():
String save = numberValue.getText().toString();
FileInputStream fos;
try {
fos = openFileOutput(FILENAME,Context.MODE_PRIVATE);
fos.write(save.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
Toast.makeText(getBaseContext(), "Save has run", Toast.LENGTH_SHORT).show();
}
and I try to read this file by calling
new Loader().execute(FILENAME);
and my Loader class looks like this:
public class Loader extends AsyncTask<String, Integer, String> {
protected void onPostExecute(String result) {
textview.setText(result);
}
#Override
protected String doInBackground(String... params) {
FileInputStream fis;
String loaded = null;
try {
fis = openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while (fis.read(dataArray) != -1) {
loaded = new String(dataArray);
}
fis.close();
textview.setText(loaded);
return loaded;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return loaded;
}
}
And I have no idea as to why the textview does not get set as the bytes from FILENAME. The idea is that the textview is an increasing number, and this number gets saved when the activity is closed and gets restored to the textview when the activity starts up again.
It does start, I know that because after a few minutes, Watch Dog tells me that a background service from this app is consuming about 50% of CPU. I did check /data/data//files and the file that I write to is there with the correct value.
You probably need to call your Loader from onResume() for this to work.
Why not just save the state you need by using the onSavedInstanceState() method? Writing stuff out to the fileSystem on the onPause method is going to making switching out of your application really slow. From the Activity Documentation regarding the onPause method:
Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
Also, from the android documentation:
In situations where the system needs more memory it may kill paused processes to reclaim resources. Because of this, you should be sure that all of your state is saved by the time you return from this function. In general onSaveInstanceState(Bundle) is used to save per-instance state in the activity and this method is used to store global persistent data (in content providers, files, etc.)
Here's where I got that from.

Categories