web-dev-qa-db-ja.com

Android MediaPlayer-setDataSourceおよびRelease-IllegalStateException

特定のパスでファイルを再生し、assetsフォルダーからファイルを再生するために、独自のMediaPlayerクラスを作成しました。ここにクラスがあります:

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

}

アクティビティから、そのクラスでいくつかのサウンドを再生したいと思います。これが私のコードです:

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){
            }
        }
    }
}

コード内のコメントに記載されているように、アプリは最初のサウンドを再生します。別のサウンドを開始するボタンをクリックすると、次のエラーが発生します。

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)

私のMediaPlayerクラスは大丈夫ですか、それとも状態によっては何か不足していますか?このクラスはリリースを呼び出す唯一のスポットですか、それともアクティビティのどこかに配置する必要がありますか?

誰かが私の間違いを見ますか? mediaPlayerに関するこの問題は、私が試してみるのに丸1日かかりました。

13
user3534643

mp.release();mp.reset();に変更します

public void reset()

MediaPlayerを初期化されていない状態にリセットします。このメソッドを呼び出した後、データソースを設定し、prepare()を呼び出して、再度初期化する必要があります。

パブリックボイドリリース()

このMediaPlayerオブジェクトに関連付けられているリソースを解放します。 MediaPlayerの使用が終了したら、このメソッドを呼び出すことをお勧めします。特に、アプリケーションのアクティビティが一時停止する(そのonPause()メソッドが呼び出される)、または停止される(そのonStop()メソッドが呼び出される)場合は常に、このメソッドを呼び出してMediaPlayerオブジェクトを解放する必要があります。アプリケーションには、オブジェクトを保持する特別なニーズがあります。不要なリソース(メモリやコーデックのインスタンスなど)が保持されることに加えて、MediaPlayerオブジェクトが不要になった場合にこのメソッドをすぐに呼び出さないと、モバイルデバイスのバッテリーが継続的に消費され、他のアプリケーションでは再生できない場合があります。同じコーデックの複数のインスタンスがデバイスでサポートされます。同じコーデックの複数のインスタンスがサポートされている場合でも、不要な複数のインスタンスを同時に使用すると、パフォーマンスの低下が予想されます。

オブジェクトを保持する必要があります。

あなたは簡単な方法でそれを行うことができます

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

私もこの問題を抱えていますが、使用しました:

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

そして停止するには:

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