Android MediaController在Resuming之后在getCurrentPosition()中抛出IllegalStateException

时间:2013-03-29 13:54:04

标签: android illegalstateexception mediacontroller

希望有人可以帮助我...

我有一个流.mp3个文件的活动。它看起来像这样:

public class PlayMediaActivity extends Activity implements OnPreparedListener, MediaController.MediaPlayerControl{
  private static final String TAG = "AudioPlayer";

  private MediaPlayer mediaPlayer;
  private MediaController mediaController;

  private Handler handler = new Handler();

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_play_media);

    String title = this.getIntent().getStringExtra("Title");
    String URL = this.getIntent().getStringExtra("URL");

    this.setTitle(title); // Title on top of activity.

    ((TextView)findViewById(R.id.now_playing_text)).setText(title);

    mediaPlayer = new MediaPlayer();
    mediaPlayer.setOnPreparedListener(this);

    mediaController = new MediaController(this);

    try {
      mediaPlayer.setDataSource(URL);
      mediaPlayer.prepare();
      mediaPlayer.start();
    } catch (IOException e) {
      Log.e(TAG, "Could not open file " + title + " for playback.", e);
    }

  }

  @Override
  protected void onStop() {
        super.onStop();
        mediaController.hide();
        mediaPlayer.stop();
        mediaPlayer.release();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    //the MediaController will hide after 3 seconds - tap the screen to make it appear again
    mediaController.show();
    return false;
  }

  //--MediaPlayerControl methods----------------------------------------------------
  public void start() {
    mediaPlayer.start();
  }

  public void pause() {
    mediaPlayer.pause();
  }

  public int getDuration() {
    return mediaPlayer.getDuration();
  }

  public int getCurrentPosition() {
    return mediaPlayer.getCurrentPosition();
  }

  public void seekTo(int i) {
    mediaPlayer.seekTo(i);
  }

  public boolean isPlaying() {
    return mediaPlayer.isPlaying();
  }

  public int getBufferPercentage() {
    return 0;
  }

  public boolean canPause() {
    return true;
  }

  public boolean canSeekBackward() {
    return true;
  }

  public boolean canSeekForward() {
    return true;
  }
  //--------------------------------------------------------------------------------

  public void onPrepared(MediaPlayer mediaPlayer) {
    Log.d(TAG, "onPrepared");
    mediaController.setMediaPlayer(this);
    mediaController.setAnchorView(findViewById(R.id.main_audio_view));

    handler.post(new Runnable() {
      public void run() {
        mediaController.setEnabled(true);
        mediaController.show();
      }
    });
  }


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_play_media, menu);
    return true;
}
}

这似乎很有效,直到我用telnet模拟电话(“gsm call”)并中断音频。当我完成通话后切换回我的应用时,它会从IllegalStateException投出getCurrentPosition()

03-29 13:33:59.896: E/AndroidRuntime(1238): FATAL EXCEPTION: main
03-29 13:33:59.896: E/AndroidRuntime(1238): java.lang.IllegalStateException
03-29 13:33:59.896: E/AndroidRuntime(1238):     at  android.media.MediaPlayer.getCurrentPosition(Native Method)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at com.lcboise.lifechurch.PlayMediaActivity.getCurrentPosition(PlayMediaActivity.java:79)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.widget.MediaController.setProgress(MediaController.java:381)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.widget.MediaController.show(MediaController.java:284)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.widget.MediaController.show(MediaController.java:249)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at com.lcboise.lifechurch.PlayMediaActivity.onTouchEvent(PlayMediaActivity.java:61)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.app.Activity.dispatchTouchEvent(Activity.java:2099)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2194)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1878)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.os.Looper.loop(Looper.java:130)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at android.app.ActivityThread.main(ActivityThread.java:3683)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at java.lang.reflect.Method.invokeNative(Native Method)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at java.lang.reflect.Method.invoke(Method.java:507)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-29 13:33:59.896: E/AndroidRuntime(1238):     at dalvik.system.NativeStart.main(Native Method)

任何想法我做错了什么?是否有某些状态我必须在中断时保存,然后在恢复应用程序时恢复?

1 个答案:

答案 0 :(得分:0)

以下是一个完整正常的MediaPlayerMediaController示例,可在来电时暂停/恢复音频。如果有人发现错误,请与我们联系。

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Menu;
import android.view.MotionEvent;
import android.widget.MediaController;
import android.widget.TextView;

public class PlayMediaActivity extends Activity implements OnPreparedListener, OnErrorListener, MediaController.MediaPlayerControl{
      private static final String TAG = "AudioPlayer";

      private MediaPlayer myMediaPlayer;
      private MediaController mediaController;

      private int seek_position = 0;

      private boolean isPaused = false; // If the player was paused before being stopped.

      private PhoneStateListener phoneStateListener = null;

      ProgressDialog dialog = null;

      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_play_media);

        String title = this.getIntent().getStringExtra("Title");
        String URL = this.getIntent().getStringExtra("URL");

        ((TextView)findViewById(R.id.now_playing_text)).setText(title);

        // Register for phone events so we can pause/restart audio when a call happens.
        phoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (state == TelephonyManager.CALL_STATE_RINGING) {
                    //Incoming call: Pause music
                    boolean s = isPaused;
                    pause();
                    isPaused = s; // Want to restore the state before we paused for phone call.
                } else if(state == TelephonyManager.CALL_STATE_IDLE) {
                    //Not in call: Play music
                    if(isPaused == true) {
                        pause();
                    }
                    else {
                        if(!isPlaying()) { // Only start if it's not currently started.
                            start();
                        }
                    }
                } else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
                    //A call is dialing, active or on hold. Pause music
                    boolean s = isPaused;
                    pause();
                    isPaused = s; // Want to restore the state before we paused for phone call.
                }
                super.onCallStateChanged(state, incomingNumber);
            }
        };

        try {           
            myMediaPlayer = new MediaPlayer();
            myMediaPlayer.setOnPreparedListener(PlayMediaActivity.this);
            myMediaPlayer.setOnErrorListener(PlayMediaActivity.this);

            mediaController = new MediaController(PlayMediaActivity.this);
            mediaController.setMediaPlayer(PlayMediaActivity.this);
            mediaController.setAnchorView(findViewById(R.id.main_audio_view));
            mediaController.setEnabled(true);

            // Inform the user that we are doing something (reading from the network).
            ContextThemeWrapper cw = new ContextThemeWrapper( PlayMediaActivity.this, R.style.AlertDialogTheme );
            dialog = ProgressDialog.show(cw, "", "Loading. Please wait...", true);

            myMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            myMediaPlayer.setDataSource(URL);

            myMediaPlayer.prepareAsync();
        } 
        catch (Exception e) 
        {
            Log.e(TAG, "Could not open file " + title + " for playback.", e);

            if(dialog != null) {
                dialog.dismiss();
            }

            ShowDialog("Unable to play audio. Try again later.");
        }
      }

    private void ShowDialog(String message) {
        // Alert the user something went wrong.
        ContextThemeWrapper cw = new ContextThemeWrapper( PlayMediaActivity.this, R.style.AlertDialogTheme );

        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( cw );

        alertDialogBuilder.setTitle("Oops!");

        // set dialog message
        alertDialogBuilder
                .setMessage(message)
                .setCancelable(true) // Allow back hardkey to dismiss
                .setPositiveButton("OK",new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        // if this button is clicked, close current activity
                        dialog.dismiss();
                        PlayMediaActivity.this.finish();
                    }
                  });

        alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {  // Catch back key press.        
            @Override
            public void onCancel(DialogInterface dialog) {
                //do whatever you want the back key to do
                dialog.dismiss();
                PlayMediaActivity.this.finish();
            }
        });

        // create alert dialog
        AlertDialog alertDialog = alertDialogBuilder.create();

        // show it
        alertDialog.show();
    }

      @Override
      protected void onStop() { // Activity becomes hidden.
            super.onStop();
            mediaController.hide(); // So you don't get the "Leaked activity..." message.

            if(this.isPaused == true) {
                seek_position = myMediaPlayer.getCurrentPosition();
            }
      }

      @Override
      protected void onDestroy() {
           super.onDestroy();

           myMediaPlayer.stop();
           myMediaPlayer.release();
           myMediaPlayer = null;

           // Unregister for phone state information as part of cleanup.
           TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
           if(mgr != null) {
               mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
           }
      }

      @Override
      protected void onResume() {
           super.onResume();

           if(this.isPaused == true) { // Restore the playback position if it was paused.
               myMediaPlayer.seekTo(seek_position);
           }
      }

      @Override
      public boolean onTouchEvent(MotionEvent event) {
        //the MediaController will hide after 3 seconds - tap the screen to make it appear again
        mediaController.show();
        return false;
      }

      //--MediaPlayerControl methods----------------------------------------------------
      public void start() {
          myMediaPlayer.start();

        this.isPaused = false;
      }

      public void pause() {
          myMediaPlayer.pause();

        this.isPaused = true;
      }

      public int getDuration() {
        return myMediaPlayer.getDuration();
      }

      public int getCurrentPosition() {
        return myMediaPlayer.getCurrentPosition();
      }

      public void seekTo(int i) {
        myMediaPlayer.seekTo(i);
      }

      public boolean isPlaying() {
        return myMediaPlayer.isPlaying();
      }

      public int getBufferPercentage() {
        return 0;
      }

      public boolean canPause() {
        return true;
      }

      public boolean canSeekBackward() {
        return true;
      }

      public boolean canSeekForward() {
        return true;
      }
      //--------------------------------------------------------------------------------

      public void onPrepared(MediaPlayer mediaPlayer) {
          Log.d(TAG, "onPrepared");

          if(dialog != null) {
              dialog.dismiss();
          }

          // Show and play the media AFTER it's been prepared.
          mediaController.show();       
          mediaPlayer.start();

          // Register for call state information AFTER we have started the media. This registration fires
          // the IDLE event, which would try and start the media. This causes a error in the media player
          // because we are "prepared" yet.
          TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
          if(mgr != null) {
              mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
          }
      }

      public boolean onError(MediaPlayer mp, int what, int extra) {

          if(dialog != null) {
            dialog.dismiss();
          }

          ShowDialog("Unable to play audio. Try again later.");

          return true;
      }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_play_media, menu);
        return true;
    }

}