/** * Called by AudioManager on audio focus changes. Implementation of {@link * AudioManager.OnAudioFocusChangeListener} */ @Override public void onAudioFocusChange(int focusChange) { LogHelper.d(TAG, "onAudioFocusChange. focusChange=", focusChange); if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // We have gained focus: mAudioFocus = AUDIO_FOCUSED; } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // We have lost focus. If we can duck (low playback volume), we can keep playing. // Otherwise, we need to pause the playback. boolean canDuck = focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK; mAudioFocus = canDuck ? AUDIO_NO_FOCUS_CAN_DUCK : AUDIO_NO_FOCUS_NO_DUCK; // If we are playing, we need to reset media player by calling configMediaPlayerState // with mAudioFocus properly set. if (mState == PlaybackStateCompat.STATE_PLAYING && !canDuck) { // If we don't have audio focus and can't duck, we save the information that // we were playing, so that we can resume playback once we get the focus back. mPlayOnFocusGain = true; } } else { LogHelper.e(TAG, "onAudioFocusChange: Ignoring unsupported focusChange: ", focusChange); } configMediaPlayerState(); }
/** * Called when there's an error playing media. When this happens, the media player goes to the * Error state. We warn the user about the error and reset the media player. * * @see OnErrorListener */ @Override public boolean onError(MediaPlayer mp, int what, int extra) { LogHelper.e(TAG, "Media player error: what=" + what + ", extra=" + extra); if (mCallback != null) { mCallback.onError("MediaPlayer error " + what + " (" + extra + ")"); } return true; // true indicates we handled the error }
@Override public void play(QueueItem item) { mPlayOnFocusGain = true; tryToGetAudioFocus(); registerAudioNoisyReceiver(); String mediaId = item.getDescription().getMediaId(); boolean mediaHasChanged = !TextUtils.equals(mediaId, mCurrentMediaId); if (mediaHasChanged) { mCurrentPosition = 0; mCurrentMediaId = mediaId; } if (mState == PlaybackStateCompat.STATE_PAUSED && !mediaHasChanged && mMediaPlayer != null) { configMediaPlayerState(); } else { mState = PlaybackStateCompat.STATE_STOPPED; relaxResources(false); // release everything except MediaPlayer MediaMetadataCompat track = mMusicProvider.getMusic( MediaIDHelper.extractMusicIDFromMediaID(item.getDescription().getMediaId())); String source = MusicProvider.getTrackSource(track.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)); try { createMediaPlayerIfNeeded(); mState = PlaybackStateCompat.STATE_BUFFERING; mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mMediaPlayer.setDataSource(source); // Starts preparing the media player in the background. When // it's done, it will call our OnPreparedListener (that is, // the onPrepared() method on this class, since we set the // listener to 'this'). Until the media player is prepared, // we *cannot* call start() on it! mMediaPlayer.prepareAsync(); // If we are streaming from the internet, we want to hold a // Wifi lock, which prevents the Wifi radio from going to // sleep while the song is playing. mWifiLock.acquire(); if (mCallback != null) { mCallback.onPlaybackStatusChanged(mState); } } catch (IOException ex) { LogHelper.e(TAG, ex, "Exception playing song"); if (mCallback != null) { mCallback.onError(ex.getMessage()); } } } }