2015-03-16 15 views
8

Ho scritto la mia classe MediaPlayer per riprodurre file su un percorso specifico e riprodurre file dalla cartella delle risorse. Ecco la classe:Android MediaPlayer - setDataSource e Release - IllegalStateException

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

} 

Voglio riprodurre più suoni con quella classe da un'attività. Qui è il mio codice:

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'applicazione riproduce il primo suono come detto nei miei commenti nel mio codice. Quando si fa clic su un pulsante che dovrebbe iniziare un altro suono ottengo il seguente errore:

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) 

È la mia classe MediaPlayer bene o mi sto perdendo qualcosa a seconda dello stato? Questa classe è l'unico posto in cui chiamare la versione o devo metterla da qualche parte nella mia attività?

Qualcuno vede il mio errore? Questo problema con il mediaplayer mi ha portato un giorno intero di provare, spero che tu mi possa aiutare ...

+1

sicura fermarsi la prima canzone prima di usare 'mediaPlayer.stop();' e resettarla usando 'mediaPlayer.reset()' e quindi impostare la nuova sorgente di dati e avviare il riproduzione! – Gavin

risposta

17

cambiamento mp.release();-mp.reset();

ripristino public void()

Resets the MediaPlayer to its uninitialized state. After calling this method, you will have to initialize it again by setting the data source and calling prepare().

pubblico rilascio void()

Releases resources associated with this MediaPlayer object. It is considered good practice to call this method when you're done using the MediaPlayer. In particular, whenever an Activity of an application is paused (its onPause() method is called), or stopped (its onStop() method is called), this method should be invoked to release the MediaPlayer object, unless the application has a special need to keep the object around. In addition to unnecessary resources (such as memory and instances of codecs) being held, failure to call this method immediately if a MediaPlayer object is no longer needed may also lead to continuous battery consumption for mobile devices, and playback failure for other applications if no multiple instances of the same codec are supported on a device. Even if multiple instances of the same codec are supported, some performance degradation may be expected when unnecessary multiple instances are used at the same time.

è necessario mantenere l'oggetto attorno.

Si può fare in modo semplice

 MediaPlayer mediaPlayer = new MediaPlayer(); 
     mediaPlayer.setDataSource(context, ringtone); 
     mediaPlayer.setAudioStreamType(AudioManager.STREAM_MEDIA); 
     mediaPlayer.prepare(); 
     mediaPlayer.start(); 
0

anch'io ho questo problema, ma ho usato:

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

e di smettere:

public void stopPlayer(){ 
    if(myPlayer!= null && myPlayer.isPlaying()){ 
     myPlayer.stop(); 
     myPlayer = null; 
    }else{ 
     myPlayer = null; 
    } 
} 
Problemi correlati