2013-03-29 50 views
0

希望有人能幫助我在這裏...的Android的MediaController恢復

後拋出IllegalStateException異常在getCurrentPosition()我有流.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通話」),一個電話,中斷音頻。當我切換回我的應用我與呼叫完成後,它拋出一個IllegalStateExceptiongetCurrentPosition()

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) 

任何想法我做錯了嗎?是否有一些狀態需要中斷時保存,然後在應用恢復時進行恢復?

+0

你能解決這個錯誤嗎? –

+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; 
    } 

}