package me.wcy.music.service; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.support.annotation.Nullable; import android.text.format.DateUtils; import android.util.Log; import java.io.IOException; import java.util.List; import java.util.Random; import me.wcy.music.application.AppCache; import me.wcy.music.application.Notifier; import me.wcy.music.constants.Actions; import me.wcy.music.enums.PlayModeEnum; import me.wcy.music.model.Music; import me.wcy.music.receiver.NoisyAudioStreamReceiver; import me.wcy.music.utils.MusicUtils; import me.wcy.music.utils.Preferences; /** * 音乐播放后台服务 * Created by wcy on 2015/11/27. */ public class PlayService extends Service implements MediaPlayer.OnCompletionListener, AudioManager.OnAudioFocusChangeListener { private static final String TAG = "Service"; private static final long TIME_UPDATE = 100L; private List<Music> mMusicList; private MediaPlayer mPlayer = new MediaPlayer(); private IntentFilter mNoisyFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); private NoisyAudioStreamReceiver mNoisyReceiver = new NoisyAudioStreamReceiver(); private Handler mHandler = new Handler(); private AudioManager mAudioManager; private OnPlayerEventListener mListener; // 正在播放的歌曲[本地|网络] private Music mPlayingMusic; // 正在播放的本地歌曲的序号 private int mPlayingPosition; private boolean isPausing; private boolean isPreparing; private long quitTimerRemain; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: " + getClass().getSimpleName()); mMusicList = AppCache.getMusicList(); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); mPlayer.setOnCompletionListener(this); Notifier.init(this); } @Nullable @Override public IBinder onBind(Intent intent) { return new PlayBinder(); } public static void startCommand(Context context, String action) { Intent intent = new Intent(context, PlayService.class); intent.setAction(action); context.startService(intent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null && intent.getAction() != null) { switch (intent.getAction()) { case Actions.ACTION_MEDIA_PLAY_PAUSE: playPause(); break; case Actions.ACTION_MEDIA_NEXT: next(); break; case Actions.ACTION_MEDIA_PREVIOUS: prev(); break; } } return START_NOT_STICKY; } /** * 扫描音乐 */ public void updateMusicList() { MusicUtils.scanMusic(this, mMusicList); if (!mMusicList.isEmpty()) { updatePlayingPosition(); mPlayingMusic = (mPlayingMusic == null) ? mMusicList.get(mPlayingPosition) : mPlayingMusic; } } @Override public void onCompletion(MediaPlayer mp) { next(); } public OnPlayerEventListener getOnPlayEventListener() { return mListener; } public void setOnPlayEventListener(OnPlayerEventListener listener) { mListener = listener; } public void play(int position) { if (mMusicList.isEmpty()) { return; } if (position < 0) { position = mMusicList.size() - 1; } else if (position >= mMusicList.size()) { position = 0; } mPlayingPosition = position; Music music = mMusicList.get(mPlayingPosition); Preferences.saveCurrentSongId(music.getId()); play(music); } public void play(Music music) { mPlayingMusic = music; try { mPlayer.reset(); mPlayer.setDataSource(music.getPath()); mPlayer.prepareAsync(); isPreparing = true; mPlayer.setOnPreparedListener(mPreparedListener); if (mListener != null) { mListener.onChange(music); } Notifier.showPlay(music); } catch (IOException e) { e.printStackTrace(); } } private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { isPreparing = false; start(); } }; public void playPause() { if (isPreparing()) { return; } if (isPlaying()) { pause(); } else if (isPausing()) { resume(); } else { play(getPlayingPosition()); } } private void start() { mPlayer.start(); isPausing = false; mHandler.post(mBackgroundRunnable); Notifier.showPlay(mPlayingMusic); mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); registerReceiver(mNoisyReceiver, mNoisyFilter); } private void pause() { if (!isPlaying()) { return; } mPlayer.pause(); isPausing = true; mHandler.removeCallbacks(mBackgroundRunnable); Notifier.showPause(mPlayingMusic); mAudioManager.abandonAudioFocus(this); unregisterReceiver(mNoisyReceiver); if (mListener != null) { mListener.onPlayerPause(); } } private void resume() { if (!isPausing()) { return; } start(); if (mListener != null) { mListener.onPlayerResume(); } } public void next() { if (mMusicList.isEmpty()) { return; } PlayModeEnum mode = PlayModeEnum.valueOf(Preferences.getPlayMode()); switch (mode) { case SHUFFLE: mPlayingPosition = new Random().nextInt(mMusicList.size()); play(mPlayingPosition); break; case SINGLE: play(mPlayingPosition); break; case LOOP: default: play(mPlayingPosition + 1); break; } } public void prev() { if (mMusicList.isEmpty()) { return; } PlayModeEnum mode = PlayModeEnum.valueOf(Preferences.getPlayMode()); switch (mode) { case SHUFFLE: mPlayingPosition = new Random().nextInt(mMusicList.size()); play(mPlayingPosition); break; case SINGLE: play(mPlayingPosition); break; case LOOP: default: play(mPlayingPosition - 1); break; } } /** * 跳转到指定的时间位置 * * @param msec 时间 */ public void seekTo(int msec) { if (isPlaying() || isPausing()) { mPlayer.seekTo(msec); if (mListener != null) { mListener.onPublish(msec); } } } public boolean isPlaying() { return mPlayer != null && mPlayer.isPlaying(); } public boolean isPausing() { return mPlayer != null && isPausing; } public boolean isPreparing() { return mPlayer != null && isPreparing; } /** * 获取正在播放的本地歌曲的序号 */ public int getPlayingPosition() { return mPlayingPosition; } /** * 获取正在播放的歌曲[本地|网络] */ public Music getPlayingMusic() { return mPlayingMusic; } /** * 删除或下载歌曲后刷新正在播放的本地歌曲的序号 */ public void updatePlayingPosition() { int position = 0; long id = Preferences.getCurrentSongId(); for (int i = 0; i < mMusicList.size(); i++) { if (mMusicList.get(i).getId() == id) { position = i; break; } } mPlayingPosition = position; Preferences.saveCurrentSongId(mMusicList.get(mPlayingPosition).getId()); } private Runnable mBackgroundRunnable = new Runnable() { @Override public void run() { if (isPlaying() && mListener != null) { mListener.onPublish(mPlayer.getCurrentPosition()); } mHandler.postDelayed(this, TIME_UPDATE); } }; @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_LOSS: case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: pause(); break; } } public void startQuitTimer(long milli) { stopQuitTimer(); if (milli > 0) { quitTimerRemain = milli + DateUtils.SECOND_IN_MILLIS; mHandler.post(mQuitRunnable); } else { quitTimerRemain = 0; if (mListener != null) { mListener.onTimer(quitTimerRemain); } } } private void stopQuitTimer() { mHandler.removeCallbacks(mQuitRunnable); } private Runnable mQuitRunnable = new Runnable() { @Override public void run() { quitTimerRemain -= DateUtils.SECOND_IN_MILLIS; if (quitTimerRemain > 0) { if (mListener != null) { mListener.onTimer(quitTimerRemain); } mHandler.postDelayed(this, DateUtils.SECOND_IN_MILLIS); } else { AppCache.clearStack(); stop(); } } }; @Override public void onDestroy() { AppCache.setPlayService(null); super.onDestroy(); Log.i(TAG, "onDestroy: " + getClass().getSimpleName()); } public void stop() { pause(); stopQuitTimer(); mPlayer.reset(); mPlayer.release(); mPlayer = null; Notifier.cancelAll(); AppCache.setPlayService(null); stopSelf(); } public class PlayBinder extends Binder { public PlayService getService() { return PlayService.this; } } }