MediaPlayer Does not stop when a phone call is received

user2407147 picture user2407147 · Sep 10, 2013 · Viewed 8.5k times · Source

MediaPlayer does not pause when a phone call is received. If anyone can help would be great!

Code:

 public class player1 extends Activity implements Runnable {


private  MediaPlayer mp;
private ProgressBar progressBar;
private ImageButton pauseicon;
private final int NUM_SOUND_FILES = 3;  //*****REPLACE THIS WITH THE ACTUAL NUMBER OF SOUND FILES YOU HAVE*****
private int mfile[] = new int[NUM_SOUND_FILES];
private Random rnd = new Random();

   @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player_1);
        pauseicon = (ImageButton) findViewById(R.id.pauseicon);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        getActionBar().setDisplayHomeAsUpEnabled(true);



        mfile[0] = R.raw.sound01;  //****REPLACE THESE WITH THE PROPER NAMES OF YOUR SOUND FILES
        mfile[1] = R.raw.sound02;  //PLACE THE SOUND FILES IN THE /res/raw/ FOLDER IN YOUR PROJECT*****
        mfile[2] = R.raw.sound03;
        // Listeners
        /**
         * Play button click event
         * plays a song and changes button to pause image
         * pauses a song and changes button to play image
         * */


        try{
             mp = MediaPlayer.create(player1.this, mfile[rnd.nextInt(NUM_SOUND_FILES)]);
             mp.seekTo(0);
             mp.start(); ;         
             progressBar.setVisibility(ProgressBar.VISIBLE);
             progressBar.setProgress(0);
             progressBar.setMax(mp.getDuration());
             new Thread(this).start();

         } catch (IllegalArgumentException e) {
             e.printStackTrace();
         } catch (IllegalStateException e) {
             e.printStackTrace();
         }

       PhoneStateListener phoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (state == TelephonyManager.CALL_STATE_RINGING) {
                    mp.pause();
                } else if(state == TelephonyManager.CALL_STATE_IDLE) {
                    //Not in call: Play music
                } else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
                    //A call is dialing, active or on hold
                }
                super.onCallStateChanged(state, incomingNumber);
            }
          };


        mp.setOnCompletionListener(new OnCompletionListener() {

            public void onCompletion(MediaPlayer mp) {
                pauseicon.setImageResource(R.drawable.playicon);
              mp.seekTo(0);

            }
        });

        pauseicon.setOnClickListener(new View.OnClickListener() {

               public void onClick(View v) {
                  if(mp.isPlaying()) {
                     mp.pause();
                     ((ImageButton) v).setImageResource(R.drawable.playicon);
                  } else {
                     mp.start();
                     ((ImageButton) v).setImageResource(R.drawable.pauseicon);

                  }

               }
            });
   }
   static boolean runThread = true;
   public void run() {
        while ( runThread )  {
              int currentPosition=0;
              int total = mp.getDuration();
              if ( mp != null && currentPosition <= total )  {
              try {
                 Thread.sleep(1000);
                 currentPosition= mp.getCurrentPosition();
              } catch (InterruptedException e) {
                 return;
              } catch (Exception e) {
                 return;
              }            
              progressBar.setProgress(currentPosition);
           } else
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
        runThread = false; 
    }



   @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);


        if (mp != null)
        if(mp.isPlaying())
              mp.stop();

          mp.release();

            return true;
        default:
            return super.onOptionsItemSelected(item);

    }

       }
    @Override 
    public void onBackPressed(){
      if (mp != null){
          if(mp.isPlaying())
              mp.stop();

          mp.release();
      }

      //there is no reason to call super.finish(); here
      //call super.onBackPressed(); and it will finish that activity for you
      super.onBackPressed(); 
    }
    }

New Error

 09-10 19:41:45.250: E/AndroidRuntime(18428): FATAL EXCEPTION: main
09-10 19:41:45.250: E/AndroidRuntime(18428): java.lang.RuntimeException: Unable to pause activity {com.example.mediaplayer/com.example.mediaplayer.player1}: java.lang.IllegalStateException
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3064)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3019)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2997)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.access$800(ActivityThread.java:141)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1273)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.os.Handler.dispatchMessage(Handler.java:99)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.os.Looper.loop(Looper.java:137)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.main(ActivityThread.java:5103)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at java.lang.reflect.Method.invokeNative(Native Method)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at java.lang.reflect.Method.invoke(Method.java:525)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at dalvik.system.NativeStart.main(Native Method)
09-10 19:41:45.250: E/AndroidRuntime(18428): Caused by: java.lang.IllegalStateException
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.media.MediaPlayer.isPlaying(Native Method)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at com.example.mediaplayer.player1.onPause(player1.java:172)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.Activity.performPause(Activity.java:5235)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1233)
09-10 19:41:45.250: E/AndroidRuntime(18428):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3050)
09-10 19:41:45.250: E/AndroidRuntime(18428):    ... 12 more

Answer

MemoryLeak picture MemoryLeak · Feb 6, 2014

You need an AudioManager to manage audio focus. Here is a neat explanation of how it works: http://developer.android.com/training/managing-audio/audio-focus.html.

Here is a simple example showing how to implement it in your app: http://developer.android.com/guide/topics/media/mediaplayer.html#audiofocus.

Even though only one activity can run at any given time, Android is a multi-tasking environment. This poses a particular challenge to applications that use audio, because there is only one audio output and there may be several media services competing for its use. Before Android 2.2, there was no built-in mechanism to address this issue, which could in some cases lead to a bad user experience. For example, when a user is listening to music and another application needs to notify the user of something very important, the user might not hear the notification tone due to the loud music. Starting with Android 2.2, the platform offers a way for applications to negotiate their use of the device's audio output. This mechanism is called Audio Focus.

Example implementation:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
    AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // could not get audio focus.
}


....
....

public void onAudioFocusChange(int focusChange) {
    switch (focusChange) {
        case AudioManager.AUDIOFOCUS_GAIN:
            // resume playback
            if (mMediaPlayer == null) initMediaPlayer();
            else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
            mMediaPlayer.setVolume(1.0f, 1.0f);
            break;

        case AudioManager.AUDIOFOCUS_LOSS:
            // Lost focus for an unbounded amount of time: stop playback and release media player
            if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
            break;

        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            // Lost focus for a short time, but we have to stop
            // playback. We don't release the media player because playback
            // is likely to resume
            if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
            break;

        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
            // Lost focus for a short time, but it's ok to keep playing
            // at an attenuated level
            if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
            break;
    }
}