webentwicklung-frage-antwort-db.com.de

Android MediaPlayer - setDataSource und Release - IllegalStateException

Ich habe meine eigene MediaPlayer-Klasse geschrieben, um Dateien unter einem bestimmten Pfad abzuspielen und Dateien aus dem Assets-Ordner wiederzugeben. Hier ist die Klasse:

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

}

Ich möchte mit dieser Klasse mehrere Sounds aus einer Aktivität spielen. Hier ist mein 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){
            }
        }
    }
}

Die App gibt den ersten Ton wieder, wie in meinen Kommentaren in meinem Code erwähnt. Wenn ich auf eine Schaltfläche klicke, die einen anderen Ton starten soll, erhalte ich die folgende Fehlermeldung:

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)

Ist meine MediaPlayer-Klasse in Ordnung oder fehlt mir je nach Status etwas? Ist diese Klasse die einzige Stelle, an der die Freigabe erfolgt, oder muss ich sie auch irgendwo in meiner Aktivität platzieren?

Kann jemand meinen Fehler sehen? Dieses Problem mit dem mediaPlayer hat mich einen ganzen Tag lang versucht, ich hoffe, Sie können mir helfen ...

11
user3534643

mp.release(); in mp.reset(); ändern 

public void reset () 

Setzt den MediaPlayer in den nicht initialisierten Zustand zurück. Nach dem Aufruf dieser Methode müssen Sie sie erneut initialisieren, indem Sie die Datenquelle festlegen und "prepare ()" aufrufen.

öffentliche void release () 

Gibt Ressourcen frei, die diesem MediaPlayer-Objekt zugeordnet sind. Es empfiehlt sich, diese Methode aufzurufen, wenn Sie mit dem MediaPlayer fertig sind. Immer wenn eine Activity einer Anwendung angehalten wird (ihre onPause () - Methode wird aufgerufen) oder gestoppt (ihre onStop () - Methode wird aufgerufen), sollte diese Methode aufgerufen werden, um das MediaPlayer-Objekt freizugeben, es sei denn, die Anwendung hat dies ein besonderes Bedürfnis, das Objekt um zu halten. Neben unnötigen Ressourcen (wie Speicher und Codec-Instanzen) kann ein nicht sofortiger Aufruf dieser Methode, wenn ein MediaPlayer-Objekt nicht mehr benötigt wird, zu einem fortlaufenden Batterieverbrauch für mobile Geräte und zu Wiedergabefehlern für andere Anwendungen führen, wenn dies nicht der Fall ist Mehrere Instanzen desselben Codecs werden auf einem Gerät unterstützt. Selbst wenn mehrere Instanzen desselben Codecs unterstützt werden, kann mit einer Leistungsverschlechterung gerechnet werden, wenn nicht mehrere Instanzen gleichzeitig verwendet werden. 

Du musst das Objekt herumliegen lassen.

Sie können es auf einfache Weise tun 

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

ich habe auch dieses Problem, aber ich habe verwendet:

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

und zu stoppen:

public void stopPlayer(){
    if(myPlayer!= null && myPlayer.isPlaying()){
        myPlayer.stop();
        myPlayer = null;
    }else{
        myPlayer = null;
    }
}
0
Omar Othman