特定のパスでファイルを再生し、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日かかりました。
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();
私もこの問題を抱えていますが、使用しました:
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;
}
}