package com.airplayer.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.audiofx.BassBoost;
import android.media.audiofx.Equalizer;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.airplayer.fragment.child.EqualizerFragment;
import com.airplayer.model.Song;
import com.airplayer.notification.AirNotification;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ZiyiTsang on 15/6/10.
* <br>Service to control play music actions</br>
*/
public class PlayMusicService extends Service {
public static final String TAG = "PlayMusicService";
// ===== broadcast action and extra keys - value =====
/**
* <br>Broadcast intent action</br>
*/
public static final String PLAY_STATE_CHANGE = "com.airplayer.PLAY_STATE_CHANGE";
/**
* <br>Broadcast intent action</br>
*/
public static final String PLAY_STATE_KEY = "com.airplayer.PLAY_STATE_CHANGE.PLAY_STATE_KEY";
/**
* <br>Broadcast intent action</br>
*/
public static final String NOTIFICATION_OPERATION = "com.airplayer.NOTIFICATION_OPERATION";
/**
* <br>Broadcast intent action</br>
*/
public static final String NOTIFICATION_OPERATION_KEY = "com.airplayer.NOTIFICATION_OPERATION_KEY";
/**
* <br>Play state value</br>
*/
public static final int PLAY_STATE_PLAY = 0;
/**
* <br>Play state value</br>
*/
public static final int PLAY_STATE_PAUSE = 1;
/**
* <br>Notification operation broadcast intent extra</br>
*/
public static final int NOTIFICATION_OPERATION_PREVIOUS = 5;
public static final int NOTIFICATION_OPERATION_PLAY_PAUSE = 0;
public static final int NOTIFICATION_OPERATION_NEXT = 2;
/**
* <br>Play mode value</br>
*/
public static final int PLAY_LIST_MODE = 0;
public static final int LOOP_LIST_MODE = 1;
public static final int SINGLE_SONG_LOOP_MODE = 2;
/**
* <br>Binder</br>
*/
private PlayerControlBinder mBinder = new PlayerControlBinder();
/**
* <br>Media player</br>
*/
private MediaPlayer mPlayer;
/**
* audio effect
*/
private Equalizer mEqualizer;
private BassBoost mBassBoost;
/**
* <br>Play list</br>
*/
private List<Song> mPlayList = new ArrayList<>();
/**
* <br>Position of song playing in { @see mPlayList }</br>
*/
private int mPosition;
/**
* <br>Position of last song played in { @see mPlayList }</br>
*/
private int lastPosition;
/**
* <br>Song instance of playing song</br>
*/
private Song songPlaying;
/**
* <br>Play Mode</br>
*/
private int mPlayMode = PLAY_LIST_MODE;
/**
* <br>Value to control pause actions</br>
*/
private boolean pause = false;
/**
* <br>Value to control shuffle play mode</br>
*/
private boolean shuffle = false;
/**
* <br>Notification { @see AirNotification }</br>
*/
private AirNotification notification;
/**
* <br>Receiver for notification operation</br>
*/
private PlayMusicReceiver playMusicReceiver;
@Override
public void onCreate() {
super.onCreate();
// ===== create MediaPlayer =====
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (songPlaying != null) {
songPlaying.addFreqOne();
}
if (mPlayMode != SINGLE_SONG_LOOP_MODE) {
if (shuffle) {
mPosition = (int) Math.round(Math.random() * (mPlayList.size() - 1));
} else {
nextPosition();
if (mPosition == 0 && mPlayMode == PLAY_LIST_MODE) {
play();
mBinder.pauseMusic();
return;
}
}
}
play();
}
});
// ===== create Equalizer =====
// if (!isEmulatorByImei(getApplicationContext())) {
//
// }
mEqualizer = new Equalizer(0, mPlayer.getAudioSessionId());
mEqualizer.setEnabled(true);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
int genres = sp.getInt(EqualizerFragment.EQUALIZER_GENRES, 0);
if (genres < mEqualizer.getNumberOfPresets()) {
mEqualizer.usePreset((short) genres);
} else {
for (short i = 0; i < mEqualizer.getNumberOfBands(); i++) {
mEqualizer.setBandLevel(i, (short) sp.getInt(EqualizerFragment.EQUALIZER_USER_BAND + i, 0));
}
}
mBassBoost = new BassBoost(0, mPlayer.getAudioSessionId());
mBassBoost.setStrength((short) sp.getInt(EqualizerFragment.BASS_BOOST, 0));
// ===== register Receiver =====
playMusicReceiver = new PlayMusicReceiver();
IntentFilter filter = new IntentFilter(NOTIFICATION_OPERATION);
filter.addAction(Intent.ACTION_HEADSET_PLUG);
registerReceiver(playMusicReceiver, filter);
// ===== clear notification =====
notification = new AirNotification(this);
notification.cancel();
Log.d(TAG, "service create");
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
unregisterReceiver(playMusicReceiver);
mPlayer.release();
if (mEqualizer != null) {
mEqualizer.release();
mBassBoost.release();
}
notification.cancel();
super.onDestroy();
Log.d(TAG, "service destroy");
}
public class PlayerControlBinder extends Binder {
public void playMusic(int position, List<Song> playList) {
mPosition = position;
mPlayList = playList;
lastPosition = mPosition - 1;
play();
}
public void resumeMusic() {
if (mPlayer != null) {
songPlaying.setPause(false);
mPlayer.start();
pause = false;
Intent intent = new Intent(PLAY_STATE_CHANGE);
intent.putExtra(PLAY_STATE_KEY, PLAY_STATE_PLAY);
sendBroadcast(intent);
notification.push(songPlaying);
}
}
public void pauseMusic() {
if (mPlayer != null && songPlaying != null && !pause) {
songPlaying.setPause(true);
mPlayer.pause();
pause = true;
Intent intent = new Intent(PLAY_STATE_CHANGE);
intent.putExtra(PLAY_STATE_KEY, PLAY_STATE_PAUSE);
sendBroadcast(intent);
notification.push(songPlaying);
}
}
public void previousMusic() {
previousPosition();
play();
}
public void nextMusic() {
nextPosition();
play();
}
public float getProgress() {
return ((float)mPlayer.getCurrentPosition()) / ((float)mPlayer.getDuration());
}
public void setProgress(double p) {
mPlayer.seekTo((int) (mPlayer.getDuration() * p));
}
public void setPlayMode(int mode) {
mPlayMode = mode;
}
public int getPlayMode() {
return mPlayMode;
}
public void setShuffle(boolean switcher) {
shuffle = switcher;
}
public boolean isShuffle() {
return shuffle;
}
public List<Song> getPlayList() { return mPlayList; }
public Song getSongPlaying() { return songPlaying; }
public boolean isPlaying() { return mPlayer.isPlaying() || pause; }
public boolean isPause() { return pause; }
public int getPosition() { return mPosition; }
// ============= Audio Effect =============
public Equalizer getEqualizer() { return mEqualizer; }
public BassBoost getBassBoost() { return mBassBoost; }
}
private void play() {
try {
if (songPlaying != null) {
songPlaying.setPause(false);
songPlaying.setPlay(false);
}
songPlaying = mPlayList.get(mPosition);
songPlaying.setPlay(true);
songPlaying.setPause(false);
pause = false;
mPlayer.reset();
mPlayer.setDataSource(songPlaying.getPath());
mPlayer.prepare();
mPlayer.start();
Intent intent = new Intent(PLAY_STATE_CHANGE);
intent.putExtra(PLAY_STATE_KEY, PLAY_STATE_PLAY);
sendBroadcast(intent);
notification.push(songPlaying);
} catch (IOException e) {
Log.e(TAG, "fail to set data source of player", e);
}
}
private void nextPosition() {
lastPosition = mPosition;
if (shuffle) {
mPosition = (int) Math.round(Math.random() * (mPlayList.size() - 1));
} else {
mPosition++;
if (mPosition >= mPlayList.size()) {
mPosition = 0;
}
}
}
private void previousPosition() {
if (mPlayer != null) {
float max = 100;
float progressInPercent = ((float)mPlayer.getCurrentPosition())
/ ((float)mPlayer.getDuration());
if (max * progressInPercent < 10) {
if (lastPosition != -1) {
mPosition = lastPosition;
lastPosition = mPosition - 1;
}
}
}
}
/**
* <br>Receive broadcast sent when user operating at notification</br>
*/
private class PlayMusicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case NOTIFICATION_OPERATION:
onNotificationActionsReceive(intent);
break;
case Intent.ACTION_HEADSET_PLUG:
onHeadsetPlugActionReceive(intent);
break;
}
}
}
private void onNotificationActionsReceive(Intent intent) {
switch (intent.getIntExtra(NOTIFICATION_OPERATION_KEY, -1)) {
case NOTIFICATION_OPERATION_PREVIOUS:
previousPosition();
play();
break;
case NOTIFICATION_OPERATION_PLAY_PAUSE:
if (pause) {
mBinder.resumeMusic();
} else {
mBinder.pauseMusic();
}
break;
case NOTIFICATION_OPERATION_NEXT:
nextPosition();
play();
break;
default:
break;
}
}
private void onHeadsetPlugActionReceive(Intent intent) {
if (intent.getIntExtra("state", -1) == 0) {
mBinder.pauseMusic();
if (mBassBoost != null) {
mBassBoost.setEnabled(false);
}
} else {
if (mBassBoost != null) {
mBassBoost.setEnabled(true);
}
}
}
private static boolean isEmulatorByImei(Context context){
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId();
return (imei == null || imei.equals("000000000000000"));
}
}