package cn.bingoogolapple.media.service; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; import android.widget.RemoteViews; import java.io.IOException; import java.util.ArrayList; import cn.bingoogolapple.media.App; import cn.bingoogolapple.media.R; import cn.bingoogolapple.media.model.MediaFile; import cn.bingoogolapple.media.ui.activity.AudioActivity; import cn.bingoogolapple.media.util.Logger; import cn.bingoogolapple.media.util.SPUtil; /** * 作者:王浩 邮件:bingoogolapple@gmail.com * 创建时间:15/9/20 下午4:48 * 描述: */ public class AudioService extends Service { private static final String TAG = AudioService.class.getSimpleName(); public static final String EXTRA_MEDIA_FILES = "EXTRA_MEDIA_FILES"; public static final String EXTRA_CURRENT_MEDIA_FILE_POSITION = "EXTRA_CURRENT_MEDIA_FILE_POSITION"; public static final String EXTRA_TOTAL_MEDIA_FILE = "EXTRA_TOTAL_MEDIA_FILE"; public static final String EXTRA_MEDIA_FILE = "EXTRA_MEDIA_FILE"; public static final String ACTION_AUDIO_PREPARED = "ACTION_AUDIO_PREPARED"; public static final String ACTION_AUDIO_COMPLETION = "ACTION_AUDIO_COMPLETION"; public static final String ACTION_AUDIO_UPDATE_ICON = "ACTION_AUDIO_UPDATE_ICON"; public static final String EXTRA_NOTIFICATION_TYPE = "EXTRA_NOTIFICATION_TYPE"; public static final String EXTRA_IS_FROM_NOTIFICATION = "EXTRA_IS_FROM_NOTIFICATION"; public static final int REQUESTCODE_PRE = 0; public static final int REQUESTCODE_PLAY = 1; public static final int REQUESTCODE_NEXT = 2; public static final int REQUESTCODE_CONTAINER = 3; private static final String SP_REPEAT_MODE = "SP_REPEAT_MODE"; private AudioBinder mAudioBinder; private MediaPlayer mMediaPlayer; private ArrayList<MediaFile> mMediaFiles; private int mCurrentMediaFilePosition; private MediaFile mCurrentMediaFile; private RepeatMode mRepeatMode = RepeatMode.Order; private LocalBroadcastManager mLocalBroadcastManager; @Override public void onCreate() { super.onCreate(); Logger.i(TAG, "onCreate"); mLocalBroadcastManager = LocalBroadcastManager.getInstance(this); mAudioBinder = new AudioBinder(); mRepeatMode = RepeatMode.values()[SPUtil.getInt(SP_REPEAT_MODE)]; } @Nullable @Override public IBinder onBind(Intent intent) { Logger.i(TAG, "onBind"); return mAudioBinder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Logger.i(TAG, "onStartCommand"); if (intent != null && intent.getExtras() != null) { if (intent.getExtras().getBoolean(EXTRA_IS_FROM_NOTIFICATION)) { switch (intent.getExtras().getInt(AudioService.EXTRA_NOTIFICATION_TYPE)) { case AudioService.REQUESTCODE_PRE: mAudioBinder.pre(); break; case AudioService.REQUESTCODE_PLAY: if (mAudioBinder.isPlaying()) { mAudioBinder.pause(); } else { mAudioBinder.start(); } break; case AudioService.REQUESTCODE_NEXT: mAudioBinder.next(); break; case AudioService.REQUESTCODE_CONTAINER: notifyPrepared(); break; } } else { mCurrentMediaFilePosition = intent.getExtras().getInt(EXTRA_CURRENT_MEDIA_FILE_POSITION); mMediaFiles = intent.getExtras().getParcelableArrayList(EXTRA_MEDIA_FILES); mAudioBinder.playAudio(mCurrentMediaFilePosition); } } return START_STICKY; } @Override public void onDestroy() { Logger.i(TAG, "onDestroy"); super.onDestroy(); } private void notifyPrepared() { Intent intent = new Intent(ACTION_AUDIO_PREPARED); intent.putExtra(EXTRA_MEDIA_FILE, mCurrentMediaFile); mLocalBroadcastManager.sendBroadcast(intent); } private void notifyCompletion() { Intent intent = new Intent(ACTION_AUDIO_COMPLETION); intent.putExtra(EXTRA_MEDIA_FILE, mCurrentMediaFile); mLocalBroadcastManager.sendBroadcast(intent); } private void notifyUpdateIcon() { Intent intent = new Intent(ACTION_AUDIO_UPDATE_ICON); intent.putExtra(EXTRA_CURRENT_MEDIA_FILE_POSITION, mCurrentMediaFilePosition); intent.putExtra(EXTRA_TOTAL_MEDIA_FILE, mMediaFiles.size()); mLocalBroadcastManager.sendBroadcast(intent); sendNotification(); } private MediaPlayer.OnPreparedListener mOnPreparedListener = new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { notifyPrepared(); mAudioBinder.start(); } }; private MediaPlayer.OnCompletionListener mOnCompletionListener = new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { notifyCompletion(); switch (mRepeatMode) { case Order: mAudioBinder.next(); break; case SingleRepeat: mAudioBinder.playAudio(mCurrentMediaFilePosition); break; case AllRepeat: if (mCurrentMediaFilePosition == mMediaFiles.size() - 1) { mAudioBinder.playAudio(0); } else { mAudioBinder.next(); } break; } } }; private void sendNotification() { Intent preIntent = new Intent(this, AudioService.class); Bundle preBundle = new Bundle(); preBundle.putBoolean(EXTRA_IS_FROM_NOTIFICATION, true); preBundle.putInt(AudioService.EXTRA_NOTIFICATION_TYPE, AudioService.REQUESTCODE_PRE); preIntent.putExtras(preBundle); // 如果有多个PendingIntent,必须把requestCode设置成不同 PendingIntent prePendingIntent = PendingIntent.getService(this, AudioService.REQUESTCODE_PRE, preIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent playIntent = new Intent(this, AudioService.class); Bundle playBundle = new Bundle(); playBundle.putBoolean(EXTRA_IS_FROM_NOTIFICATION, true); playBundle.putInt(AudioService.EXTRA_NOTIFICATION_TYPE, AudioService.REQUESTCODE_PLAY); playIntent.putExtras(playBundle); // 也可以通过getService方法获取PendingIntent,在onStartCommand方法中处理 PendingIntent playPendingIntent = PendingIntent.getService(this, AudioService.REQUESTCODE_PLAY, playIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent nextIntent = new Intent(this, AudioService.class); Bundle nextBundle = new Bundle(); nextBundle.putBoolean(EXTRA_IS_FROM_NOTIFICATION, true); nextBundle.putInt(AudioService.EXTRA_NOTIFICATION_TYPE, AudioService.REQUESTCODE_NEXT); nextIntent.putExtras(nextBundle); PendingIntent nextPendingIntent = PendingIntent.getService(this, AudioService.REQUESTCODE_NEXT, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent containerIntent = new Intent(this, AudioActivity.class); Bundle containerBundle = new Bundle(); containerBundle.putBoolean(EXTRA_IS_FROM_NOTIFICATION, true); containerBundle.putInt(AudioService.EXTRA_NOTIFICATION_TYPE, AudioService.REQUESTCODE_CONTAINER); containerIntent.putExtras(containerBundle); PendingIntent containerPendingIntent = PendingIntent.getActivity(this, AudioService.REQUESTCODE_CONTAINER, containerIntent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteView = new RemoteViews(getPackageName(), R.layout.notification_audio); remoteView.setOnClickPendingIntent(R.id.iv_audio_pre, prePendingIntent); remoteView.setOnClickPendingIntent(R.id.iv_audio_play, playPendingIntent); remoteView.setOnClickPendingIntent(R.id.iv_audio_next, nextPendingIntent); remoteView.setOnClickPendingIntent(R.id.ll_audio_container, containerPendingIntent); remoteView.setTextViewText(R.id.tv_audio_name, mCurrentMediaFile.name); remoteView.setTextViewText(R.id.tv_audio_artist, mCurrentMediaFile.artist); remoteView.setImageViewResource(R.id.iv_audio_play, mAudioBinder.isPlaying() ? R.drawable.selector_btn_audio_pause : R.drawable.selector_btn_audio_play); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setOngoing(true); // 必须制定图标,否则不会显示该条信息 builder.setSmallIcon(R.mipmap.ic_launcher); builder.setTicker(mCurrentMediaFile.name); builder.setWhen(System.currentTimeMillis()); builder.setContent(remoteView); // App.getInstance().removeNotification(1000); App.getInstance().addNotification(1000, builder.build()); // startForeground(1000, builder.build()); // stopForeground(true); } public final class AudioBinder extends Binder { public void playAudio(int position) { if (mMediaFiles != null && mMediaFiles.size() > 0 && position >= 0 && position <= mMediaFiles.size() - 1) { mCurrentMediaFilePosition = position; mCurrentMediaFile = mMediaFiles.get(mCurrentMediaFilePosition); if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } mMediaPlayer = new MediaPlayer(); mMediaPlayer.setOnPreparedListener(mOnPreparedListener); mMediaPlayer.setOnCompletionListener(mOnCompletionListener); try { mMediaPlayer.setDataSource(mCurrentMediaFile.path); mMediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); } } } public void start() { if (mMediaPlayer != null) { mMediaPlayer.start(); } notifyUpdateIcon(); } public void pause() { if (mMediaPlayer != null) { mMediaPlayer.pause(); } notifyUpdateIcon(); } public void pre() { playAudio(mCurrentMediaFilePosition - 1); } public void next() { playAudio(mCurrentMediaFilePosition + 1); } public void seekTo(int msec) { if (mMediaPlayer != null) { mMediaPlayer.seekTo(msec); } } public boolean isPlaying() { return mMediaPlayer != null ? mMediaPlayer.isPlaying() : false; } public int getCurrentPosition() { return mMediaPlayer != null ? mMediaPlayer.getCurrentPosition() : 0; } public int getDuration() { return mMediaPlayer != null ? mMediaPlayer.getDuration() : 0; } public void switchPlayMode() { switch (mRepeatMode) { case Order: mRepeatMode = RepeatMode.SingleRepeat; break; case SingleRepeat: mRepeatMode = RepeatMode.AllRepeat; break; case AllRepeat: mRepeatMode = RepeatMode.Order; break; } SPUtil.putInt(SP_REPEAT_MODE, mRepeatMode.ordinal()); } public RepeatMode getRepeatMode() { return mRepeatMode; } } public enum RepeatMode { Order, SingleRepeat, AllRepeat } }