J'ai écrit ma propre classe MediaPlayer pour lire des fichiers sur un chemin spécifique et pour lire des fichiers du dossier des ressources. Voici la classe:
public class CMediaPlayer extends MediaPlayer{
public void play(String audioPath){
this.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
File f = new File(audioPath);
if(f.exists()){
try{
FileInputStream fis = new FileInputStream(f);
FileDescriptor fileD = fis.getFD();
this.setDataSource(fileD);
this.prepare();
}catch(IOException e){
}
this.start();
}
}
public void play(AssetFileDescriptor descriptor){
this.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
try {
this.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
this.prepare();
}catch (IOException e){
}
this.start();
}
}
Je veux jouer plusieurs sons avec cette classe d'une activité. Voici mon code:
public class playGame extends Activity {
//a lot of variables
CMediaPlayer mediaPlayer; //declare my mediaplayer
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK ) {
//release??????
Intent myIntent = new Intent(getBaseContext(), startView.class);
startActivity(myIntent);
}
return super.onKeyDown(keyCode, event);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_question2);
mediaPlayer = new CMediaPlayer(); //define my mediaplayer
//stuff
}
//more variables
public void playQuestion(File question){
//stuff
TextView myTextView = (TextView) findViewById(R.id.textViewQuestion);
//stuff
myTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPlayer.play(pathSoundQuestion); //play sound when clicked
}
});
//stuff
myImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPlayer.play(pathSoundQuestion); //play sound when clicked
}
});
//stuff
mediaPlayer.play(pathSoundQuestion); //plays sound immediatly, first played sound (works fine)
//button1
Button myButton = (Button) findViewById(R.id.button1);
//stuff
myButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
if(lastClickedButton == v){
//stuff
return;
}
//stuff
mediaPlayer.play(pathAudio1); //play sound when clicked (error)
}
});
//button2
myButton = (Button) findViewById(R.id.button2);
//stuff
myButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
if(lastClickedButton == v){
//stuff
return;
}
//stuff
mediaPlayer.play(pathAudio2); //play sound, same problem
}
});
//goes on like this some more times...
}
public void logIn(View v, String right){
//stuff
if(right.equals("true")){
//stuff
try {
AssetFileDescriptor descriptor = getAssets().openFd("Right");
mediaPlayer.play(descriptor); //play sound from assets
Intent myIntent = new Intent(getApplication(), playGame.class);
startActivity(myIntent);
}catch (IOException e){
}
}else{
//stuff
try {
AssetFileDescriptor descriptor = getAssets().openFd("Wrong");
mediaPlayer.play(descriptor); //play sound from assets
Intent myIntent = new Intent(getApplication(), playGame.class);
startActivity(myIntent);
}catch (IOException e){
}
}
}
}
L'application lit le premier son comme mentionné dans mes commentaires dans mon code. Lorsque je clique sur un bouton qui devrait déclencher un autre son, le message d'erreur suivant s'affiche:
03-16 23:07:38.478 13646-13646/com.example.cello.myownquiz E/AndroidRuntime﹕ FATAL EXCEPTION: main
Java.lang.IllegalStateException
at Android.media.MediaPlayer.setDataSource(Native Method)
at Android.media.MediaPlayer.setDataSource(MediaPlayer.Java:1005)
Ma classe MediaPlayer est-elle correcte ou manque-t-il quelque chose en fonction de l'état? Cette classe est-elle le seul endroit où appeler la libération ou dois-je la mettre quelque part dans mon activité aussi?
Est-ce que quelqu'un voit mon erreur? Ce problème avec le mediaPlayer m'a pris toute une journée d'essayer, j'espère que vous pourrez m'aider ...
remplacez mp.release();
par mp.reset();
public void reset ()
Réinitialise le MediaPlayer à son état non initialisé. Après avoir appelé cette méthode, vous devrez l'initialiser à nouveau en définissant la source de données et en appelant la méthode prepare ().
libération publique publique ()
Libère les ressources associées à cet objet MediaPlayer. Il est recommandé d’appeler cette méthode lorsque vous avez terminé d’utiliser MediaPlayer. En particulier, chaque fois qu’une activité d’une application est suspendue (sa méthode onPause () est appelée) ou arrêtée (sa méthode onStop () est appelée), cette méthode doit être appelée pour libérer l’objet MediaPlayer, sauf si l’application a un besoin particulier de garder l'objet autour . En plus des ressources inutiles (telles que la mémoire et les instances de codecs), l’impossibilité d’appeler cette méthode immédiatement si un objet MediaPlayer n’est plus nécessaire peut également entraîner une consommation de batterie continue pour les périphériques mobiles et une défaillance de lecture pour d’autres applications si aucune plusieurs instances du même codec sont prises en charge sur un périphérique. Même si plusieurs instances du même codec sont prises en charge, une dégradation des performances peut être attendue lorsque plusieurs instances inutiles sont utilisées en même temps.
Vous devez garder l'objet autour.
Vous pouvez le faire d'une manière simple
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(context, ringtone);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MEDIA);
mediaPlayer.prepare();
mediaPlayer.start();
moi aussi j'ai ce problème mais j'ai utilisé:
public void play(String name){
try {
AssetFileDescriptor afd = getAssets().openFd(name);
if(myPlayer == null){
myPlayer = new MediaPlayer();
}
myPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
myPlayer.prepare();
myPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
et pour arrêter:
public void stopPlayer(){
if(myPlayer!= null && myPlayer.isPlaying()){
myPlayer.stop();
myPlayer = null;
}else{
myPlayer = null;
}
}