import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.widget.RemoteViews;
import android.widget.Toast;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.Random;
import java.util.Vector;
private boolean mResumeAfterCall = false;
private boolean mIsSupposedToBePlaying = false;
private boolean mQuietMode = false;
-
+ private AudioManager mAudioManager;
+ // used to track what type of audio focus loss caused the playback to pause
+ private boolean mPausedByTransientLossOfFocus = false;
+
private SharedPreferences mPreferences;
// We use this to distinguish between different cards when saving/restoring playlists.
// This will have to change if we want to support multiple simultaneous cards.
float mCurrentVolume = 1.0f;
@Override
public void handleMessage(Message msg) {
+ MusicUtils.debugLog("mMediaplayerHandler.handleMessage " + msg.what);
switch (msg.what) {
case FADEIN:
if (!isPlaying()) {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
+ MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);
if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
next(true);
} else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
}
};
+ private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
+ public void onAudioFocusChanged(int focusChange) {
+ // AudioFocus is a new feature: focus updates are made verbose on purpose
+ switch (focusChange) {
+ case AudioManager.AUDIOFOCUS_LOSS:
+ Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS");
+ if(isPlaying()) {
+ mPausedByTransientLossOfFocus = false;
+ pause();
+ }
+ break;
+ case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+ case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+ Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT");
+ if(isPlaying()) {
+ mPausedByTransientLossOfFocus = true;
+ pause();
+ }
+ break;
+ case AudioManager.AUDIOFOCUS_GAIN:
+ Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_GAIN");
+ if(!isPlaying() && mPausedByTransientLossOfFocus) {
+ mPausedByTransientLossOfFocus = false;
+ play();
+ }
+ break;
+ default:
+ Log.e(LOGTAG, "Unknown audio focus change code");
+ }
+ }
+ };
+
public MediaPlaybackService() {
}
@Override
public void onCreate() {
super.onCreate();
+
+ mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager.registerAudioFocusListener(mAudioFocusListener);
+ mAudioManager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(),
+ MediaButtonIntentReceiver.class.getName()));
mPreferences = getSharedPreferences("Music", MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE);
mCardId = MusicUtils.getCardId(this);
// release all MediaPlayer resources, including the native player and wakelocks
mPlayer.release();
mPlayer = null;
+
+ mAudioManager.abandonAudioFocus(mAudioFocusListener);
+ mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
// make sure there aren't any other messages coming
mDelayedStopHandler.removeCallbacksAndMessages(null);
if (intent != null) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
+ MusicUtils.debugLog("onStartCommand " + action + " / " + cmd);
if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
next(true);
* Starts playback of a previously opened file.
*/
public void play() {
+ mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN);
+ mAudioManager.registerMediaButtonEventReceiver(new ComponentName(this.getPackageName(),
+ MediaButtonIntentReceiver.class.getName()));
+
if (mPlayer.isInitialized()) {
// if we are at the end of the song, go to the next song first
long duration = mPlayer.duration();
}
public void start() {
+ MusicUtils.debugLog(new Exception("MultiPlayer.start called"));
mMediaPlayer.start();
}
}
}
-
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.println("" + mPlayListLen + " items in queue, currently at index " + mPlayPos);
+ writer.println("Currently loaded:");
+ writer.println(getArtistName());
+ writer.println(getAlbumName());
+ writer.println(getTrackName());
+ writer.println(getPath());
+ writer.println("playing: " + mIsSupposedToBePlaying);
+ writer.println("actual: " + mPlayer.mMediaPlayer.isPlaying());
+ writer.println("shuffle mode: " + mShuffleMode);
+ MusicUtils.debugDump(writer);
+ }
+
private final IBinder mBinder = new ServiceStub(this);
}